8 #include <sys/socket.h>
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
13 #include <sys/select.h>
17 #include <afs/afsint.h>
18 #define FSINT_COMMON_XG 1
19 #include <afs/afscbint.h>
20 #include <sys/ioctl.h>
21 #include <afs/venus.h>
22 #include <afs/cellconfig.h>
23 #include <afs/sys_prototypes.h>
25 #include <afs/afs_consts.h>
27 /*#include <rx/rxkad.h>*/
28 #include <rx/rx_null.h>
29 #include <rx/rx_prototypes.h>
32 #include <afs/com_err.h>
40 statfile(char *path
, char *cellname
, afs_uint32
* server
, struct AFSFid
*f
)
45 afs_int32 srvbuf
[AFS_MAXHOSTS
];
48 if (!strncmp(path
, "@afs:", 5)) {
55 if (!(p
= strtok(NULL
, ":"))) {
59 strncpy(cellname
, p
, MAXCELLCHARS
);
61 if (!(p
= strtok(NULL
, ":"))) {
65 he
= gethostbyname(p
);
67 printf("Unknown host %s\n", p
);
71 memcpy(server
, he
->h_addr
, he
->h_length
);
73 if (!(p
= strtok(NULL
, ":"))) {
79 if (!(p
= strtok(NULL
, ":"))) {
85 if (!(p
= strtok(NULL
, ":"))) {
91 if (strtok(NULL
, ":")) {
92 printf("Too much extra stuff after @afs:...\n");
103 v
.out_size
= MAXCELLCHARS
;
104 if ((code
= pioctl(path
, VIOC_FILE_CELL_NAME
, &v
, 1)))
108 v
.out_size
= sizeof(struct VenusFid
);
109 if ((code
= pioctl(path
, VIOCGETFID
, &v
, 1)))
111 memcpy(f
, &vf
.Fid
, sizeof(struct AFSFid
));
113 v
.out
= (char *)srvbuf
;
114 v
.out_size
= sizeof(srvbuf
);
115 if ((code
= pioctl(path
, VIOCWHEREIS
, &v
, 1)))
117 if (v
.out_size
<= sizeof(afs_int32
))
120 memcpy(server
, srvbuf
, sizeof(afs_int32
));
125 struct rx_securityClass
*sc
;
128 start_cb_server(void)
130 struct rx_service
*s
;
132 sc
= rxnull_NewServerSecurityObject();
133 s
= rx_NewService(0, 1, "afs", &sc
, 1, RXAFSCB_ExecuteRequest
);
141 /*extern int rx_socket;*/
142 extern unsigned short rx_port
;
146 struct sockaddr_in s
;
150 fprintf(stderr
, "Cannot initialize rx\n");
154 len
= sizeof(struct sockaddr_in
);
155 if (getsockname(rx_socket
, (struct sockaddr
*)&s
, (socklen_t
*)&len
)) {
156 perror("getsockname");
159 rx_port
= ntohs(s
.sin_port
);
164 struct rx_securityClass
*
165 get_sc(char *cellname
)
168 char realm
[REALM_SZ
];
172 return rxnull_NewClientSecurityObject();
175 ucstring(realm
, cellname
, REALM_SZ
);
177 if (krb_get_cred("afs", "", realm
, &c
)) {
178 if (get_ad_tkt("afs", "", realm
, DEFAULT_TKT_LIFE
)) {
181 if (krb_get_cred("afs", "", realm
, &c
)) {
187 return rxkad_NewClientSecurityObject(rxkad_clear
, c
.session
, c
.kvno
,
188 c
.ticket_st
.length
, c
.ticket_st
.dat
);
192 #define scindex_NULL 0
193 #define scindex_RXKAD 2
195 #define scindex scindex_RXKAD
197 main(int argc
, char **argv
)
199 char scell
[MAXCELLCHARS
], dcell
[MAXCELLCHARS
];
200 afs_uint32 ssrv
, dsrv
;
201 char *databuffer
, *srcf
= NULL
, *destd
= NULL
, *destf
= NULL
, *destpath
= NULL
;
204 struct AFSStoreStatus sst
;
205 struct AFSFetchStatus fst
, dfst
;
206 struct AFSVolSync vs
;
207 struct AFSCallBack scb
, dcb
;
208 struct AFSFid sf
, dd
, df
;
211 int ch
, blksize
, bytesremaining
, bytes
;
212 struct timeval start
, finish
;
213 struct rx_securityClass
*ssc
= 0, *dsc
= 0;
214 int sscindex
, dscindex
;
215 struct rx_connection
*sconn
= NULL
, *dconn
= NULL
;
216 struct rx_call
*scall
= NULL
, *dcall
= NULL
;
217 int code
= 0, fetchcode
, storecode
, printcallerrs
= 0;
218 int slcl
= 0, dlcl
= 0, unlock
= 0;
219 int sfd
= 0, dfd
= 0, unauth
= 0;
222 struct AFSCBFids theFids
;
223 struct AFSCBs theCBs
;
228 while ((ch
= getopt(argc
, argv
, "iouUb:s:")) != -1) {
231 blksize
= atoi(optarg
);
240 sleeptime
= atoi(optarg
);
249 printf("Unknown option '%c'\n", ch
);
255 if (argc
- optind
+ unlock
< 2) {
257 "Usage: afscp [-i|-o]] [-b xfersz] [-s time] [-u] [-U] source [dest]\n");
258 fprintf(stderr
, " -b Set block size\n");
259 fprintf(stderr
, " -i Source is local (copy into AFS)\n");
260 fprintf(stderr
, " -o Dest is local (copy out of AFS)\n");
261 fprintf(stderr
, " -s Set the seconds to sleep before reading/writing data\n");
262 fprintf(stderr
, " -u Run unauthenticated\n");
263 fprintf(stderr
, " -U Send an unlock request for source. (dest path not required)\n");
264 fprintf(stderr
, "source and dest can be paths or specified as:\n");
265 fprintf(stderr
, " @afs:cellname:servername:volume:vnode:uniq\n");
268 srcf
= argv
[optind
++];
270 destpath
= argv
[optind
++];
271 destd
= strdup(destpath
);
276 if ((destf
= strrchr(destd
, '/'))) {
283 fprintf(stderr
, "-i and -U cannot be used together\n");
286 if (!slcl
&& statfile(srcf
, scell
, &ssrv
, &sf
)) {
287 fprintf(stderr
, "Cannot get attributes of %s\n", srcf
);
290 if (!unlock
&& !dlcl
&& statfile(destd
, dcell
, &dsrv
, &dd
)) {
291 fprintf(stderr
, "Cannot get attributes of %s\n", destd
);
295 if ((databuffer
= malloc(blksize
)) == NULL
) {
303 if (start_cb_server()) {
304 printf("Cannot start callback service\n");
309 sscindex
= scindex_RXKAD
;
310 if (unauth
|| (ssc
= get_sc(scell
)) == NULL
) {
311 ssc
= rxnull_NewClientSecurityObject();
312 sscindex
= scindex_NULL
;
313 /*printf("Cannot get authentication for cell %s; running unauthenticated\n", scell); */
315 sscindex
= scindex_NULL
;
318 rx_NewConnection(ssrv
, htons(AFSCONF_FILEPORT
), 1, ssc
,
323 printf("Cannot initialize rx connection to source server (%s)\n",
329 if (!dlcl
&& !unlock
) {
330 if (!slcl
&& ssrv
== dsrv
) {
334 if (slcl
|| strcmp(scell
, dcell
)) {
335 dscindex
= scindex_RXKAD
;
336 if (unauth
|| (dsc
= get_sc(dcell
)) == NULL
) {
337 dsc
= rxnull_NewClientSecurityObject();
338 dscindex
= scindex_NULL
;
339 /*printf("Cannot get authentication for cell %s; running unauthenticated\n", dcell); */
341 dscindex
= scindex_NULL
;
348 rx_NewConnection(dsrv
, htons(AFSCONF_FILEPORT
), 1, dsc
,
354 ("Cannot initialize rx connection to dest server (%s)\n",
362 memset(&sst
, 0, sizeof(struct AFSStoreStatus
));
364 if (dlcl
&& !unlock
) {
365 dfd
= open(destpath
, O_RDWR
| O_CREAT
| O_EXCL
, 0666);
366 if (dfd
< 0 && errno
== EEXIST
) {
367 printf("%s already exists, overwriting\n", destpath
);
368 dfd
= open(destpath
, O_RDWR
| O_TRUNC
, 0666);
370 fprintf(stderr
, "Cannot open %s (%s)\n", destpath
,
371 afs_error_message(errno
));
374 } else if (dfd
< 0) {
375 fprintf(stderr
, "Cannot open %s (%s)\n", destpath
,
376 afs_error_message(errno
));
379 } else if (!unlock
) {
381 RXAFS_CreateFile(dconn
, &dd
, destf
, &sst
, &df
, &fst
, &dfst
, &dcb
,
383 if (code
== EEXIST
) {
384 printf("%s already exits, overwriting\n", destpath
);
385 if (statfile(destpath
, dcell
, &dsrv
, &df
))
386 fprintf(stderr
, "Cannot get attributes of %s\n",
391 printf("Cannot create %s (%s)\n", destpath
,
392 afs_error_message(code
));
400 sfd
= open(srcf
, O_RDONLY
, 0);
402 fprintf(stderr
, "Cannot open %s (%s)\n", srcf
,
403 afs_error_message(errno
));
406 if (fstat(sfd
, &statbuf
) < 0) {
407 fprintf(stderr
, "Cannot stat %s (%s)\n", srcf
,
408 afs_error_message(errno
));
413 if ((code
= RXAFS_FetchStatus(sconn
, &sf
, &fst
, &scb
, &vs
))) {
414 printf("Cannot fetchstatus of %d.%d (%s)\n", sf
.Volume
, sf
.Vnode
,
415 afs_error_message(code
));
423 filesz
= statbuf
.st_size
;
431 if (!slcl
&& !unlock
)
432 scall
= rx_NewCall(sconn
);
433 if (!dlcl
&& !unlock
)
434 dcall
= rx_NewCall(dconn
);
435 gettimeofday(&start
, NULL
);
438 printf("Sending 1 unlock for %s (%d locks)\n", srcf
, fst
.lockCount
);
439 if ((code
= RXAFS_ReleaseLock(sconn
, &sf
, &vs
))) {
440 printf("Unable to unlock %s (%s)\n", srcf
,
441 afs_error_message(code
));
444 printf("No locks for %s\n", srcf
);
451 if ((code
= StartRXAFS_FetchData(scall
, &sf
, 0, filesz
))) {
452 printf("Unable to fetch data from %s (%s)\n", srcf
,
453 afs_error_message(code
));
460 sst
.Mask
= AFS_SETMODTIME
| AFS_SETMODE
;
461 sst
.ClientModTime
= statbuf
.st_mtime
;
463 statbuf
.st_mode
& ~(S_IFMT
| S_ISUID
| S_ISGID
);
465 sst
.Mask
= AFS_SETMODTIME
| AFS_SETMODE
;
466 sst
.ClientModTime
= fst
.ClientModTime
;
468 fst
.UnixModeBits
& ~(S_IFMT
| S_ISUID
| S_ISGID
);
472 StartRXAFS_StoreData(dcall
, &df
, &sst
, 0, filesz
, filesz
))) {
473 printf("Unable to store data to %s (%s)\n", destpath
,
474 afs_error_message(code
));
480 bytesremaining
= statbuf
.st_size
;
482 rx_Read(scall
, (char *)&bytesremaining
, sizeof(afs_int32
));
483 bytesremaining
= ntohl(bytesremaining
);
486 while (bytesremaining
> 0) {
487 /*printf("%d bytes remaining\n",bytesremaining); */
490 read(sfd
, databuffer
, min(blksize
, bytesremaining
))) <= 0) {
496 rx_Read(scall
, databuffer
,
497 min(blksize
, bytesremaining
))) <= 0)
501 if (write(dfd
, databuffer
, bytes
) != bytes
) {
506 if (rx_Write(dcall
, databuffer
, bytes
) != bytes
)
511 #ifdef AFS_PTHREAD_ENV
514 IOMGR_Sleep(sleeptime
);
516 /* only sleep once */
520 bytesremaining
-= bytes
;
521 /*printf("%d bytes copied\n",bytes); */
525 if (bytesremaining
> 0) {
526 printf("Some network error occured while copying data\n");
531 fetchcode
= EndRXAFS_FetchData(scall
, &fst
, &scb
, &vs
);
533 storecode
= EndRXAFS_StoreData(dcall
, &fst
, &vs
);
538 if (close(sfd
) && !fetchcode
)
541 fetchcode
= rx_EndCall(scall
, fetchcode
);
544 printf("Error returned from fetch: %s\n", afs_error_message(fetchcode
));
547 if (close(dfd
) && !storecode
)
549 } else if (!unlock
) {
550 storecode
= rx_EndCall(dcall
, storecode
);
553 printf("Error returned from store: %s\n", afs_error_message(storecode
));
555 gettimeofday(&finish
, NULL
);
558 theFids
.AFSCBFids_len
= 1;
559 theFids
.AFSCBFids_val
= &sf
;
560 theCBs
.AFSCBs_len
= 1;
561 theCBs
.AFSCBs_val
= &scb
;
562 scb
.CallBackType
= CB_DROPPED
;
563 if ((code
= RXAFS_GiveUpCallBacks(sconn
, &theFids
, &theCBs
)))
564 printf("Could not give up source callback: %s\n",
565 afs_error_message(code
));
569 theFids
.AFSCBFids_len
= 1;
570 theFids
.AFSCBFids_val
= &df
;
571 theCBs
.AFSCBs_len
= 1;
572 theCBs
.AFSCBs_val
= &dcb
;
573 dcb
.CallBackType
= CB_DROPPED
;
574 if ((code
= RXAFS_GiveUpCallBacks(dconn
, &theFids
, &theCBs
)))
575 printf("Could not give up target callback: %s\n",
576 afs_error_message(code
));
585 if (!dlcl
&& !unlock
&& (slcl
|| dconn
!= sconn
))
586 rx_DestroyConnection(dconn
);
589 rx_DestroyConnection(sconn
);
591 if (dsc
&& dsc
!= ssc
)
599 if (printcallerrs
&& !unlock
) {
600 double rate
, size
, time
;
601 if (finish
.tv_sec
== start
.tv_sec
) {
602 printf("Copied %d bytes in %d microseconds\n", filesz
,
603 (int)(finish
.tv_usec
- start
.tv_usec
));
605 printf("Copied %d bytes in %d seconds\n", filesz
,
606 (int)(finish
.tv_sec
- start
.tv_sec
));
609 size
= filesz
/ 1024.0;
611 finish
.tv_sec
- start
.tv_sec
+ (finish
.tv_usec
-
612 start
.tv_usec
) / 1e+06;
614 printf("Transfer rate %g Kbytes/sec\n", rate
);