Consolidate duplicate definitions
[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/afs_consts.h>
77 #include <afs/afscbint.h>
78 #include <afs/vldbint.h>
79 #include <afs/vlserver.h>
80 #include <afs/volser.h>
81 #include <afs/ptint.h>
82 #include <afs/dir.h>
83 #include <afs/nfs.h>
84 #include <afs/ihandle.h>
85 #include <afs/vnode.h>
86 #include <afs/com_err.h>
87 #ifdef HAVE_DIRENT_H
88 #include <dirent.h>
89 #endif
90 #ifdef HAVE_DIRECT_H
91 #include <direct.h>
92 #endif
93 #ifdef AFS_DARWIN_ENV
94 #include <sys/malloc.h>
95 #else
96 #include <malloc.h>
97 #endif
98 #include <afs/errors.h>
99 #include <afs/sys_prototypes.h>
100 #include <des_prototypes.h>
101 #include <rx_prototypes.h>
102 #include "../rxkad/md5.h"
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( 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             Tmpafs_int32 = (afs_int32 *)buf;
889             Fid->Volume = Tmpafs_int32[1];
890             Fid->Vnode = Tmpafs_int32[2];
891             Fid->Unique = Tmpafs_int32[3];
892         }
893     }
894     return code;
895 }
896
897 int
898 DestroyConnections(void)
899 {
900     int i;
901
902     if (!ConnLookupInitialized) return 0;
903     for (i = 0; i < MAX_HOSTS; i++) {
904         if (!ConnLookup[i].conn) break;
905         RXAFS_GiveUpAllCallBacks(ConnLookup[i].conn);
906         rx_DestroyConnection(ConnLookup[i].conn);
907     }
908     if (!rxInitDone)
909         rx_Finalize();
910     return 0;
911 }
912
913
914 int
915 LogErrors (int level, const char *fmt, ...)
916 {
917     va_list ap;
918
919     va_start(ap, fmt);
920     return vfprintf(stderr, fmt, ap);
921 }
922
923 int
924 readFile(struct cmd_syndesc *as, void *unused)
925 {
926     char *fname;
927     char *cell = 0;
928     afs_int32 code;
929     afs_int32 hosts[MAXHOSTS];
930     AFSFid Fid;
931     int i, j;
932     struct rx_connection *RXConn;
933     struct cellLookup *cl;
934     struct rx_call *tcall;
935     struct AFSVolSync tsync;
936     struct AFSFetchStatus OutStatus;
937     struct AFSCallBack CallBack;
938     afs_int64 Pos;
939     afs_int32 len;
940     afs_int64 length, Len;
941     u_char vnode = 0;
942     u_char first = 1;
943     int bytes;
944     int worstCode = 0;
945     char *buf = 0;
946     int bufflen = BUFFLEN;
947
948     i=0;
949
950     if (as->name[0] == 'f')
951         vnode = 1;
952     if (as->parms[2].items)
953         verbose = 1;
954     if (as->parms[3].items) {
955         md5sum = 1;
956         MD5_Init(&md5);
957     }
958
959     CBServiceNeeded = 1;
960     InitializeCBService();
961
962     gettimeofday (&starttime, &Timezone);
963     fname = as->parms[0].items->data;
964     cell = 0;
965     if (as->parms[1].items)
966         cell = as->parms[1].items->data;
967     if (vnode)
968         code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
969     else
970         code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, 0);
971     if (code) {
972         fprintf(stderr,"File not found %s\n", fname);
973         return code;
974     }
975     if (Fid.Vnode & 1) {
976         fprintf(stderr,"%s is a directory, not a file\n", fname);
977         return ENOENT;
978     }
979     cl = FindCell(cell);
980     for (j=0;j<MAXHOSTS;++j) {
981         int useHost;
982
983         if (first && as->parms[6].items) {
984             afs_uint32 fields, ip1, ip2, ip3, ip4;
985             fields = sscanf(as->parms[6].items->data, "%d.%d.%d.%d",
986                             &ip1, &ip2, &ip3, &ip4);
987             useHost = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
988             j--;
989         } else {
990             if (!hosts[j])
991                 break;
992             useHost = hosts[j];
993         }
994         first = 0;
995         RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
996                                   cl->sc[cl->scIndex], cl->scIndex);
997         if (!RXConn) {
998             fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
999                     useHost);
1000             continue;
1001         }
1002 #ifndef NO_AFS_CLIENT
1003         if (vnode) {
1004 #endif /* NO_AFS_CLIENT */
1005             code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1006             if (code) {
1007                 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for"
1008                         " file %s, code was %d\n",
1009                         useHost, fname, code);
1010                 continue;
1011             }
1012 #ifndef NO_AFS_CLIENT
1013         }
1014 #endif /* NO_AFS_CLIENT */
1015         gettimeofday(&opentime, &Timezone);
1016         if (verbose) {
1017             seconds = (float)(opentime.tv_sec + opentime.tv_usec *.000001
1018                 -starttime.tv_sec - starttime.tv_usec *.000001);
1019             fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1020                     seconds);
1021         }
1022         Len = OutStatus.Length_hi;
1023         Len <<= 32;
1024         Len += OutStatus.Length;
1025         ZeroInt64(Pos);
1026         {
1027             afs_uint32 high, low;
1028
1029             tcall = rx_NewCall(RXConn);
1030             code = StartAFS_FetchData64 (tcall, &Fid, Pos, Len);
1031             if (code == RXGEN_OPCODE) {
1032                 afs_int32 tmpPos,  tmpLen;
1033                 tmpPos = (afs_int32)Pos; tmpLen = (afs_int32)Len;
1034                 code = StartAFS_FetchData (tcall, &Fid, tmpPos, tmpLen);
1035                 bytes = rx_Read(tcall, (char *)&low, sizeof(afs_int32));
1036                 length = ntohl(low);
1037                 if (bytes != 4) code = -3;
1038             } else if (!code) {
1039                 bytes = rx_Read(tcall, (char *)&high, 4);
1040                 length = ntohl(high);
1041                 length <<= 32;
1042                 bytes += rx_Read(tcall, (char *)&low, 4);
1043                 length += ntohl(low);
1044                 if (bytes != 8) code = -3;
1045             }
1046             if (code) {
1047                 if (code == RXGEN_OPCODE) {
1048                     fprintf(stderr, "File server for %s might not be running a"
1049                             " multi-resident AFS server\n",
1050                             fname);
1051                 } else {
1052                     fprintf(stderr, "%s for %s ended with error code %d\n",
1053                             (char *) &as->name, fname, code);
1054                     exit(1);
1055                 }
1056             }
1057             if (length > bufflen)
1058                 len = bufflen;
1059             else
1060                 len = (afs_int32) length;
1061             buf = (char *)malloc(len);
1062             if (!buf) {
1063                 fprintf(stderr, "couldn't allocate buffer\n");
1064                 exit(1);
1065             }
1066             while (!code && NonZeroInt64(length)) {
1067                 if (length > bufflen)
1068                     len = bufflen;
1069                 else
1070                     len = (afs_int32) length;
1071                 bytes = rx_Read(tcall, (char *) buf, len);
1072                 if (bytes != len) {
1073                     code = -3;
1074                 }
1075                 if (md5sum)
1076                     MD5_Update(&md5, buf, len);
1077                 if (!code)
1078                     write(1, buf, len);
1079                 length -= len;
1080                 xfered += len;
1081                 gettimeofday(&now, &Timezone);
1082                 if (verbose)
1083                     printDatarate();
1084             }
1085             worstCode = code;
1086             code = EndRXAFS_FetchData (tcall, &OutStatus, &CallBack, &tsync);
1087             rx_EndCall(tcall, 0);
1088             if (!worstCode)
1089                 worstCode = code;
1090         }
1091         break;
1092     }
1093     gettimeofday(&readtime, &Timezone);
1094     if (worstCode) {
1095         fprintf(stderr,"%s failed with code %d\n",
1096                 (char *) &as->name, worstCode);
1097     } else {
1098         if (md5sum) {
1099             afs_uint32 md5int[4];
1100             char *p;
1101             MD5_Final((char *) &md5int[0], &md5);
1102             p = fname + strlen(fname);
1103             while (p > fname) {
1104                 if (*(--p) == '/') {
1105                     ++p;
1106                     break;
1107                 }
1108             }
1109             fprintf(stderr, "%08x%08x%08x%08x  %s\n",
1110                     htonl(md5int[0]), htonl(md5int[1]),
1111                     htonl(md5int[2]), htonl(md5int[3]), p);
1112         }
1113         if(verbose) {
1114             seconds = (float)(readtime.tv_sec + readtime.tv_usec *.000001
1115                 -opentime.tv_sec - opentime.tv_usec *.000001);
1116             fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1117                     xfered, seconds);
1118             datarate = (xfered >> 20) / seconds;
1119             fprintf(stderr,"Total data rate = %.0f MB/sec. for read\n",
1120                     datarate);
1121         }
1122     }
1123     DestroyConnections();
1124     return worstCode;
1125 }
1126
1127 int
1128 writeFile(struct cmd_syndesc *as, void *unused)
1129 {
1130     char *fname = NULL;
1131     char *cell = 0;
1132     afs_int32 code, localcode = 0;
1133     afs_int32 hosts[MAXHOSTS];
1134     afs_uint32 useHost;
1135     AFSFid Fid;
1136     int i;
1137     struct rx_connection *RXConn;
1138     struct cellLookup *cl;
1139     struct rx_call *tcall;
1140     struct AFSVolSync tsync;
1141     struct AFSFetchStatus OutStatus;
1142     struct AFSStoreStatus InStatus;
1143     struct AFSCallBack CallBack;
1144     afs_int64 Pos;
1145     afs_int64 length, Len, synthlength = 0, offset = 0;
1146     u_char vnode = 0;
1147     afs_int64 bytes;
1148     int worstCode = 0;
1149     int append = 0;
1150     int synthesize = 0;
1151     afs_int32 byteswritten;
1152     struct wbuf *bufchain = 0;
1153     struct wbuf *previous, *tbuf;
1154
1155     i=0;
1156
1157     if (as->name[0] == 'f') {
1158         vnode = 1;
1159         if (as->name[3] == 'a')
1160             append = 1;
1161     } else
1162         if (as->name[0] == 'a')
1163             append = 1;
1164     if (as->parms[2].items)
1165         verbose = 1;
1166     if (as->parms[3].items)
1167         md5sum = 1;
1168     if (as->parms[4].items) {
1169         code = util_GetInt64(as->parms[4].items->data, &synthlength);
1170         if (code) {
1171             fprintf(stderr, "Invalid value for synthesize length %s\n",
1172                     as->parms[4].items->data);
1173             return code;
1174         }
1175         synthesize = 1;
1176     }
1177     CBServiceNeeded = 1;
1178     InitializeCBService();
1179
1180     if (as->parms[0].items)
1181         fname = as->parms[0].items->data;
1182
1183     cell = 0;
1184     if (as->parms[1].items) cell = as->parms[1].items->data;
1185     if (vnode) {
1186         code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
1187         if (code)
1188             return code;
1189     } else
1190         code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, append ? 0 : 1);
1191     if (code) {
1192         fprintf(stderr,"File or directory not found: %s\n",
1193                     fname);
1194         return code;
1195     }
1196     if (Fid.Vnode & 1) {
1197         fprintf(stderr,"%s is a directory, not a file\n", fname);
1198         return ENOENT;
1199     }
1200     if (!hosts[0]) {
1201         fprintf(stderr,"AFS file not found: %s\n", fname);
1202         return ENOENT;
1203     }
1204     cl = FindCell(cell);
1205     gettimeofday (&starttime, &Timezone);
1206     useHost = hosts[0];
1207     RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1208                               cl->sc[cl->scIndex], cl->scIndex);
1209     if (!RXConn) {
1210         fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1211                 hosts[0]);
1212         return -1;
1213     }
1214     code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1215     if (code) {
1216         fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for file %s, code was%d\n",
1217                             useHost, fname, code);
1218        return -1;
1219     }
1220     if (!append && (OutStatus.Length || OutStatus.Length_hi)) {
1221         fprintf(stderr,"AFS file %s not empty, request aborted.\n", fname);
1222         DestroyConnections();
1223         return -5;
1224     }
1225     InStatus.Mask = AFS_SETMODE + AFS_FSYNC;
1226     InStatus.UnixModeBits = 0644;
1227     if (append) {
1228         Pos = OutStatus.Length_hi;
1229         Pos = (Pos << 32) | OutStatus.Length;
1230     } else
1231         Pos = 0;
1232     previous = (struct wbuf *)&bufchain;
1233     if (md5sum)
1234         MD5_Init(&md5);
1235
1236     Len = 0;
1237     while (Len<WRITEBUFFLEN) {
1238         tbuf = (struct wbuf *)malloc(sizeof(struct wbuf));
1239         if (!tbuf) {
1240             if (!bufchain) {
1241                 fprintf(stderr, "Couldn't allocate buffer, aborting\n");
1242                 exit(1);
1243             }
1244             break;
1245         }
1246         memset(tbuf, 0, sizeof(struct wbuf));
1247         tbuf->buflen = BUFFLEN;
1248         if (synthesize) {
1249             afs_int64 ll, l = tbuf->buflen;
1250             if (l > synthlength)
1251                 l = synthlength;
1252             for (ll = 0; ll < l; ll += 4096) {
1253                 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1254                         (unsigned int)((offset + ll) >> 32),
1255                         (unsigned int)((offset + ll) & 0xffffffff));
1256             }
1257             offset += l;
1258             synthlength -= l;
1259             tbuf->used = (afs_int32)l;
1260         } else
1261             tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1262         if (!tbuf->used) {
1263             free(tbuf);
1264             break;
1265         }
1266         if (md5sum)
1267             MD5_Update(&md5, &tbuf->buf, tbuf->used);
1268         previous->next = tbuf;
1269         previous = tbuf;
1270         Len += tbuf->used;
1271     }
1272     gettimeofday(&opentime, &Timezone);
1273     if (verbose) {
1274         seconds = (float) (opentime.tv_sec + opentime.tv_usec *.000001
1275             -starttime.tv_sec - starttime.tv_usec *.000001);
1276         fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1277                 seconds);
1278     }
1279     bytes = Len;
1280     while (!code && bytes) {
1281         afs_int32 code2;
1282         Len = bytes;
1283     restart:
1284         tcall = rx_NewCall(RXConn);
1285         code = StartAFS_StoreData64 (tcall, &Fid, &InStatus, Pos, Len, Pos+Len);
1286         if (code == RXGEN_OPCODE) {
1287             afs_uint32 tmpLen, tmpPos;
1288             tmpPos = (afs_int32) Pos;
1289             tmpLen = (afs_int32) Len;
1290             if (Pos+Len > 0x7fffffff) {
1291                 fprintf(stderr,"AFS fileserver does not support files >= 2 GB\n");
1292                 return EFBIG;
1293             }
1294             code = StartAFS_StoreData (tcall, &Fid, &InStatus, tmpPos, tmpLen,
1295                                        tmpPos+tmpLen);
1296         }
1297         if (code) {
1298             fprintf(stderr, "StartRXAFS_StoreData had error code %d\n", code);
1299             return code;
1300         }
1301         length = Len;
1302         tbuf = bufchain;
1303         if (Len) {
1304             for (tbuf= bufchain; tbuf; tbuf=tbuf->next) {
1305                 if (!tbuf->used)
1306                     break;
1307                 byteswritten = rx_Write(tcall, tbuf->buf, tbuf->used);
1308                 if (byteswritten != tbuf->used) {
1309                     fprintf(stderr,"Only %d instead of %" AFS_INT64_FMT " bytes transferred by rx_Write()\n", byteswritten, length);
1310                     fprintf(stderr, "At %" AFS_UINT64_FMT " bytes from the end\n", length);
1311                     code = -4;
1312                     break;
1313                 }
1314                 xfered += tbuf->used;
1315                 gettimeofday(&now, &Timezone);
1316                 if (verbose)
1317                     printDatarate();
1318                 length -= tbuf->used;
1319             }
1320         }
1321         worstCode = code;
1322         code = EndRXAFS_StoreData64 (tcall, &OutStatus, &tsync);
1323         if (code) {
1324             fprintf(stderr, "EndRXAFS_StoreData64 returned %d\n", code);
1325             worstCode = code;
1326         }
1327         code2 = rx_Error(tcall);
1328         if (code2) {
1329             fprintf(stderr, "rx_Error returned %d\n", code2);
1330             worstCode = code2;
1331         }
1332         code2 = rx_EndCall(tcall, localcode);
1333         if (code2) {
1334             fprintf(stderr, "rx_EndCall returned %d\n", code2);
1335             worstCode = code2;
1336         }
1337         code = worstCode;
1338         if (code == 110) {
1339             fprintf(stderr, "Waiting for busy volume\n");
1340             sleep(10);
1341             goto restart;
1342         }
1343         Pos += Len;
1344         bytes = 0;
1345         if (!code) {
1346             for (tbuf = bufchain; tbuf; tbuf=tbuf->next) {
1347                 tbuf->offset = 0;
1348                 if (synthesize) {
1349                     afs_int64 ll, l = tbuf->buflen;
1350                     if (l > synthlength)
1351                         l = synthlength;
1352                     for (ll = 0; ll < l; ll += 4096) {
1353                         sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1354                                 (unsigned int)((offset + ll) >> 32),
1355                                 (unsigned int)((offset + ll) & 0xffffffff));
1356                     }
1357                     offset += l;
1358                     synthlength -= l;
1359                     tbuf->used = (afs_int32) l;
1360                 } else
1361                     tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1362                 if (!tbuf->used)
1363                     break;
1364                 if (md5sum)
1365                     MD5_Update(&md5, &tbuf->buf, tbuf->used);
1366                 Len += tbuf->used;
1367                 bytes += tbuf->used;
1368             }
1369         }
1370     }
1371     gettimeofday(&writetime, &Timezone);
1372     if (worstCode) {
1373         fprintf(stderr,"%s failed with code %d\n", as->name, worstCode);
1374     } else if(verbose) {
1375         seconds = (float) (writetime.tv_sec + writetime.tv_usec *.000001
1376             -opentime.tv_sec - opentime.tv_usec *.000001);
1377         fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1378                 xfered, seconds);
1379         datarate = (xfered >> 20) / seconds;
1380         fprintf(stderr,"Total data rate = %.0f MB/sec. for write\n",
1381                 datarate);
1382     }
1383     while (bufchain) {
1384         tbuf = bufchain;
1385         bufchain = tbuf->next;
1386         free(tbuf);
1387     }
1388     DestroyConnections();
1389     if (md5sum) {
1390         afs_uint32 md5int[4];
1391         char *p;
1392         MD5_Final((char *) &md5int[0], &md5);
1393         p = fname + strlen(fname);
1394         while (p > fname) {
1395             if (*(--p) == '/') {
1396                 ++p;
1397                 break;
1398             }
1399         }
1400         fprintf(stdout, "%08x%08x%08x%08x  %s\n",
1401                 htonl(md5int[0]), htonl(md5int[1]),
1402                 htonl(md5int[2]), htonl(md5int[3]), p);
1403     }
1404     return worstCode;
1405 }
1406
1407 struct cellLookup *
1408 FindCell(char *cellName)
1409 {
1410     char name[MAXCELLCHARS];
1411     char *np;
1412     struct cellLookup *p, *p2;
1413     static struct afsconf_dir *tdir;
1414     struct ktc_principal sname;
1415     struct ktc_token ttoken;
1416     afs_int32 len, code;
1417
1418     if (cellName) {
1419         np = cellName;
1420     } else {
1421         if (!tdir)
1422             tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1423         len = MAXCELLCHARS;
1424         afsconf_GetLocalCell(tdir, name, len);
1425         np = (char *) &name;
1426     }
1427     SetCellFname(np);
1428
1429     p2 = (struct cellLookup *) &Cells;
1430     for (p = Cells; p; p = p->next) {
1431         if (!strcmp((char *)&p->info.name, np)) {
1432 #ifdef NO_AFS_CLIENT
1433             if (!strcmp((char *)&lastcell, np))
1434                 code = VLDBInit(1, &p->info);
1435 #endif
1436             return p;
1437         }
1438         p2 = p;
1439     }
1440     p2->next = (struct cellLookup *) malloc(sizeof(struct cellLookup));
1441     p = p2->next;
1442     memset(p, 0, sizeof(struct cellLookup));
1443     p->next = (struct cellLookup *) 0;
1444     if (!tdir)
1445         tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1446     if (afsconf_GetCellInfo(tdir, np, AFSCONF_VLDBSERVICE, &p->info)) {
1447         p2->next = (struct cellLookup *) 0;
1448         free(p);
1449         p = (struct cellLookup *) 0;
1450     } else {
1451 #ifdef NO_AFS_CLIENT
1452         if (code = VLDBInit(1, &p->info))
1453             fprintf(stderr,"VLDBInit failed for cell %s\n", p->info.name);
1454 #endif
1455         strcpy((char *)&sname.cell, (char *)&p->info.name);
1456         sname.instance[0] = 0;
1457         strcpy(sname.name, "afs");
1458         code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL);
1459         if (code)
1460             p->scIndex = 0;
1461         else {
1462             if ((ttoken.kvno >= 0) && (ttoken.kvno <= 255))
1463                 /* this is a kerberos ticket, set scIndex accordingly */
1464                 p->scIndex = 2;
1465             else {
1466                 fprintf(stderr,"funny kvno (%d) in ticket, proceeding\n",
1467                         ttoken.kvno);
1468                 p->scIndex = 2;
1469             }
1470             p->sc[2] = (struct rx_securityClass *)
1471                 rxkad_NewClientSecurityObject(rxkad_clear, &ttoken.sessionKey,
1472                                               ttoken.kvno, ttoken.ticketLen,
1473                                               ttoken.ticket);
1474         }
1475         if (p->scIndex == 0)
1476             p->sc[0] = (struct rx_securityClass *)
1477                 rxnull_NewClientSecurityObject();
1478     }
1479
1480     if (p)
1481         return p;
1482     else
1483         return 0;
1484 }
1485
1486 struct rx_connection *
1487 FindRXConnection(afs_uint32 host, u_short port, u_short service,
1488                  struct rx_securityClass *securityObject,
1489                  int serviceSecurityIndex)
1490 {
1491     int i;
1492
1493     if (!ConnLookupInitialized) {
1494         memset(ConnLookup, 0, MAX_HOSTS * sizeof(struct connectionLookup));
1495         ConnLookupInitialized = 1;
1496     }
1497
1498     for (i = 0; i < MAX_HOSTS; i++) {
1499         if ((ConnLookup[i].host == host) && (ConnLookup[i].port == port))
1500             return ConnLookup[i].conn;
1501         if (!ConnLookup[i].conn)
1502             break;
1503     }
1504
1505     if (i >= MAX_HOSTS)
1506         return 0;
1507
1508     ConnLookup[i].conn = rx_NewConnection(host, port, service, securityObject, serviceSecurityIndex);
1509     if (ConnLookup[i].conn) {
1510         ConnLookup[i].host = host;
1511         ConnLookup[i].port = port;
1512     }
1513
1514     return ConnLookup[i].conn;
1515 }