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