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