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