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