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