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