Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / tests / afscp.c
1 #include <afsconfig.h>
2 #include <afs/param.h>
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <sys/socket.h>
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <sys/select.h>
14 #include <sys/stat.h>
15 #include <netdb.h>
16
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>
24
25 #include <afs/afs_consts.h>
26
27 /*#include <rx/rxkad.h>*/
28 #include <rx/rx_null.h>
29 #include <rx/rx_prototypes.h>
30
31 /*#include <krb.h>*/
32 #include <afs/com_err.h>
33
34 struct VenusFid {
35 afs_int32 Cell;
36 struct AFSFid Fid;
37 };
38
39 int
40 statfile(char *path, char *cellname, afs_uint32 * server, struct AFSFid *f)
41 {
42
43 struct ViceIoctl v;
44 struct VenusFid vf;
45 afs_int32 srvbuf[AFS_MAXHOSTS];
46 int code;
47
48 if (!strncmp(path, "@afs:", 5)) {
49 char *pdup, *p;
50 struct hostent *he;
51
52 pdup = strdup(path);
53 strtok(pdup, ":");
54
55 if (!(p = strtok(NULL, ":"))) {
56 free(pdup);
57 return -1;
58 }
59 strncpy(cellname, p, MAXCELLCHARS);
60
61 if (!(p = strtok(NULL, ":"))) {
62 free(pdup);
63 return -1;
64 }
65 he = gethostbyname(p);
66 if (!he) {
67 printf("Unknown host %s\n", p);
68 free(pdup);
69 return -1;
70 }
71 memcpy(server, he->h_addr, he->h_length);
72
73 if (!(p = strtok(NULL, ":"))) {
74 free(pdup);
75 return -1;
76 }
77 f->Volume = atoi(p);
78
79 if (!(p = strtok(NULL, ":"))) {
80 free(pdup);
81 return -1;
82 }
83 f->Vnode = atoi(p);
84
85 if (!(p = strtok(NULL, ":"))) {
86 free(pdup);
87 return -1;
88 }
89 f->Unique = atoi(p);
90
91 if (strtok(NULL, ":")) {
92 printf("Too much extra stuff after @afs:...\n");
93 free(pdup);
94 return -1;
95 }
96
97 return 0;
98 }
99
100 v.in = 0;
101 v.in_size = 0;
102 v.out = cellname;
103 v.out_size = MAXCELLCHARS;
104 if ((code = pioctl(path, VIOC_FILE_CELL_NAME, &v, 1)))
105 return code;
106
107 v.out = (char *)&vf;
108 v.out_size = sizeof(struct VenusFid);
109 if ((code = pioctl(path, VIOCGETFID, &v, 1)))
110 return code;
111 memcpy(f, &vf.Fid, sizeof(struct AFSFid));
112
113 v.out = (char *)srvbuf;
114 v.out_size = sizeof(srvbuf);
115 if ((code = pioctl(path, VIOCWHEREIS, &v, 1)))
116 return code;
117 if (v.out_size <= sizeof(afs_int32))
118 return EINVAL;
119
120 memcpy(server, srvbuf, sizeof(afs_int32));
121 return 0;
122 }
123
124
125 struct rx_securityClass *sc;
126
127 extern int
128 start_cb_server(void)
129 {
130 struct rx_service *s;
131
132 sc = rxnull_NewServerSecurityObject();
133 s = rx_NewService(0, 1, "afs", &sc, 1, RXAFSCB_ExecuteRequest);
134 if (!s)
135 return 1;
136 rx_StartServer(0);
137 return 0;
138 }
139
140
141 /*extern int rx_socket;*/
142 extern unsigned short rx_port;
143 int
144 do_rx_Init(void)
145 {
146 struct sockaddr_in s;
147 int len;
148
149 if (rx_Init(0)) {
150 fprintf(stderr, "Cannot initialize rx\n");
151 return 1;
152 }
153
154 len = sizeof(struct sockaddr_in);
155 if (getsockname(rx_socket, (struct sockaddr *)&s, (socklen_t *)&len)) {
156 perror("getsockname");
157 return 1;
158 }
159 rx_port = ntohs(s.sin_port);
160
161 return 0;
162 }
163
164 struct rx_securityClass *
165 get_sc(char *cellname)
166 {
167 #if 0
168 char realm[REALM_SZ];
169 CREDENTIALS c;
170 #endif
171
172 return rxnull_NewClientSecurityObject();
173 #if 0
174
175 ucstring(realm, cellname, REALM_SZ);
176
177 if (krb_get_cred("afs", "", realm, &c)) {
178 if (get_ad_tkt("afs", "", realm, DEFAULT_TKT_LIFE)) {
179 return NULL;
180 } else {
181 if (krb_get_cred("afs", "", realm, &c)) {
182 return NULL;
183 }
184 }
185 }
186
187 return rxkad_NewClientSecurityObject(rxkad_clear, c.session, c.kvno,
188 c.ticket_st.length, c.ticket_st.dat);
189 #endif
190 }
191
192 #define scindex_NULL 0
193 #define scindex_RXKAD 2
194
195 #define scindex scindex_RXKAD
196 int
197 main(int argc, char **argv)
198 {
199 char scell[MAXCELLCHARS], dcell[MAXCELLCHARS];
200 afs_uint32 ssrv, dsrv;
201 char *databuffer, *srcf = NULL, *destd = NULL, *destf = NULL, *destpath = NULL;
202 struct stat statbuf;
203
204 struct AFSStoreStatus sst;
205 struct AFSFetchStatus fst, dfst;
206 struct AFSVolSync vs;
207 struct AFSCallBack scb, dcb;
208 struct AFSFid sf, dd, df;
209
210 int filesz = 0;
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;
220 int sleeptime = 0;
221
222 struct AFSCBFids theFids;
223 struct AFSCBs theCBs;
224
225
226 blksize = 8 * 1024;
227
228 while ((ch = getopt(argc, argv, "iouUb:s:")) != -1) {
229 switch (ch) {
230 case 'b':
231 blksize = atoi(optarg);
232 break;
233 case 'i':
234 slcl = 1;
235 break;
236 case 'o':
237 dlcl = 1;
238 break;
239 case 's':
240 sleeptime = atoi(optarg);
241 break;
242 case 'u':
243 unauth = 1;
244 break;
245 case 'U':
246 unlock = 1;
247 break;
248 default:
249 printf("Unknown option '%c'\n", ch);
250 exit(1);
251 }
252 }
253
254
255 if (argc - optind + unlock < 2) {
256 fprintf(stderr,
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");
266 exit(1);
267 }
268 srcf = argv[optind++];
269 if (!unlock) {
270 destpath = argv[optind++];
271 destd = strdup(destpath);
272 if (!destd) {
273 perror("strdup");
274 exit(1);
275 }
276 if ((destf = strrchr(destd, '/'))) {
277 *destf++ = 0;
278 } else {
279 destf = destd;
280 destd = ".";
281 }
282 } else if (slcl) {
283 fprintf(stderr, "-i and -U cannot be used together\n");
284 }
285
286 if (!slcl && statfile(srcf, scell, &ssrv, &sf)) {
287 fprintf(stderr, "Cannot get attributes of %s\n", srcf);
288 exit(1);
289 }
290 if (!unlock && !dlcl && statfile(destd, dcell, &dsrv, &dd)) {
291 fprintf(stderr, "Cannot get attributes of %s\n", destd);
292 exit(1);
293 }
294
295 if ((databuffer = malloc(blksize)) == NULL) {
296 perror("malloc");
297 exit(1);
298 }
299
300 if (do_rx_Init())
301 exit(1);
302
303 if (start_cb_server()) {
304 printf("Cannot start callback service\n");
305 goto Fail_rx;
306 }
307
308 if (!slcl) {
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); */
314 }
315 sscindex = scindex_NULL;
316
317 if ((sconn =
318 rx_NewConnection(ssrv, htons(AFSCONF_FILEPORT), 1, ssc,
319 sscindex))
320 == NULL) {
321 struct in_addr s;
322 s.s_addr = ssrv;
323 printf("Cannot initialize rx connection to source server (%s)\n",
324 inet_ntoa(s));
325 goto Fail_sc;
326 }
327 }
328
329 if (!dlcl && !unlock) {
330 if (!slcl && ssrv == dsrv) {
331 dconn = sconn;
332 dsc = NULL;
333 } else {
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); */
340 }
341 dscindex = scindex_NULL;
342 } else {
343 dsc = ssc;
344 dscindex = sscindex;
345 }
346
347 if ((dconn =
348 rx_NewConnection(dsrv, htons(AFSCONF_FILEPORT), 1, dsc,
349 dscindex))
350 == NULL) {
351 struct in_addr s;
352 s.s_addr = dsrv;
353 printf
354 ("Cannot initialize rx connection to dest server (%s)\n",
355 inet_ntoa(s));
356 goto Fail_sconn;
357 }
358 }
359 }
360
361
362 memset(&sst, 0, sizeof(struct AFSStoreStatus));
363
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);
369 if (dfd < 0) {
370 fprintf(stderr, "Cannot open %s (%s)\n", destpath,
371 afs_error_message(errno));
372 goto Fail_dconn;
373 }
374 } else if (dfd < 0) {
375 fprintf(stderr, "Cannot open %s (%s)\n", destpath,
376 afs_error_message(errno));
377 goto Fail_dconn;
378 }
379 } else if (!unlock) {
380 if ((code =
381 RXAFS_CreateFile(dconn, &dd, destf, &sst, &df, &fst, &dfst, &dcb,
382 &vs))) {
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",
387 destpath);
388 else
389 code = 0;
390 } else {
391 printf("Cannot create %s (%s)\n", destpath,
392 afs_error_message(code));
393 if (code)
394 goto Fail_dconn;
395 }
396 }
397 }
398
399 if (slcl) {
400 sfd = open(srcf, O_RDONLY, 0);
401 if (sfd < 0) {
402 fprintf(stderr, "Cannot open %s (%s)\n", srcf,
403 afs_error_message(errno));
404 goto Fail_dconn;
405 }
406 if (fstat(sfd, &statbuf) < 0) {
407 fprintf(stderr, "Cannot stat %s (%s)\n", srcf,
408 afs_error_message(errno));
409 close(sfd);
410 goto Fail_dconn;
411 }
412 } else {
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));
416 goto Fail_dconn;
417 }
418 }
419
420
421
422 if (slcl) {
423 filesz = statbuf.st_size;
424 } else {
425 filesz = fst.Length;
426 }
427
428 printcallerrs = 0;
429 fetchcode = 0;
430 storecode = 0;
431 if (!slcl && !unlock)
432 scall = rx_NewCall(sconn);
433 if (!dlcl && !unlock)
434 dcall = rx_NewCall(dconn);
435 gettimeofday(&start, NULL);
436 if (unlock) {
437 if (fst.lockCount) {
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));
442 }
443 } else {
444 printf("No locks for %s\n", srcf);
445 }
446 fetchcode = code;
447 goto Finish;
448 }
449
450 if (!slcl) {
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));
454 goto Fail_call;
455 }
456 }
457
458 if (!dlcl) {
459 if (slcl) {
460 sst.Mask = AFS_SETMODTIME | AFS_SETMODE;
461 sst.ClientModTime = statbuf.st_mtime;
462 sst.UnixModeBits =
463 statbuf.st_mode & ~(S_IFMT | S_ISUID | S_ISGID);
464 } else {
465 sst.Mask = AFS_SETMODTIME | AFS_SETMODE;
466 sst.ClientModTime = fst.ClientModTime;
467 sst.UnixModeBits =
468 fst.UnixModeBits & ~(S_IFMT | S_ISUID | S_ISGID);
469 }
470
471 if ((code =
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));
475 goto Fail_call;
476 }
477 }
478
479 if (slcl) {
480 bytesremaining = statbuf.st_size;
481 } else {
482 rx_Read(scall, (char *)&bytesremaining, sizeof(afs_int32));
483 bytesremaining = ntohl(bytesremaining);
484 }
485
486 while (bytesremaining > 0) {
487 /*printf("%d bytes remaining\n",bytesremaining); */
488 if (slcl) {
489 if ((bytes =
490 read(sfd, databuffer, min(blksize, bytesremaining))) <= 0) {
491 fetchcode = errno;
492 break;
493 }
494 } else {
495 if ((bytes =
496 rx_Read(scall, databuffer,
497 min(blksize, bytesremaining))) <= 0)
498 break;
499 }
500 if (dlcl) {
501 if (write(dfd, databuffer, bytes) != bytes) {
502 storecode = errno;
503 break;
504 }
505 } else {
506 if (rx_Write(dcall, databuffer, bytes) != bytes)
507 break;
508 }
509
510 if (sleeptime > 0) {
511 #ifdef AFS_PTHREAD_ENV
512 sleep(sleeptime);
513 #else
514 IOMGR_Sleep(sleeptime);
515 #endif
516 /* only sleep once */
517 sleeptime = 0;
518 }
519
520 bytesremaining -= bytes;
521 /*printf("%d bytes copied\n",bytes); */
522 }
523
524
525 if (bytesremaining > 0) {
526 printf("Some network error occured while copying data\n");
527 goto Fail_call;
528 }
529
530 if (!slcl)
531 fetchcode = EndRXAFS_FetchData(scall, &fst, &scb, &vs);
532 if (!dlcl)
533 storecode = EndRXAFS_StoreData(dcall, &fst, &vs);
534 printcallerrs = 1;
535 Fail_call:
536
537 if (slcl) {
538 if (close(sfd) && !fetchcode)
539 fetchcode = errno;
540 } else {
541 fetchcode = rx_EndCall(scall, fetchcode);
542 }
543 if (fetchcode)
544 printf("Error returned from fetch: %s\n", afs_error_message(fetchcode));
545
546 if (dlcl) {
547 if (close(dfd) && !storecode)
548 storecode = errno;
549 } else if (!unlock) {
550 storecode = rx_EndCall(dcall, storecode);
551 }
552 if (storecode)
553 printf("Error returned from store: %s\n", afs_error_message(storecode));
554 Finish:
555 gettimeofday(&finish, NULL);
556
557 if (!slcl) {
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));
566 }
567
568 if (!dlcl) {
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));
577 }
578
579 if (code == 0)
580 code = storecode;
581 if (code == 0)
582 code = fetchcode;
583
584 Fail_dconn:
585 if (!dlcl && !unlock && (slcl || dconn != sconn))
586 rx_DestroyConnection(dconn);
587 Fail_sconn:
588 if (!slcl)
589 rx_DestroyConnection(sconn);
590 Fail_sc:
591 if (dsc && dsc != ssc)
592 RXS_Close(dsc);
593 if (ssc)
594 RXS_Close(ssc);
595 Fail_rx:
596 rx_Finalize();
597
598 free(databuffer);
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));
604 } else {
605 printf("Copied %d bytes in %d seconds\n", filesz,
606 (int)(finish.tv_sec - start.tv_sec));
607 }
608
609 size = filesz / 1024.0;
610 time =
611 finish.tv_sec - start.tv_sec + (finish.tv_usec -
612 start.tv_usec) / 1e+06;
613 rate = size / time;
614 printf("Transfer rate %g Kbytes/sec\n", rate);
615
616 }
617
618 exit(code != 0);
619 }