afsio is a command to pipe data into or out of afs files
[openafs.git] / src / venus / afsio.c
1 /*
2  * Copyright (c) 2007, Hartmut Reuter,
3  * RZG, Max-Planck-Institut f. Plasmaphysik.
4  * All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  *   1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *   2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in
13  *      the documentation and/or other materials provided with the
14  *      distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <afsconfig.h>
29 #include <afs/param.h>
30
31 #include <stdio.h>
32 #include <setjmp.h>
33 #include <sys/types.h>
34 #include <string.h>
35 #include <ctype.h>
36 #ifdef AFS_NT40_ENV
37 #include <fcntl.h>
38 #else
39 #include <sys/param.h>
40 #include <sys/file.h>
41 #include <sys/ioctl.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <netdb.h>
46 #include <string.h>
47 #include <fcntl.h>
48 #endif
49 #include <sys/stat.h>
50 #include <errno.h>
51 #include <pwd.h>
52 #include <signal.h>
53 #include <afs/vice.h>
54 #include <afs/cmd.h>
55 #include <afs/auth.h>
56 #include <afs/cellconfig.h>
57 #include <afs/afsutil.h>
58 #include <rx/rx.h>
59 #include <rx/xdr.h>
60 #include <afs/venus.h>
61 #include <afs/afscbint.h>
62 #define FSINT_COMMON_XG 1
63 #include <afs/afsint.h>
64 #include <afs/vldbint.h>
65 #include <afs/vlserver.h>
66 #include <afs/volser.h>
67 #include <afs/ptint.h>
68 #include <afs/dir.h>
69 #include <afs/nfs.h>
70 #include <afs/ihandle.h>
71 #include <afs/namei_ops.h>
72 #include <afs/vnode.h>
73 #include <afs/com_err.h>
74 #ifdef HAVE_DIRENT_H
75 #include <dirent.h>
76 #endif
77 #ifdef HAVE_DIRECT_H
78 #include <direct.h>
79 #endif
80 #include <sys/time.h>
81 #include <netdb.h>
82 #ifdef AFS_DARWIN_ENV
83 #include <sys/malloc.h>
84 #else
85 #include <malloc.h>
86 #endif
87 #include <afs/errors.h>
88 #include <afs/sys_prototypes.h>
89 #include <des_prototypes.h>
90 #include <rx_prototypes.h>
91 #include "../rxkad/md5.h"
92 #define MAXHOSTS 13
93 #ifdef O_LARGEFILE
94 #define afs_stat        stat64
95 #define afs_fstat       fstat64
96 #define afs_open        open64
97 #else /* !O_LARGEFILE */
98 #define afs_stat        stat
99 #define afs_fstat       fstat
100 #define afs_open        open
101 #endif /* !O_LARGEFILE */
102 #ifdef AFS_PTHREAD_ENV
103 #include <assert.h>
104 pthread_key_t uclient_key;
105 #endif
106
107 int readFile(struct cmd_syndesc *as, void *);
108 int writeFile(struct cmd_syndesc *as, void *);
109 struct rx_connection *FindRXConnection(afs_uint32 host, u_short port, u_short service, struct rx_securityClass *securityObject, int serviceSecurityIndex);
110 struct cellLookup * FindCell(char *cellName);
111
112 char pnp[255];
113 int rxInitDone = 0;
114 static int verbose = 0;         /* Set if -verbose option given */
115 static int CBServiceNeeded = 0;
116 static struct timeval starttime, opentime, readtime, writetime;
117 afs_uint64 xfered=0, oldxfered=0;
118 static struct timeval now;
119 struct timezone Timezone;
120 static float seconds, datarate, oldseconds;
121 extern int rxInitDone;
122 afs_uint64 transid = 0;
123 afs_uint32 expires = 0;
124 afs_uint32 server_List[MAXHOSTSPERCELL];
125 char tmpstr[1024];
126 char tmpstr2[1024];
127 static struct ubik_client *uclient;
128 #define BUFFLEN 65536
129 #define WRITEBUFFLEN 1024*1024*64
130
131 afsUUID uuid;
132 MD5_CTX md5;
133 int md5sum = 0;
134
135 struct wbuf {
136     struct wbuf *next;
137     afs_uint32 offset;          /* offset inside the buffer */
138     afs_uint32 buflen;          /* total length == BUFFLEN */
139     afs_uint32 used;            /* bytes used inside buffer */
140     char buf[BUFFLEN];
141 };
142
143 struct connectionLookup {
144     afs_uint32 host;
145     u_short port;
146     struct rx_connection *conn;
147 };
148
149 struct cellLookup {
150     struct cellLookup *next;
151     struct afsconf_cell info;
152     struct rx_securityClass *sc[3];
153     afs_int32 scIndex;
154 };
155
156 struct dirLookup {
157     struct dirLookup *next;
158     struct dirLookup *prev;
159     afs_int32 host;
160     struct cellLookup *cell;
161     AFSFid fid;
162     char name[VL_MAXNAMELEN];
163 };
164
165 struct cellLookup *Cells = 0;
166 struct dirLookup  *Dirs = 0;
167 char cellFname[256];
168
169 #define MAX_HOSTS 256
170 static struct connectionLookup ConnLookup[MAX_HOSTS];
171 static int ConnLookupInitialized = 0;
172
173 struct FsCmdInputs PioctlInputs;
174 struct FsCmdOutputs PioctlOutputs;
175
176 void
177 printDatarate(void)
178 {
179     seconds = now.tv_sec + now.tv_usec *.000001
180         -opentime.tv_sec - opentime.tv_usec *.000001;
181     if ((seconds - oldseconds) > 30.) {
182         afs_int64 tmp;
183         tmp = xfered - oldxfered;
184         datarate = ((afs_uint32) (tmp >> 20)) / (seconds - oldseconds);
185         fprintf(stderr,"%llu MB transferred, present date rate = %.0f MB/sec.\n",
186                 xfered >> 20, datarate);
187         oldxfered = xfered;
188         oldseconds = seconds;
189     }
190 }
191
192 void
193 SetCellFname(char *name)
194 {
195     struct afsconf_dir *tdir;
196
197     strcpy((char *) &cellFname,"/afs/");
198     if (name)
199         strcat((char *) &cellFname, name);
200     else {
201         tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
202         afsconf_GetLocalCell(tdir, &cellFname[5], MAXCELLCHARS);
203     }
204 }
205
206 afs_int32
207 main (int argc, char **argv)
208 {
209     afs_int32 code;
210     struct cmd_syndesc *ts;
211
212     strcpy(pnp, argv[0]);
213
214 #ifdef AFS_PTHREAD_ENV
215     assert(pthread_key_create(&uclient_key, NULL) == 0);
216 #endif
217     ts = cmd_CreateSyntax("read", readFile, CMD_REQUIRED,
218                           "read a file from AFS");
219     cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename");
220     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
221     cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
222     cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
223
224     ts = cmd_CreateSyntax("fidread", readFile, CMD_REQUIRED,
225                           "read on a non AFS-client a file from AFS");
226     cmd_IsAdministratorCommand(ts);
227     cmd_AddParm(ts, "-fid", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
228     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
229     cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
230     cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
231
232     ts = cmd_CreateSyntax("write", writeFile, CMD_REQUIRED,
233                           "write a file into AFS");
234     cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
235     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
236     cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
237     cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
238     cmd_AddParm(ts, "-synthesize", CMD_SINGLE, CMD_OPTIONAL, "create data pattern of specified length instead reading from stdin");
239
240     ts = cmd_CreateSyntax("fidwrite", writeFile, CMD_REQUIRED,
241                           "write a file into AFS");
242     cmd_IsAdministratorCommand(ts);
243     cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
244     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
245     cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
246     cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
247
248     ts = cmd_CreateSyntax("append", writeFile, CMD_REQUIRED,
249                           "append to a file in AFS");
250     cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
251     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
252     cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
253
254     ts = cmd_CreateSyntax("fidappend", writeFile, CMD_REQUIRED,
255                           "append to a file in AFS");
256     cmd_IsAdministratorCommand(ts);
257     cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
258     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
259     cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
260
261     code = cmd_Dispatch(argc, argv);
262     exit (0);
263 }
264
265 AFS_UNUSED
266 afs_int32
267 HandleLocalAuth(struct rx_securityClass **sc[3], afs_int32 *scIndex)
268 {
269     static struct afsconf_dir *tdir = NULL;
270     struct ktc_principal sname;
271     struct ktc_token ttoken;
272     int kvno;
273     struct ktc_encryptionKey key;
274     afs_uint32 host = 0;
275     char *cell;
276     afs_int32 code;
277
278     tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
279     if (!tdir) {
280         fprintf(stderr,"Could not open configuration directory: %s.\n",
281                 AFSDIR_SERVER_ETC_DIRPATH);
282         return -1;
283     }
284     cell = tdir->cellName;
285     strcpy(sname.cell, cell);
286     sname.instance[0] = 0;
287     strcpy(sname.name, "afs");
288     code=afsconf_GetLatestKey(tdir, &kvno, &key);
289     if (code) {
290         fprintf(stderr,"afsconf_GetLatestKey returned %d\n", code);
291         return -1;
292     }
293     ttoken.kvno = kvno;
294     des_init_random_number_generator(ktc_to_cblock(&key));
295     code = des_random_key(ktc_to_cblock(&ttoken.sessionKey));
296     if (code) {
297         fprintf(stderr,"des_random_key returned %d\n", code);
298         return -1;
299     }
300     ttoken.ticketLen = MAXKTCTICKETLEN;
301     code = tkt_MakeTicket(ttoken.ticket, &ttoken.ticketLen, &key,
302                           AUTH_SUPERUSER, "", sname.cell,
303                           0, 0xffffffff,
304                           &ttoken.sessionKey, host,
305                           sname.name, sname.instance);
306     if (code)
307         *scIndex = 0;
308     else {
309         *scIndex = 2;
310         *sc[2] = (struct rx_securityClass *)
311             rxkad_NewClientSecurityObject(rxkad_clear,
312                                           &ttoken.sessionKey, ttoken.kvno,
313                                           ttoken.ticketLen, ttoken.ticket);
314     }
315     if (*scIndex == 0)
316         *sc[0] = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
317     return 0;
318 }
319
320 afs_int32
321 AFS_Lookup(struct rx_connection *conn, AFSFid *dirfid, char *name,
322            AFSFid *outfid, AFSFetchStatus *outstatus, AFSFetchStatus
323            *dirstatus, AFSCallBack *callback, AFSVolSync *sync)
324 {
325     afs_int32 code = VBUSY;
326     while (code == VBUSY) {
327         code = RXAFS_Lookup(conn, dirfid, name, outfid, outstatus, dirstatus,
328                             callback, sync);
329         if (code == VBUSY) {
330             fprintf(stderr, "waiting for busy AFS volume %u.\n",
331                     dirfid->Volume);
332 #ifdef AFS_PTHREAD_ENV
333             sleep(10);
334 #else
335             IOMGR_Sleep(10);
336 #endif
337         }
338     }
339     return code;
340 }
341
342 afs_int32
343 AFS_FetchStatus(struct rx_connection *conn, AFSFid *fid, AFSFetchStatus
344                 *Status, AFSCallBack *callback, AFSVolSync *sync)
345 {
346     afs_int32 code = VBUSY;
347
348     while (code == VBUSY) {
349         code = RXAFS_FetchStatus(conn, fid, Status, callback, sync);
350         if (code == VBUSY) {
351             fprintf(stderr, "waiting for busy AFS volume %u.\n",
352                     fid->Volume);
353 #ifdef AFS_PTHREAD_ENV
354             sleep(10);
355 #else
356             IOMGR_Sleep(10);
357 #endif
358         }
359     }
360     return code;
361 }
362
363 afs_int32
364 StartAFS_FetchData(struct rx_call *call, AFSFid *fid, afs_int32 pos,
365                    afs_int32 len)
366 {
367     afs_int32 code = VBUSY;
368     while (code == VBUSY) {
369         code = StartRXAFS_FetchData (call, fid, pos, len);
370         if (code == VBUSY) {
371             fprintf(stderr, "waiting for busy AFS volume %u.\n",
372                     fid->Volume);
373 #ifdef AFS_PTHREAD_ENV
374             sleep(10);
375 #else
376             IOMGR_Sleep(10);
377 #endif
378         }
379     }
380     return code;
381 }
382
383 afs_int32
384 StartAFS_FetchData64(struct rx_call *call, AFSFid *fid, afs_int64 pos,
385                      afs_int64 len)
386 {
387     afs_int32 code = VBUSY;
388     while (code == VBUSY) {
389         code = StartRXAFS_FetchData64 (call, fid, pos, len);
390         if (code == VBUSY) {
391             fprintf(stderr, "waiting for busy AFS volume %u.\n",
392                     fid->Volume);
393 #ifdef AFS_PTHREAD_ENV
394             sleep(10);
395 #else
396             IOMGR_Sleep(10);
397 #endif
398         }
399     }
400     return code;
401 }
402
403 afs_int32
404 StartAFS_StoreData(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
405                    afs_int32 pos, afs_int32 len, afs_int32 len2)
406 {
407     afs_int32 code = VBUSY;
408     while (code == VBUSY) {
409         code = StartRXAFS_StoreData (call, fid, status, pos, len, len2);
410         if (code == VBUSY) {
411             fprintf(stderr, "waiting for busy AFS volume %u.\n",
412                     fid->Volume);
413 #ifdef AFS_PTHREAD_ENV
414             sleep(10);
415 #else
416             IOMGR_Sleep(10);
417 #endif
418         }
419     }
420     return code;
421 }
422
423 afs_uint32
424 StartAFS_StoreData64(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
425                      afs_int64 pos, afs_int64 len, afs_int64 len2)
426 {
427     afs_int32 code = VBUSY;
428     while (code == VBUSY) {
429         code = StartRXAFS_StoreData64 (call, fid, status, pos, len, len2);
430         if (code == VBUSY) {
431             fprintf(stderr, "waiting for busy AFS volume %u.\n",
432                     fid->Volume);
433 #ifdef AFS_PTHREAD_ENV
434             sleep(10);
435 #else
436             IOMGR_Sleep(10);
437 #endif
438         }
439     }
440     return code;
441 }
442
443 afs_int32
444 SRXAFSCB_CallBack(struct rx_call *rxcall, AFSCBFids *Fids_Array,
445                   AFSCBs *CallBack_Array)
446 {
447     return 0;
448 }
449
450 afs_int32
451 SRXAFSCB_InitCallBackState(struct rx_call *rxcall)
452 {
453     return 0;
454 }
455
456 afs_int32
457 SRXAFSCB_Probe(struct rx_call *rxcall)
458 {
459     return 0;
460 }
461
462 afs_int32
463 SRXAFSCB_GetCE(struct rx_call *rxcall,
464                afs_int32 index,
465                AFSDBCacheEntry * ce)
466 {
467     return(0);
468 }
469
470 afs_int32
471 SRXAFSCB_GetLock(struct rx_call *rxcall,
472                  afs_int32 index,
473                  AFSDBLock * lock)
474 {
475     return(0);
476 }
477
478 afs_int32
479 SRXAFSCB_XStatsVersion(struct rx_call *rxcall,
480                        afs_int32 * versionNumberP)
481 {
482     return(0);
483 }
484
485 afs_int32
486 SRXAFSCB_GetXStats(struct rx_call *rxcall,
487                    afs_int32 clientVersionNumber,
488                    afs_int32 collectionNumber,
489                    afs_int32 * srvVersionNumberP,
490                    afs_int32 * timeP,
491                    AFSCB_CollData * dataP)
492 {
493     return(0);
494 }
495
496 afs_int32
497 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID *a_uuid)
498 {
499     return(0);
500 }
501
502
503 afs_int32
504 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
505 {
506     int code = 0;
507
508     addr->numberOfInterfaces = 0;
509     addr->uuid = uuid;
510 #ifdef notdef
511     /* return all network interface addresses */
512     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
513     for ( i=0; i < afs_cb_interface.numberOfInterfaces; i++) {
514         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
515         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
516         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
517     }
518 #endif
519
520     return code;
521 }
522
523 afs_int32
524 SRXAFSCB_InitCallBackState2(struct rx_call *a_call, struct interfaceAddr *
525                             addr)
526 {
527     return RXGEN_OPCODE;
528 }
529
530 afs_int32
531 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID *a_uuid)
532 {
533     return 0;
534 }
535
536 afs_int32
537 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
538                         afs_uint32 *serverVersion, afs_uint32 *configCount,
539                         cacheConfig *config)
540 {
541     return RXGEN_OPCODE;
542 }
543
544 afs_int32
545 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
546 {
547     return RXGEN_OPCODE;
548 }
549
550 afs_int32
551 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
552                        char **a_name, serverList *a_hosts)
553 {
554     return RXGEN_OPCODE;
555 }
556
557 afs_int32
558 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
559                         afs_int32 *a_srvr_addr, afs_int32 *a_srvr_rank)
560 {
561     return RXGEN_OPCODE;
562 }
563
564 afs_int32
565 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call, struct interfaceAddr *
566                              addr, Capabilities *capabilities)
567 {
568     return RXGEN_OPCODE;
569 }
570
571 afs_int32
572 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
573                       char **a_name, serverList *a_hosts)
574 {
575     return RXGEN_OPCODE;
576 }
577
578 afs_int32
579 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
580                  struct AFSDBCacheEntry64 *a_result)
581 {
582     return RXGEN_OPCODE;
583 }
584
585 void *
586 InitializeCBService_LWP(void *unused)
587 {
588     struct rx_securityClass *CBsecobj;
589     struct rx_service *CBService;
590
591     afs_uuid_create(&uuid);
592
593     CBsecobj = (struct rx_securityClass *)rxnull_NewServerSecurityObject();
594     if (!CBsecobj) {
595         fprintf(stderr,"rxnull_NewServerSecurityObject failed for callback service.\n");
596         exit(1);
597     }
598     CBService = rx_NewService(0, 1, "afs", &CBsecobj, 1,
599                               RXAFSCB_ExecuteRequest);
600     if (!CBService) {
601         fprintf(stderr,"rx_NewService failed for callback service.\n");
602         exit(1);
603     }
604     rx_StartServer(1);
605     return 0;
606 }
607
608
609 int
610 InitializeCBService(void)
611 {
612 #define RESTOOL_CBPORT 7102
613 #define MAX_PORT_TRIES 1000
614 #define LWP_STACK_SIZE  (16 * 1024)
615     afs_int32 code;
616 #ifdef AFS_PTHREAD_ENV
617     pthread_t CBservicePid, parentPid;
618     pthread_attr_t tattr;
619 #else
620     PROCESS CBServiceLWP_ID, parentPid;
621 #endif
622     int InitialCBPort;
623     int CBPort;
624
625 #ifndef NO_AFS_CLIENT
626     if (!CBServiceNeeded)
627         return 0;
628 #endif
629 #ifndef AFS_PTHREAD_ENV
630     code = LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid);
631     if (code != LWP_SUCCESS) {
632         fprintf(stderr,"Unable to initialize LWP support, code %d\n",
633                 code);
634         exit(1);
635     }
636 #endif
637
638 #if defined(AFS_AIX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI_ENV)
639     srandom(getpid());
640     InitialCBPort = RESTOOL_CBPORT + random() % 1000;
641 #else /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
642 #if defined(AFS_HPUX_ENV)
643     srand48(getpid());
644     InitialCBPort = RESTOOL_CBPORT + lrand48() % 1000;
645 #else /* AFS_HPUX_ENV */
646     srand(getpid());
647     InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
648 #endif /* AFS_HPUX_ENV */
649 #endif /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
650
651     CBPort = InitialCBPort;
652     do {
653         code = rx_Init(htons(CBPort));
654         if (code) {
655             if ((code == RX_ADDRINUSE) &&
656                 (CBPort < MAX_PORT_TRIES + InitialCBPort)) {
657                 CBPort++;
658             } else if (CBPort < MAX_PORT_TRIES + InitialCBPort) {
659                 fprintf(stderr, "rx_Init didn't succeed for callback service."
660                         " Tried port numbers %d through %d\n",
661                         InitialCBPort, CBPort);
662                 exit(1);
663             } else {
664                 fprintf(stderr,"Couldn't initialize callback service "
665                         "because too many users are running this program. "
666                         "Try again later.\n");
667                 exit(1);
668             }
669         }
670     } while(code);
671 #ifdef AFS_PTHREAD_ENV
672     assert(pthread_attr_init(&tattr) == 0);
673     assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
674     assert(pthread_create(
675                &CBservicePid, &tattr, InitializeCBService_LWP, 0)
676            == 0);
677 #else
678     code = LWP_CreateProcess(InitializeCBService_LWP, LWP_STACK_SIZE,
679                              LWP_MAX_PRIORITY - 2, (int *) 0, "CBService",
680                              &CBServiceLWP_ID);
681     if (code != LWP_SUCCESS) {
682         fprintf(stderr,"Unable to create the callback service LWP, code %d\n",
683                 code);
684         exit(1);
685     }
686 #endif
687     return 0;
688 }
689
690 int
691 ScanVnode(char *fname, char *cell)
692 {
693     afs_int32 i, code = 0;
694
695     SetCellFname(cell);
696     i = sscanf(fname, "%u.%u.%u",
697                &PioctlInputs.fid.Volume,
698                &PioctlInputs.fid.Vnode,
699                &PioctlInputs.fid.Unique);
700     if (i != 3) {
701         PioctlInputs.fid.Volume = 0;
702         PioctlInputs.fid.Vnode = 0;
703         PioctlInputs.fid.Unique = 0;
704         fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
705         code = EINVAL;
706     }
707     /*
708      * The following is used to handle the case of unknown uniquifier. We
709      * just need a valid reference to the volume to direct the RPC to the
710      * right fileserver. Therefore we take the root directory of the volume.
711      */
712     if (PioctlInputs.fid.Unique == 0) {
713         PioctlInputs.int32s[0] = PioctlInputs.fid.Vnode;
714         PioctlInputs.fid.Vnode = 1;
715         PioctlInputs.fid.Unique = 1;
716     }
717     return code;
718 }
719
720 int
721 VLDBInit(int noAuthFlag, struct afsconf_cell *info)
722 {
723     afs_int32 code;
724
725     code = ugen_ClientInit(noAuthFlag, (char *) AFSDIR_CLIENT_ETC_DIRPATH,
726                            info->name, 0, &uclient,
727                            NULL, pnp, rxkad_clear,
728                            VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
729                            0, 0, USER_SERVICE_ID);
730     rxInitDone = 1;
731     return code;
732 }
733
734 afs_int32
735 get_vnode_hosts(char *fname, char **cellp, afs_int32 *hosts, AFSFid *Fid,
736                 int onlyRW)
737 {
738     struct afsconf_dir *tdir;
739     struct vldbentry vldbEntry;
740     afs_int32 i, j, code, *h, len;
741     struct afsconf_cell info;
742     afs_int32 mask;
743
744     tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
745     if (!tdir) {
746         fprintf(stderr,"Could not process files in configuration directory "
747                 "(%s).\n",AFSDIR_CLIENT_ETC_DIRPATH);
748         return -1;
749     }
750     if (!*cellp) {
751         len = MAXCELLCHARS;
752         *cellp = (char *) malloc(MAXCELLCHARS);
753         code = afsconf_GetLocalCell(tdir, *cellp, len);
754         if (code) return code;
755     }
756     code = afsconf_GetCellInfo(tdir, *cellp, AFSCONF_VLDBSERVICE, &info);
757     if (code) {
758         fprintf(stderr,"fs: cell %s not in %s/CellServDB\n",
759                 *cellp, AFSDIR_CLIENT_ETC_DIRPATH);
760         return code;
761     }
762
763     i = sscanf(fname, "%u.%u.%u", &Fid->Volume, &Fid->Vnode, &Fid->Unique);
764     if (i != 3) {
765         fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
766         return 1;
767     }
768     code = VLDBInit(1, &info);
769     if (code == 0) {
770         code = ubik_VL_GetEntryByID(uclient, 0, Fid->Volume,
771                                     -1, &vldbEntry);
772         if (code == VL_NOENT)
773             fprintf(stderr,"fs: volume %u does not exist in this cell.\n",
774                     Fid->Volume);
775         if (code) return code;
776     }
777     h = hosts;
778     mask = VLSF_RWVOL;
779     if (!onlyRW) mask |= VLSF_RWVOL;
780     for (i=0, j=0; j<vldbEntry.nServers; j++) {
781         if (vldbEntry.serverFlags[j] & mask) {
782             *h++ = ntohl(vldbEntry.serverNumber[j]);
783             i++;
784         }
785     }
786     for (; i<MAXHOSTS; i++) *h++ = 0;
787     return 0;
788 }
789
790 /* get_file_cell()
791  *     Determine which AFS cell file 'fn' lives in, the list of servers that
792  *     offer it, and the FID.
793  */
794 afs_int32
795 get_file_cell(char *fn, char **cellp, afs_int32 hosts[MAXHOSTS], AFSFid *Fid,
796               struct AFSFetchStatus *Status, afs_int32 create)
797 {
798     afs_int32 code;
799     char buf[256];
800     struct ViceIoctl status;
801     int j;
802     afs_int32 *Tmpafs_int32;
803
804     memset((char *) Status, 0, sizeof(struct AFSFetchStatus));
805     memset(buf, 0, sizeof(buf));
806     status.in_size = 0;
807     status.out_size = sizeof(buf);
808     status.in = buf;
809     status.out = buf;
810     errno = 0;
811     code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
812     if (code && create) {
813         char *c;
814         int fd;
815         strcpy(buf,fn);
816         if ((c = strrchr(buf,'/'))) {
817             *c = 0;
818             code = pioctl(buf,VIOC_FILE_CELL_NAME, &status, 0);
819             if (!code) {
820                 fd = open(fn, O_CREAT, 0644);
821                 close(fd);
822             }
823             code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
824         }
825     }
826     if (code) {
827         fprintf(stderr, "Unable to determine cell for %s\n", fn);
828         if (errno) {
829             perror(fn);
830             if (errno == EINVAL)
831                 fprintf(stderr, "(File might not be in AFS)\n");
832         } else
833             afs_com_err(pnp, code, (char *) 0);
834     } else {
835         *cellp = (char *) malloc(strlen(buf)+1);
836         strcpy(*cellp, buf);
837         SetCellFname(*cellp);
838         memset(buf, 0, sizeof(buf));
839         status.in = 0;
840         status.in_size = 0;
841         status.out = buf;
842         status.out_size = sizeof(buf);
843         code = pioctl(fn, VIOCWHEREIS, &status, 0);
844         if (code) {
845             fprintf(stderr, "Unable to determine fileservers for %s\n", fn);
846             if (errno) {
847                 perror(fn);
848             }
849             else
850                 afs_com_err(pnp, code, (char *) 0);
851         } else {
852             Tmpafs_int32 = (afs_int32 *)buf;
853             for (j=0;j<MAXHOSTS;++j) {
854                 hosts[j] = Tmpafs_int32[j];
855                 if (!Tmpafs_int32[j])
856                     break;
857             }
858         }
859         memset(buf, 0, sizeof(buf));
860         status.in_size = 0;
861         status.out_size = sizeof(buf);
862         status.in = 0;
863         status.out = buf;
864         code = pioctl(fn, VIOCGETFID, &status, 0);
865         if (code) {
866             fprintf(stderr, "Unable to determine FID for %s\n", fn);
867             if (errno) {
868                 perror(fn);
869             } else {
870                 afs_com_err(pnp, code, (char *) 0);
871             }
872         } else {
873             afs_int32 saveCommand, saveVolume;
874
875             Tmpafs_int32 = (afs_int32 *)buf;
876             Fid->Volume = Tmpafs_int32[1];
877             Fid->Vnode = Tmpafs_int32[2];
878             Fid->Unique = Tmpafs_int32[3];
879             status.in_size = sizeof(struct FsCmdInputs);
880             status.out_size = sizeof(struct FsCmdOutputs);
881             status.in = (char *) &PioctlInputs;
882             status.out = (char *) &PioctlOutputs;
883             saveCommand = PioctlInputs.command;
884             saveVolume = PioctlInputs.fid.Volume;
885             PioctlInputs.command = 0;
886             PioctlInputs.fid.Volume = 0;
887             if (!pioctl(fn, VIOC_FS_CMD, &status, 0))
888                 memcpy((char *)Status, &PioctlOutputs.status,
889                       sizeof(struct AFSFetchStatus));
890             PioctlInputs.command = saveCommand;
891             PioctlInputs.fid.Volume = saveVolume;
892             if (create && (Status->Length || Status->Length_hi)) {
893                 fprintf(stderr,"AFS file %s not empty, request aborted.\n",
894                         fn);
895                 exit(-5);
896             }
897         }
898     }
899     return code;
900 }
901
902 int
903 DestroyConnections(void)
904 {
905     int i;
906
907     if (!ConnLookupInitialized) return 0;
908     for (i = 0; i < MAX_HOSTS; i++) {
909         if (!ConnLookup[i].conn) break;
910         RXAFS_GiveUpAllCallBacks(ConnLookup[i].conn);
911         rx_DestroyConnection(ConnLookup[i].conn);
912     }
913     if (!rxInitDone)
914         rx_Finalize();
915     return 0;
916 }
917
918
919 int
920 LogErrors (int level, const char *fmt, ...)
921 {
922     va_list ap;
923
924     va_start(ap, fmt);
925     return vfprintf(stderr, fmt, ap);
926 }
927
928 int
929 readFile(struct cmd_syndesc *as, void *unused)
930 {
931     char *fname;
932     char *cell = 0;
933     afs_int32 code;
934     afs_int32 hosts[MAXHOSTS];
935     AFSFid Fid;
936     int i, j;
937     struct rx_connection *RXConn;
938     struct cellLookup *cl;
939     struct rx_call *tcall;
940     struct AFSVolSync tsync;
941     struct AFSFetchStatus OutStatus;
942     struct AFSCallBack CallBack;
943     afs_int64 Pos;
944     afs_int32 len;
945     afs_int64 length, Len;
946     u_char vnode = 0;
947     u_char first = 1;
948     int bytes;
949     int worstCode = 0;
950     char *buf = 0;
951     int bufflen = BUFFLEN;
952
953     i=0;
954
955     if (as->name[0] == 'f')
956         vnode = 1;
957     if (as->parms[2].items)
958         verbose = 1;
959     if (as->parms[3].items) {
960         md5sum = 1;
961         MD5_Init(&md5);
962     }
963
964     CBServiceNeeded = 1;
965     InitializeCBService();
966
967     gettimeofday (&starttime, &Timezone);
968     fname = as->parms[0].items->data;
969     cell = 0;
970     if (as->parms[1].items)
971         cell = as->parms[1].items->data;
972     if (vnode)
973         code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
974     else
975         code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, 0);
976     if (code) {
977         fprintf(stderr,"File not found %s\n", fname);
978         return code;
979     }
980     if (Fid.Vnode & 1) {
981         fprintf(stderr,"%s is a directory, not a file\n", fname);
982         return ENOENT;
983     }
984     cl = FindCell(cell);
985     for (j=0;j<MAXHOSTS;++j) {
986         int useHost;
987
988         if (first && as->parms[6].items) {
989             afs_uint32 fields, ip1, ip2, ip3, ip4;
990             fields = sscanf(as->parms[6].items->data, "%d.%d.%d.%d",
991                             &ip1, &ip2, &ip3, &ip4);
992             useHost = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
993             j--;
994         } else {
995             if (!hosts[j])
996                 break;
997             useHost = hosts[j];
998         }
999         first = 0;
1000         RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1001                                   cl->sc[cl->scIndex], cl->scIndex);
1002         if (!RXConn) {
1003             fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1004                     useHost);
1005             continue;
1006         }
1007 #ifndef NO_AFS_CLIENT
1008         if (vnode) {
1009 #endif /* NO_AFS_CLIENT */
1010             code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1011             if (code) {
1012                 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for"
1013                         " file %s, code was %d\n",
1014                         useHost, fname, code);
1015                 continue;
1016             }
1017 #ifndef NO_AFS_CLIENT
1018         }
1019 #endif /* NO_AFS_CLIENT */
1020         gettimeofday(&opentime, &Timezone);
1021         if (verbose) {
1022             seconds = opentime.tv_sec + opentime.tv_usec *.000001
1023                 -starttime.tv_sec - starttime.tv_usec *.000001;
1024             fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1025                     seconds);
1026         }
1027         Len = OutStatus.Length_hi;
1028         Len <<= 32;
1029         Len += OutStatus.Length;
1030         ZeroInt64(Pos);
1031         {
1032             afs_uint32 high, low;
1033
1034             tcall = rx_NewCall(RXConn);
1035             code = StartAFS_FetchData64 (tcall, &Fid, Pos, Len);
1036             if (code == RXGEN_OPCODE) {
1037                 afs_uint32 tmpPos,  tmpLen;
1038                 tmpPos = Pos; tmpLen = Len;
1039                 code = StartAFS_FetchData (tcall, &Fid, Pos, Len);
1040                 bytes = rx_Read(tcall, (char *)&low, sizeof(afs_int32));
1041                 length = ntohl(low);
1042                 if (bytes != 4) code = -3;
1043             } else if (!code) {
1044                 bytes = rx_Read(tcall, (char *)&high, 4);
1045                 length = ntohl(high);
1046                 length <<= 32;
1047                 bytes += rx_Read(tcall, (char *)&low, 4);
1048                 length += ntohl(low);
1049                 if (bytes != 8) code = -3;
1050             }
1051             if (code) {
1052                 if (code == RXGEN_OPCODE) {
1053                     fprintf(stderr, "File server for %s might not be running a"
1054                             " multi-resident AFS server\n",
1055                             fname);
1056                 } else {
1057                     fprintf(stderr, "%s for %s ended with error code %d\n",
1058                             (char *) &as->name, fname, code);
1059                     exit(1);
1060                 }
1061             }
1062             if (length > bufflen)
1063                 len = bufflen;
1064             else
1065                 len = length;
1066             buf = (char *)malloc(len);
1067             if (!buf) {
1068                 fprintf(stderr, "couldn't allocate buffer\n");
1069                 exit(1);
1070             }
1071             while (!code && NonZeroInt64(length)) {
1072                 if (length > bufflen)
1073                     len = bufflen;
1074                 else
1075                     len = length;
1076                 bytes = rx_Read(tcall, (char *) buf, len);
1077                 if (bytes != len) {
1078                     code = -3;
1079                 }
1080                 if (md5sum)
1081                     MD5_Update(&md5, buf, len);
1082                 if (!code)
1083                     write(1, buf, len);
1084                 length -= len;
1085                 xfered += len;
1086                 gettimeofday(&now, &Timezone);
1087                 if (verbose)
1088                     printDatarate();
1089             }
1090             worstCode = code;
1091             code = EndRXAFS_FetchData (tcall, &OutStatus, &CallBack, &tsync);
1092             rx_EndCall(tcall, 0);
1093             if (!worstCode)
1094                 worstCode = code;
1095         }
1096         break;
1097     }
1098     gettimeofday(&readtime, &Timezone);
1099     if (worstCode) {
1100         fprintf(stderr,"%s failed with code %d\n",
1101                 (char *) &as->name, worstCode);
1102     } else {
1103         if (md5sum) {
1104             afs_uint32 md5int[4];
1105             char *p;
1106             MD5_Final((char *) &md5int[0], &md5);
1107             p = fname + strlen(fname);
1108             while (p > fname) {
1109                 if (*(--p) == '/') {
1110                     ++p;
1111                     break;
1112                 }
1113             }
1114             fprintf(stderr, "%08x%08x%08x%08x  %s\n",
1115                     htonl(md5int[0]), htonl(md5int[1]),
1116                     htonl(md5int[2]), htonl(md5int[3]), p);
1117         }
1118         if(verbose) {
1119             seconds = readtime.tv_sec + readtime.tv_usec *.000001
1120                 -opentime.tv_sec - opentime.tv_usec *.000001;
1121             fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1122                     xfered, seconds);
1123             datarate = (xfered >> 20) / seconds;
1124             fprintf(stderr,"Total data rate = %.0f MB/sec. for read\n",
1125                     datarate);
1126         }
1127     }
1128     DestroyConnections();
1129     return worstCode;
1130 }
1131
1132 int
1133 writeFile(struct cmd_syndesc *as, void *unused)
1134 {
1135     char *fname = NULL;
1136     char *cell = 0;
1137     afs_int32 code, localcode = 0;
1138     afs_int32 hosts[MAXHOSTS];
1139     afs_uint32 useHost;
1140     AFSFid Fid;
1141     int i;
1142     struct rx_connection *RXConn;
1143     struct cellLookup *cl;
1144     struct rx_call *tcall;
1145     struct AFSVolSync tsync;
1146     struct AFSFetchStatus OutStatus;
1147     struct AFSStoreStatus InStatus;
1148     afs_int64 Pos;
1149     afs_int64 length, Len, synthlength = 0, offset = 0;
1150     u_char vnode = 0;
1151     int bytes;
1152     int worstCode = 0;
1153     int append = 0;
1154     int synthesize = 0;
1155     afs_int32 byteswritten;
1156     struct wbuf *bufchain = 0;
1157     struct wbuf *previous, *tbuf;
1158
1159     i=0;
1160
1161     if (as->name[0] == 'f') {
1162         vnode = 1;
1163         if (as->name[3] == 'a')
1164             append = 1;
1165     } else
1166         if (as->name[0] == 'a')
1167             append = 1;
1168     if (as->parms[2].items)
1169         verbose = 1;
1170     if (as->parms[3].items)
1171         md5sum = 1;
1172     if (as->parms[4].items) {
1173         code = util_GetInt64(as->parms[4].items->data, &synthlength);
1174         if (code) {
1175             fprintf(stderr, "Invalid value for synthesize length %s\n",
1176                     as->parms[4].items->data);
1177             return code;
1178         }
1179         synthesize = 1;
1180     }
1181     CBServiceNeeded = 1;
1182     InitializeCBService();
1183
1184     if (as->parms[0].items)
1185         fname = as->parms[0].items->data;
1186
1187     cell = 0;
1188     if (as->parms[1].items) cell = as->parms[1].items->data;
1189     if (vnode) {
1190         code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
1191         if (code)
1192             return code;
1193     } else
1194         code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, append ? 0 : 1);
1195     if (code) {
1196       if (code != -5)
1197             fprintf(stderr,"File or directory not found: %s\n",
1198                     fname);
1199         return code;
1200     }
1201     if (Fid.Vnode & 1) {
1202         fprintf(stderr,"%s is a directory, not a file\n", fname);
1203         return ENOENT;
1204     }
1205     if (!hosts[0]) {
1206         fprintf(stderr,"AFS file not found: %s\n", fname);
1207         return ENOENT;
1208     }
1209     cl = FindCell(cell);
1210     gettimeofday (&starttime, &Timezone);
1211     useHost = hosts[0];
1212     RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1213                               cl->sc[cl->scIndex], cl->scIndex);
1214     if (!RXConn) {
1215         fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1216                 hosts[0]);
1217         return -1;
1218     }
1219     InStatus.Mask = AFS_SETMODE + AFS_FSYNC;
1220     InStatus.UnixModeBits = 0644;
1221     if (append) {
1222         Pos = OutStatus.Length_hi;
1223         Pos = (Pos << 32) | OutStatus.Length;
1224     } else
1225         Pos = 0;
1226     previous = (struct wbuf *)&bufchain;
1227     if (md5sum)
1228         MD5_Init(&md5);
1229
1230     Len = 0;
1231     while (Len<WRITEBUFFLEN) {
1232         tbuf = (struct wbuf *)malloc(sizeof(struct wbuf));
1233         if (!tbuf) {
1234             if (!bufchain) {
1235                 fprintf(stderr, "Couldn't allocate buffer, aborting\n");
1236                 exit(1);
1237             }
1238             break;
1239         }
1240         memset(tbuf, 0, sizeof(struct wbuf));
1241         tbuf->buflen = BUFFLEN;
1242         if (synthesize) {
1243             afs_int32 ll, l = tbuf->buflen;
1244             if (l > synthlength)
1245                 l = synthlength;
1246             for (ll = 0; ll < l; ll += 4096) {
1247                 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1248                         (unsigned int)(offset >> 32),
1249                         (unsigned int)(offset & 0xffffffff) + ll);
1250             }
1251             offset += l;
1252             synthlength -= l;
1253             tbuf->used = l;
1254         } else
1255             tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1256         if (!tbuf->used) {
1257             free(tbuf);
1258             break;
1259         }
1260         if (md5sum)
1261             MD5_Update(&md5, &tbuf->buf, tbuf->used);
1262         previous->next = tbuf;
1263         previous = tbuf;
1264         Len += tbuf->used;
1265     }
1266     gettimeofday(&opentime, &Timezone);
1267     if (verbose) {
1268         seconds = opentime.tv_sec + opentime.tv_usec *.000001
1269             -starttime.tv_sec - starttime.tv_usec *.000001;
1270         fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1271                 seconds);
1272     }
1273     bytes = Len;
1274     while (!code && bytes) {
1275         afs_int32 code2;
1276         Len = bytes;
1277     restart:
1278         tcall = rx_NewCall(RXConn);
1279         code = StartAFS_StoreData64 (tcall, &Fid, &InStatus, Pos, Len, Pos+Len);
1280         if (code == RXGEN_OPCODE) {
1281             afs_uint32 tmpLen, tmpPos;
1282             tmpPos = Pos;
1283             tmpLen = Len;
1284             if (Pos+Len > 0x7fffffff) {
1285                 fprintf(stderr,"AFS fileserver does not support files >= 2 GB\n");
1286                 return EFBIG;
1287             }
1288             code = StartAFS_StoreData (tcall, &Fid, &InStatus, tmpPos, tmpLen,
1289                                        tmpPos+tmpLen);
1290         }
1291         if (code) {
1292             fprintf(stderr, "StartRXAFS_StoreData had error code %d\n", code);
1293             return code;
1294         }
1295         length = Len;
1296         tbuf = bufchain;
1297         if (Len) {
1298             for (tbuf= bufchain; tbuf; tbuf=tbuf->next) {
1299                 if (!tbuf->used)
1300                     break;
1301                 byteswritten = rx_Write(tcall, tbuf->buf, tbuf->used);
1302                 if (byteswritten != tbuf->used) {
1303                     fprintf(stderr,"Only %d instead of %" AFS_INT64_FMT " bytes transferred by rx_Write()\n", byteswritten, length);
1304                     fprintf(stderr, "At %" AFS_UINT64_FMT " bytes from the end\n", length);
1305                     code = -4;
1306                     break;
1307                 }
1308                 xfered += tbuf->used;
1309                 gettimeofday(&now, &Timezone);
1310                 if (verbose)
1311                     printDatarate();
1312                 length -= tbuf->used;
1313             }
1314         }
1315         worstCode = code;
1316         code = EndRXAFS_StoreData64 (tcall, &OutStatus, &tsync);
1317         if (code) {
1318             fprintf(stderr, "EndRXAFS_StoreData64 returned %d\n", code);
1319             worstCode = code;
1320         }
1321         code2 = rx_Error(tcall);
1322         if (code2) {
1323             fprintf(stderr, "rx_Error returned %d\n", code2);
1324             worstCode = code2;
1325         }
1326         code2 = rx_EndCall(tcall, localcode);
1327         if (code2) {
1328             fprintf(stderr, "rx_EndCall returned %d\n", code2);
1329             worstCode = code2;
1330         }
1331         code = worstCode;
1332         if (code == 110) {
1333             fprintf(stderr, "Waiting for busy volume\n");
1334             sleep(10);
1335             goto restart;
1336         }
1337         Pos += Len;
1338         bytes = 0;
1339         if (!code) {
1340             for (tbuf = bufchain; tbuf; tbuf=tbuf->next) {
1341                 tbuf->offset = 0;
1342                 if (synthesize) {
1343                     afs_int32 ll, l = tbuf->buflen;
1344                     if (l > synthlength)
1345                         l = synthlength;
1346                     for (ll = 0; ll < l; ll += 4096) {
1347                       sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1348                               (unsigned int)(offset >> 32),
1349                               (unsigned int)(offset & 0xffffffff) + ll);
1350                     }
1351                     offset += l;
1352                     synthlength -= l;
1353                     tbuf->used = l;
1354                 } else
1355                     tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1356                 if (!tbuf->used)
1357                     break;
1358                 if (md5sum)
1359                     MD5_Update(&md5, &tbuf->buf, tbuf->used);
1360                 Len += tbuf->used;
1361                 bytes += tbuf->used;
1362             }
1363         }
1364     }
1365     gettimeofday(&writetime, &Timezone);
1366     if (worstCode) {
1367         fprintf(stderr,"%s failed with code %d\n", as->name, worstCode);
1368     } else if(verbose) {
1369         seconds = writetime.tv_sec + writetime.tv_usec *.000001
1370             -opentime.tv_sec - opentime.tv_usec *.000001;
1371         fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1372                 xfered, seconds);
1373         datarate = (xfered >> 20) / seconds;
1374         fprintf(stderr,"Total data rate = %.0f MB/sec. for write\n",
1375                 datarate);
1376     }
1377     while (bufchain) {
1378         tbuf = bufchain;
1379         bufchain = tbuf->next;
1380         free(tbuf);
1381     }
1382     DestroyConnections();
1383     if (md5sum) {
1384         afs_uint32 md5int[4];
1385         char *p;
1386         MD5_Final((char *) &md5int[0], &md5);
1387         p = fname + strlen(fname);
1388         while (p > fname) {
1389             if (*(--p) == '/') {
1390                 ++p;
1391                 break;
1392             }
1393         }
1394         fprintf(stdout, "%08x%08x%08x%08x  %s\n",
1395                 htonl(md5int[0]), htonl(md5int[1]),
1396                 htonl(md5int[2]), htonl(md5int[3]), p);
1397     }
1398     return worstCode;
1399 }
1400
1401 struct cellLookup *
1402 FindCell(char *cellName)
1403 {
1404     char name[MAXCELLCHARS];
1405     char *np;
1406     struct cellLookup *p, *p2;
1407     static struct afsconf_dir *tdir;
1408     struct ktc_principal sname;
1409     struct ktc_token ttoken;
1410     afs_int32 len, code;
1411
1412     if (cellName) {
1413         np = cellName;
1414     } else {
1415         if (!tdir)
1416             tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1417         len = MAXCELLCHARS;
1418         afsconf_GetLocalCell(tdir, name, len);
1419         np = (char *) &name;
1420     }
1421     SetCellFname(np);
1422
1423     p2 = (struct cellLookup *) &Cells;
1424     for (p = Cells; p; p = p->next) {
1425         if (!strcmp((char *)&p->info.name, np)) {
1426 #ifdef NO_AFS_CLIENT
1427             if (!strcmp((char *)&lastcell, np))
1428                 code = VLDBInit(1, &p->info);
1429 #endif
1430             return p;
1431         }
1432         p2 = p;
1433     }
1434     p2->next = (struct cellLookup *) malloc(sizeof(struct cellLookup));
1435     p = p2->next;
1436     memset(p, 0, sizeof(struct cellLookup));
1437     p->next = (struct cellLookup *) 0;
1438     if (!tdir)
1439         tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1440     if (afsconf_GetCellInfo(tdir, np, AFSCONF_VLDBSERVICE, &p->info)) {
1441         p2->next = (struct cellLookup *) 0;
1442         free(p);
1443         p = (struct cellLookup *) 0;
1444     } else {
1445 #ifdef NO_AFS_CLIENT
1446         if (code = VLDBInit(1, &p->info))
1447             fprintf(stderr,"VLDBInit failed for cell %s\n", p->info.name);
1448 #endif
1449         strcpy((char *)&sname.cell, (char *)&p->info.name);
1450         sname.instance[0] = 0;
1451         strcpy(sname.name, "afs");
1452         code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL);
1453         if (code)
1454             p->scIndex = 0;
1455         else {
1456             if ((ttoken.kvno >= 0) && (ttoken.kvno <= 255))
1457                 /* this is a kerberos ticket, set scIndex accordingly */
1458                 p->scIndex = 2;
1459             else {
1460                 fprintf(stderr,"funny kvno (%d) in ticket, proceeding\n",
1461                         ttoken.kvno);
1462                 p->scIndex = 2;
1463             }
1464             p->sc[2] = (struct rx_securityClass *)
1465                 rxkad_NewClientSecurityObject(rxkad_clear, &ttoken.sessionKey,
1466                                               ttoken.kvno, ttoken.ticketLen,
1467                                               ttoken.ticket);
1468         }
1469         if (p->scIndex == 0)
1470             p->sc[0] = (struct rx_securityClass *)
1471                 rxnull_NewClientSecurityObject();
1472     }
1473
1474     if (p)
1475         return p;
1476     else
1477         return 0;
1478 }
1479
1480 struct rx_connection *
1481 FindRXConnection(afs_uint32 host, u_short port, u_short service,
1482                  struct rx_securityClass *securityObject,
1483                  int serviceSecurityIndex)
1484 {
1485     int i;
1486
1487     if (!ConnLookupInitialized) {
1488         memset(ConnLookup, 0, MAX_HOSTS * sizeof(struct connectionLookup));
1489         ConnLookupInitialized = 1;
1490     }
1491
1492     for (i = 0; i < MAX_HOSTS; i++) {
1493         if ((ConnLookup[i].host == host) && (ConnLookup[i].port == port))
1494             return ConnLookup[i].conn;
1495         if (!ConnLookup[i].conn)
1496             break;
1497     }
1498
1499     if (i >= MAX_HOSTS)
1500         return 0;
1501
1502     ConnLookup[i].conn = rx_NewConnection(host, port, service, securityObject, serviceSecurityIndex);
1503     if (ConnLookup[i].conn) {
1504         ConnLookup[i].host = host;
1505         ConnLookup[i].port = port;
1506     }
1507
1508     return ConnLookup[i].conn;
1509 }