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