2 * Copyright (c) 2007, Hartmut Reuter,
3 * RZG, Max-Planck-Institut f. Plasmaphysik.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
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
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.
28 #include <afsconfig.h>
29 #include <afs/param.h>
33 #include <sys/types.h>
39 #include <sys/param.h>
41 #include <sys/ioctl.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
56 #include <afs/cellconfig.h>
57 #include <afs/afsutil.h>
60 #include <afs/venus.h>
61 #include <afs/afscbint.h>
62 #define FSINT_COMMON_XG 1
63 #include <afs/afsint.h>
64 #include <afs/vldbint.h>
65 #include <afs/vlserver.h>
66 #include <afs/volser.h>
67 #include <afs/ptint.h>
70 #include <afs/ihandle.h>
71 #include <afs/namei_ops.h>
72 #include <afs/vnode.h>
73 #include <afs/com_err.h>
83 #include <sys/malloc.h>
87 #include <afs/errors.h>
88 #include <afs/sys_prototypes.h>
89 #include <des_prototypes.h>
90 #include <rx_prototypes.h>
91 #include "../rxkad/md5.h"
94 #define afs_stat stat64
95 #define afs_fstat fstat64
96 #define afs_open open64
97 #else /* !O_LARGEFILE */
99 #define afs_fstat fstat
100 #define afs_open open
101 #endif /* !O_LARGEFILE */
102 #ifdef AFS_PTHREAD_ENV
104 pthread_key_t uclient_key;
107 int readFile(struct cmd_syndesc *as, void *);
108 int writeFile(struct cmd_syndesc *as, void *);
109 struct rx_connection *FindRXConnection(afs_uint32 host, u_short port, u_short service, struct rx_securityClass *securityObject, int serviceSecurityIndex);
110 struct cellLookup * FindCell(char *cellName);
114 static int verbose = 0; /* Set if -verbose option given */
115 static int CBServiceNeeded = 0;
116 static struct timeval starttime, opentime, readtime, writetime;
117 afs_uint64 xfered=0, oldxfered=0;
118 static struct timeval now;
119 struct timezone Timezone;
120 static float seconds, datarate, oldseconds;
121 extern int rxInitDone;
122 afs_uint64 transid = 0;
123 afs_uint32 expires = 0;
124 afs_uint32 server_List[MAXHOSTSPERCELL];
127 static struct ubik_client *uclient;
128 #define BUFFLEN 65536
129 #define WRITEBUFFLEN 1024*1024*64
137 afs_uint32 offset; /* offset inside the buffer */
138 afs_uint32 buflen; /* total length == BUFFLEN */
139 afs_uint32 used; /* bytes used inside buffer */
143 struct connectionLookup {
146 struct rx_connection *conn;
150 struct cellLookup *next;
151 struct afsconf_cell info;
152 struct rx_securityClass *sc[3];
157 struct dirLookup *next;
158 struct dirLookup *prev;
160 struct cellLookup *cell;
162 char name[VL_MAXNAMELEN];
165 struct cellLookup *Cells = 0;
166 struct dirLookup *Dirs = 0;
169 #define MAX_HOSTS 256
170 static struct connectionLookup ConnLookup[MAX_HOSTS];
171 static int ConnLookupInitialized = 0;
173 struct FsCmdInputs PioctlInputs;
174 struct FsCmdOutputs PioctlOutputs;
179 seconds = now.tv_sec + now.tv_usec *.000001
180 -opentime.tv_sec - opentime.tv_usec *.000001;
181 if ((seconds - oldseconds) > 30.) {
183 tmp = xfered - oldxfered;
184 datarate = ((afs_uint32) (tmp >> 20)) / (seconds - oldseconds);
185 fprintf(stderr,"%llu MB transferred, present date rate = %.0f MB/sec.\n",
186 xfered >> 20, datarate);
188 oldseconds = seconds;
193 SetCellFname(char *name)
195 struct afsconf_dir *tdir;
197 strcpy((char *) &cellFname,"/afs/");
199 strcat((char *) &cellFname, name);
201 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
202 afsconf_GetLocalCell(tdir, &cellFname[5], MAXCELLCHARS);
207 main (int argc, char **argv)
210 struct cmd_syndesc *ts;
212 strcpy(pnp, argv[0]);
214 #ifdef AFS_PTHREAD_ENV
215 assert(pthread_key_create(&uclient_key, NULL) == 0);
217 ts = cmd_CreateSyntax("read", readFile, CMD_REQUIRED,
218 "read a file from AFS");
219 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename");
220 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
221 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
222 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
224 ts = cmd_CreateSyntax("fidread", readFile, CMD_REQUIRED,
225 "read on a non AFS-client a file from AFS");
226 cmd_IsAdministratorCommand(ts);
227 cmd_AddParm(ts, "-fid", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
228 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
229 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
230 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
232 ts = cmd_CreateSyntax("write", writeFile, CMD_REQUIRED,
233 "write a file into AFS");
234 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
235 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
236 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
237 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
238 cmd_AddParm(ts, "-synthesize", CMD_SINGLE, CMD_OPTIONAL, "create data pattern of specified length instead reading from stdin");
240 ts = cmd_CreateSyntax("fidwrite", writeFile, CMD_REQUIRED,
241 "write a file into AFS");
242 cmd_IsAdministratorCommand(ts);
243 cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
244 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
245 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
246 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
248 ts = cmd_CreateSyntax("append", writeFile, CMD_REQUIRED,
249 "append to a file in AFS");
250 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
251 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
252 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
254 ts = cmd_CreateSyntax("fidappend", writeFile, CMD_REQUIRED,
255 "append to a file in AFS");
256 cmd_IsAdministratorCommand(ts);
257 cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
258 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
259 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
261 code = cmd_Dispatch(argc, argv);
267 HandleLocalAuth(struct rx_securityClass **sc[3], afs_int32 *scIndex)
269 static struct afsconf_dir *tdir = NULL;
270 struct ktc_principal sname;
271 struct ktc_token ttoken;
273 struct ktc_encryptionKey key;
278 tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
280 fprintf(stderr,"Could not open configuration directory: %s.\n",
281 AFSDIR_SERVER_ETC_DIRPATH);
284 cell = tdir->cellName;
285 strcpy(sname.cell, cell);
286 sname.instance[0] = 0;
287 strcpy(sname.name, "afs");
288 code=afsconf_GetLatestKey(tdir, &kvno, &key);
290 fprintf(stderr,"afsconf_GetLatestKey returned %d\n", code);
294 des_init_random_number_generator(ktc_to_cblock(&key));
295 code = des_random_key(ktc_to_cblock(&ttoken.sessionKey));
297 fprintf(stderr,"des_random_key returned %d\n", code);
300 ttoken.ticketLen = MAXKTCTICKETLEN;
301 code = tkt_MakeTicket(ttoken.ticket, &ttoken.ticketLen, &key,
302 AUTH_SUPERUSER, "", sname.cell,
304 &ttoken.sessionKey, host,
305 sname.name, sname.instance);
310 *sc[2] = (struct rx_securityClass *)
311 rxkad_NewClientSecurityObject(rxkad_clear,
312 &ttoken.sessionKey, ttoken.kvno,
313 ttoken.ticketLen, ttoken.ticket);
316 *sc[0] = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
321 AFS_Lookup(struct rx_connection *conn, AFSFid *dirfid, char *name,
322 AFSFid *outfid, AFSFetchStatus *outstatus, AFSFetchStatus
323 *dirstatus, AFSCallBack *callback, AFSVolSync *sync)
325 afs_int32 code = VBUSY;
326 while (code == VBUSY) {
327 code = RXAFS_Lookup(conn, dirfid, name, outfid, outstatus, dirstatus,
330 fprintf(stderr, "waiting for busy AFS volume %u.\n",
332 #ifdef AFS_PTHREAD_ENV
343 AFS_FetchStatus(struct rx_connection *conn, AFSFid *fid, AFSFetchStatus
344 *Status, AFSCallBack *callback, AFSVolSync *sync)
346 afs_int32 code = VBUSY;
348 while (code == VBUSY) {
349 code = RXAFS_FetchStatus(conn, fid, Status, callback, sync);
351 fprintf(stderr, "waiting for busy AFS volume %u.\n",
353 #ifdef AFS_PTHREAD_ENV
364 StartAFS_FetchData(struct rx_call *call, AFSFid *fid, afs_int32 pos,
367 afs_int32 code = VBUSY;
368 while (code == VBUSY) {
369 code = StartRXAFS_FetchData (call, fid, pos, len);
371 fprintf(stderr, "waiting for busy AFS volume %u.\n",
373 #ifdef AFS_PTHREAD_ENV
384 StartAFS_FetchData64(struct rx_call *call, AFSFid *fid, afs_int64 pos,
387 afs_int32 code = VBUSY;
388 while (code == VBUSY) {
389 code = StartRXAFS_FetchData64 (call, fid, pos, len);
391 fprintf(stderr, "waiting for busy AFS volume %u.\n",
393 #ifdef AFS_PTHREAD_ENV
404 StartAFS_StoreData(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
405 afs_int32 pos, afs_int32 len, afs_int32 len2)
407 afs_int32 code = VBUSY;
408 while (code == VBUSY) {
409 code = StartRXAFS_StoreData (call, fid, status, pos, len, len2);
411 fprintf(stderr, "waiting for busy AFS volume %u.\n",
413 #ifdef AFS_PTHREAD_ENV
424 StartAFS_StoreData64(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
425 afs_int64 pos, afs_int64 len, afs_int64 len2)
427 afs_int32 code = VBUSY;
428 while (code == VBUSY) {
429 code = StartRXAFS_StoreData64 (call, fid, status, pos, len, len2);
431 fprintf(stderr, "waiting for busy AFS volume %u.\n",
433 #ifdef AFS_PTHREAD_ENV
444 SRXAFSCB_CallBack(struct rx_call *rxcall, AFSCBFids *Fids_Array,
445 AFSCBs *CallBack_Array)
451 SRXAFSCB_InitCallBackState(struct rx_call *rxcall)
457 SRXAFSCB_Probe(struct rx_call *rxcall)
463 SRXAFSCB_GetCE(struct rx_call *rxcall,
465 AFSDBCacheEntry * ce)
471 SRXAFSCB_GetLock(struct rx_call *rxcall,
479 SRXAFSCB_XStatsVersion(struct rx_call *rxcall,
480 afs_int32 * versionNumberP)
486 SRXAFSCB_GetXStats(struct rx_call *rxcall,
487 afs_int32 clientVersionNumber,
488 afs_int32 collectionNumber,
489 afs_int32 * srvVersionNumberP,
491 AFSCB_CollData * dataP)
497 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID *a_uuid)
504 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
508 addr->numberOfInterfaces = 0;
511 /* return all network interface addresses */
512 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
513 for ( i=0; i < afs_cb_interface.numberOfInterfaces; i++) {
514 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
515 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
516 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
524 SRXAFSCB_InitCallBackState2(struct rx_call *a_call, struct interfaceAddr *
531 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID *a_uuid)
537 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
538 afs_uint32 *serverVersion, afs_uint32 *configCount,
545 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
551 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
552 char **a_name, serverList *a_hosts)
558 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
559 afs_int32 *a_srvr_addr, afs_int32 *a_srvr_rank)
565 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call, struct interfaceAddr *
566 addr, Capabilities *capabilities)
572 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
573 char **a_name, serverList *a_hosts)
579 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
580 struct AFSDBCacheEntry64 *a_result)
586 InitializeCBService_LWP(void *unused)
588 struct rx_securityClass *CBsecobj;
589 struct rx_service *CBService;
591 afs_uuid_create(&uuid);
593 CBsecobj = (struct rx_securityClass *)rxnull_NewServerSecurityObject();
595 fprintf(stderr,"rxnull_NewServerSecurityObject failed for callback service.\n");
598 CBService = rx_NewService(0, 1, "afs", &CBsecobj, 1,
599 RXAFSCB_ExecuteRequest);
601 fprintf(stderr,"rx_NewService failed for callback service.\n");
610 InitializeCBService(void)
612 #define RESTOOL_CBPORT 7102
613 #define MAX_PORT_TRIES 1000
614 #define LWP_STACK_SIZE (16 * 1024)
616 #ifdef AFS_PTHREAD_ENV
617 pthread_t CBservicePid, parentPid;
618 pthread_attr_t tattr;
620 PROCESS CBServiceLWP_ID, parentPid;
625 #ifndef NO_AFS_CLIENT
626 if (!CBServiceNeeded)
629 #ifndef AFS_PTHREAD_ENV
630 code = LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid);
631 if (code != LWP_SUCCESS) {
632 fprintf(stderr,"Unable to initialize LWP support, code %d\n",
638 #if defined(AFS_AIX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI_ENV)
640 InitialCBPort = RESTOOL_CBPORT + random() % 1000;
641 #else /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
642 #if defined(AFS_HPUX_ENV)
644 InitialCBPort = RESTOOL_CBPORT + lrand48() % 1000;
645 #else /* AFS_HPUX_ENV */
647 InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
648 #endif /* AFS_HPUX_ENV */
649 #endif /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
651 CBPort = InitialCBPort;
653 code = rx_Init(htons(CBPort));
655 if ((code == RX_ADDRINUSE) &&
656 (CBPort < MAX_PORT_TRIES + InitialCBPort)) {
658 } else if (CBPort < MAX_PORT_TRIES + InitialCBPort) {
659 fprintf(stderr, "rx_Init didn't succeed for callback service."
660 " Tried port numbers %d through %d\n",
661 InitialCBPort, CBPort);
664 fprintf(stderr,"Couldn't initialize callback service "
665 "because too many users are running this program. "
666 "Try again later.\n");
671 #ifdef AFS_PTHREAD_ENV
672 assert(pthread_attr_init(&tattr) == 0);
673 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
674 assert(pthread_create(
675 &CBservicePid, &tattr, InitializeCBService_LWP, 0)
678 code = LWP_CreateProcess(InitializeCBService_LWP, LWP_STACK_SIZE,
679 LWP_MAX_PRIORITY - 2, (int *) 0, "CBService",
681 if (code != LWP_SUCCESS) {
682 fprintf(stderr,"Unable to create the callback service LWP, code %d\n",
691 ScanVnode(char *fname, char *cell)
693 afs_int32 i, code = 0;
696 i = sscanf(fname, "%u.%u.%u",
697 &PioctlInputs.fid.Volume,
698 &PioctlInputs.fid.Vnode,
699 &PioctlInputs.fid.Unique);
701 PioctlInputs.fid.Volume = 0;
702 PioctlInputs.fid.Vnode = 0;
703 PioctlInputs.fid.Unique = 0;
704 fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
708 * The following is used to handle the case of unknown uniquifier. We
709 * just need a valid reference to the volume to direct the RPC to the
710 * right fileserver. Therefore we take the root directory of the volume.
712 if (PioctlInputs.fid.Unique == 0) {
713 PioctlInputs.int32s[0] = PioctlInputs.fid.Vnode;
714 PioctlInputs.fid.Vnode = 1;
715 PioctlInputs.fid.Unique = 1;
721 VLDBInit(int noAuthFlag, struct afsconf_cell *info)
725 code = ugen_ClientInit(noAuthFlag, (char *) AFSDIR_CLIENT_ETC_DIRPATH,
726 info->name, 0, &uclient,
727 NULL, pnp, rxkad_clear,
728 VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
729 0, 0, USER_SERVICE_ID);
735 get_vnode_hosts(char *fname, char **cellp, afs_int32 *hosts, AFSFid *Fid,
738 struct afsconf_dir *tdir;
739 struct vldbentry vldbEntry;
740 afs_int32 i, j, code, *h, len;
741 struct afsconf_cell info;
744 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
746 fprintf(stderr,"Could not process files in configuration directory "
747 "(%s).\n",AFSDIR_CLIENT_ETC_DIRPATH);
752 *cellp = (char *) malloc(MAXCELLCHARS);
753 code = afsconf_GetLocalCell(tdir, *cellp, len);
754 if (code) return code;
756 code = afsconf_GetCellInfo(tdir, *cellp, AFSCONF_VLDBSERVICE, &info);
758 fprintf(stderr,"fs: cell %s not in %s/CellServDB\n",
759 *cellp, AFSDIR_CLIENT_ETC_DIRPATH);
763 i = sscanf(fname, "%u.%u.%u", &Fid->Volume, &Fid->Vnode, &Fid->Unique);
765 fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
768 code = VLDBInit(1, &info);
770 code = ubik_VL_GetEntryByID(uclient, 0, Fid->Volume,
772 if (code == VL_NOENT)
773 fprintf(stderr,"fs: volume %u does not exist in this cell.\n",
775 if (code) return code;
779 if (!onlyRW) mask |= VLSF_RWVOL;
780 for (i=0, j=0; j<vldbEntry.nServers; j++) {
781 if (vldbEntry.serverFlags[j] & mask) {
782 *h++ = ntohl(vldbEntry.serverNumber[j]);
786 for (; i<MAXHOSTS; i++) *h++ = 0;
791 * Determine which AFS cell file 'fn' lives in, the list of servers that
792 * offer it, and the FID.
795 get_file_cell(char *fn, char **cellp, afs_int32 hosts[MAXHOSTS], AFSFid *Fid,
796 struct AFSFetchStatus *Status, afs_int32 create)
800 struct ViceIoctl status;
802 afs_int32 *Tmpafs_int32;
804 memset((char *) Status, 0, sizeof(struct AFSFetchStatus));
805 memset(buf, 0, sizeof(buf));
807 status.out_size = sizeof(buf);
811 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
812 if (code && create) {
816 if ((c = strrchr(buf,'/'))) {
818 code = pioctl(buf,VIOC_FILE_CELL_NAME, &status, 0);
820 fd = open(fn, O_CREAT, 0644);
823 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
827 fprintf(stderr, "Unable to determine cell for %s\n", fn);
831 fprintf(stderr, "(File might not be in AFS)\n");
833 afs_com_err(pnp, code, (char *) 0);
835 *cellp = (char *) malloc(strlen(buf)+1);
837 SetCellFname(*cellp);
838 memset(buf, 0, sizeof(buf));
842 status.out_size = sizeof(buf);
843 code = pioctl(fn, VIOCWHEREIS, &status, 0);
845 fprintf(stderr, "Unable to determine fileservers for %s\n", fn);
850 afs_com_err(pnp, code, (char *) 0);
852 Tmpafs_int32 = (afs_int32 *)buf;
853 for (j=0;j<MAXHOSTS;++j) {
854 hosts[j] = Tmpafs_int32[j];
855 if (!Tmpafs_int32[j])
859 memset(buf, 0, sizeof(buf));
861 status.out_size = sizeof(buf);
864 code = pioctl(fn, VIOCGETFID, &status, 0);
866 fprintf(stderr, "Unable to determine FID for %s\n", fn);
870 afs_com_err(pnp, code, (char *) 0);
873 afs_int32 saveCommand, saveVolume;
875 Tmpafs_int32 = (afs_int32 *)buf;
876 Fid->Volume = Tmpafs_int32[1];
877 Fid->Vnode = Tmpafs_int32[2];
878 Fid->Unique = Tmpafs_int32[3];
879 status.in_size = sizeof(struct FsCmdInputs);
880 status.out_size = sizeof(struct FsCmdOutputs);
881 status.in = (char *) &PioctlInputs;
882 status.out = (char *) &PioctlOutputs;
883 saveCommand = PioctlInputs.command;
884 saveVolume = PioctlInputs.fid.Volume;
885 PioctlInputs.command = 0;
886 PioctlInputs.fid.Volume = 0;
887 if (!pioctl(fn, VIOC_FS_CMD, &status, 0))
888 memcpy((char *)Status, &PioctlOutputs.status,
889 sizeof(struct AFSFetchStatus));
890 PioctlInputs.command = saveCommand;
891 PioctlInputs.fid.Volume = saveVolume;
892 if (create && (Status->Length || Status->Length_hi)) {
893 fprintf(stderr,"AFS file %s not empty, request aborted.\n",
903 DestroyConnections(void)
907 if (!ConnLookupInitialized) return 0;
908 for (i = 0; i < MAX_HOSTS; i++) {
909 if (!ConnLookup[i].conn) break;
910 RXAFS_GiveUpAllCallBacks(ConnLookup[i].conn);
911 rx_DestroyConnection(ConnLookup[i].conn);
920 LogErrors (int level, const char *fmt, ...)
925 return vfprintf(stderr, fmt, ap);
929 readFile(struct cmd_syndesc *as, void *unused)
934 afs_int32 hosts[MAXHOSTS];
937 struct rx_connection *RXConn;
938 struct cellLookup *cl;
939 struct rx_call *tcall;
940 struct AFSVolSync tsync;
941 struct AFSFetchStatus OutStatus;
942 struct AFSCallBack CallBack;
945 afs_int64 length, Len;
951 int bufflen = BUFFLEN;
955 if (as->name[0] == 'f')
957 if (as->parms[2].items)
959 if (as->parms[3].items) {
965 InitializeCBService();
967 gettimeofday (&starttime, &Timezone);
968 fname = as->parms[0].items->data;
970 if (as->parms[1].items)
971 cell = as->parms[1].items->data;
973 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
975 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, 0);
977 fprintf(stderr,"File not found %s\n", fname);
981 fprintf(stderr,"%s is a directory, not a file\n", fname);
985 for (j=0;j<MAXHOSTS;++j) {
988 if (first && as->parms[6].items) {
989 afs_uint32 fields, ip1, ip2, ip3, ip4;
990 fields = sscanf(as->parms[6].items->data, "%d.%d.%d.%d",
991 &ip1, &ip2, &ip3, &ip4);
992 useHost = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
1000 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1001 cl->sc[cl->scIndex], cl->scIndex);
1003 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1007 #ifndef NO_AFS_CLIENT
1009 #endif /* NO_AFS_CLIENT */
1010 code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1012 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for"
1013 " file %s, code was %d\n",
1014 useHost, fname, code);
1017 #ifndef NO_AFS_CLIENT
1019 #endif /* NO_AFS_CLIENT */
1020 gettimeofday(&opentime, &Timezone);
1022 seconds = opentime.tv_sec + opentime.tv_usec *.000001
1023 -starttime.tv_sec - starttime.tv_usec *.000001;
1024 fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1027 Len = OutStatus.Length_hi;
1029 Len += OutStatus.Length;
1032 afs_uint32 high, low;
1034 tcall = rx_NewCall(RXConn);
1035 code = StartAFS_FetchData64 (tcall, &Fid, Pos, Len);
1036 if (code == RXGEN_OPCODE) {
1037 afs_uint32 tmpPos, tmpLen;
1038 tmpPos = Pos; tmpLen = Len;
1039 code = StartAFS_FetchData (tcall, &Fid, Pos, Len);
1040 bytes = rx_Read(tcall, (char *)&low, sizeof(afs_int32));
1041 length = ntohl(low);
1042 if (bytes != 4) code = -3;
1044 bytes = rx_Read(tcall, (char *)&high, 4);
1045 length = ntohl(high);
1047 bytes += rx_Read(tcall, (char *)&low, 4);
1048 length += ntohl(low);
1049 if (bytes != 8) code = -3;
1052 if (code == RXGEN_OPCODE) {
1053 fprintf(stderr, "File server for %s might not be running a"
1054 " multi-resident AFS server\n",
1057 fprintf(stderr, "%s for %s ended with error code %d\n",
1058 (char *) &as->name, fname, code);
1062 if (length > bufflen)
1066 buf = (char *)malloc(len);
1068 fprintf(stderr, "couldn't allocate buffer\n");
1071 while (!code && NonZeroInt64(length)) {
1072 if (length > bufflen)
1076 bytes = rx_Read(tcall, (char *) buf, len);
1081 MD5_Update(&md5, buf, len);
1086 gettimeofday(&now, &Timezone);
1091 code = EndRXAFS_FetchData (tcall, &OutStatus, &CallBack, &tsync);
1092 rx_EndCall(tcall, 0);
1098 gettimeofday(&readtime, &Timezone);
1100 fprintf(stderr,"%s failed with code %d\n",
1101 (char *) &as->name, worstCode);
1104 afs_uint32 md5int[4];
1106 MD5_Final((char *) &md5int[0], &md5);
1107 p = fname + strlen(fname);
1109 if (*(--p) == '/') {
1114 fprintf(stderr, "%08x%08x%08x%08x %s\n",
1115 htonl(md5int[0]), htonl(md5int[1]),
1116 htonl(md5int[2]), htonl(md5int[3]), p);
1119 seconds = readtime.tv_sec + readtime.tv_usec *.000001
1120 -opentime.tv_sec - opentime.tv_usec *.000001;
1121 fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1123 datarate = (xfered >> 20) / seconds;
1124 fprintf(stderr,"Total data rate = %.0f MB/sec. for read\n",
1128 DestroyConnections();
1133 writeFile(struct cmd_syndesc *as, void *unused)
1137 afs_int32 code, localcode = 0;
1138 afs_int32 hosts[MAXHOSTS];
1142 struct rx_connection *RXConn;
1143 struct cellLookup *cl;
1144 struct rx_call *tcall;
1145 struct AFSVolSync tsync;
1146 struct AFSFetchStatus OutStatus;
1147 struct AFSStoreStatus InStatus;
1149 afs_int64 length, Len, synthlength = 0, offset = 0;
1155 afs_int32 byteswritten;
1156 struct wbuf *bufchain = 0;
1157 struct wbuf *previous, *tbuf;
1161 if (as->name[0] == 'f') {
1163 if (as->name[3] == 'a')
1166 if (as->name[0] == 'a')
1168 if (as->parms[2].items)
1170 if (as->parms[3].items)
1172 if (as->parms[4].items) {
1173 code = util_GetInt64(as->parms[4].items->data, &synthlength);
1175 fprintf(stderr, "Invalid value for synthesize length %s\n",
1176 as->parms[4].items->data);
1181 CBServiceNeeded = 1;
1182 InitializeCBService();
1184 if (as->parms[0].items)
1185 fname = as->parms[0].items->data;
1188 if (as->parms[1].items) cell = as->parms[1].items->data;
1190 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
1194 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, append ? 0 : 1);
1197 fprintf(stderr,"File or directory not found: %s\n",
1201 if (Fid.Vnode & 1) {
1202 fprintf(stderr,"%s is a directory, not a file\n", fname);
1206 fprintf(stderr,"AFS file not found: %s\n", fname);
1209 cl = FindCell(cell);
1210 gettimeofday (&starttime, &Timezone);
1212 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1213 cl->sc[cl->scIndex], cl->scIndex);
1215 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1219 InStatus.Mask = AFS_SETMODE + AFS_FSYNC;
1220 InStatus.UnixModeBits = 0644;
1222 Pos = OutStatus.Length_hi;
1223 Pos = (Pos << 32) | OutStatus.Length;
1226 previous = (struct wbuf *)&bufchain;
1231 while (Len<WRITEBUFFLEN) {
1232 tbuf = (struct wbuf *)malloc(sizeof(struct wbuf));
1235 fprintf(stderr, "Couldn't allocate buffer, aborting\n");
1240 memset(tbuf, 0, sizeof(struct wbuf));
1241 tbuf->buflen = BUFFLEN;
1243 afs_int32 ll, l = tbuf->buflen;
1244 if (l > synthlength)
1246 for (ll = 0; ll < l; ll += 4096) {
1247 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1248 (unsigned int)(offset >> 32),
1249 (unsigned int)(offset & 0xffffffff) + ll);
1255 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1261 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1262 previous->next = tbuf;
1266 gettimeofday(&opentime, &Timezone);
1268 seconds = opentime.tv_sec + opentime.tv_usec *.000001
1269 -starttime.tv_sec - starttime.tv_usec *.000001;
1270 fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1274 while (!code && bytes) {
1278 tcall = rx_NewCall(RXConn);
1279 code = StartAFS_StoreData64 (tcall, &Fid, &InStatus, Pos, Len, Pos+Len);
1280 if (code == RXGEN_OPCODE) {
1281 afs_uint32 tmpLen, tmpPos;
1284 if (Pos+Len > 0x7fffffff) {
1285 fprintf(stderr,"AFS fileserver does not support files >= 2 GB\n");
1288 code = StartAFS_StoreData (tcall, &Fid, &InStatus, tmpPos, tmpLen,
1292 fprintf(stderr, "StartRXAFS_StoreData had error code %d\n", code);
1298 for (tbuf= bufchain; tbuf; tbuf=tbuf->next) {
1301 byteswritten = rx_Write(tcall, tbuf->buf, tbuf->used);
1302 if (byteswritten != tbuf->used) {
1303 fprintf(stderr,"Only %d instead of %" AFS_INT64_FMT " bytes transferred by rx_Write()\n", byteswritten, length);
1304 fprintf(stderr, "At %" AFS_UINT64_FMT " bytes from the end\n", length);
1308 xfered += tbuf->used;
1309 gettimeofday(&now, &Timezone);
1312 length -= tbuf->used;
1316 code = EndRXAFS_StoreData64 (tcall, &OutStatus, &tsync);
1318 fprintf(stderr, "EndRXAFS_StoreData64 returned %d\n", code);
1321 code2 = rx_Error(tcall);
1323 fprintf(stderr, "rx_Error returned %d\n", code2);
1326 code2 = rx_EndCall(tcall, localcode);
1328 fprintf(stderr, "rx_EndCall returned %d\n", code2);
1333 fprintf(stderr, "Waiting for busy volume\n");
1340 for (tbuf = bufchain; tbuf; tbuf=tbuf->next) {
1343 afs_int32 ll, l = tbuf->buflen;
1344 if (l > synthlength)
1346 for (ll = 0; ll < l; ll += 4096) {
1347 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1348 (unsigned int)(offset >> 32),
1349 (unsigned int)(offset & 0xffffffff) + ll);
1355 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1359 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1361 bytes += tbuf->used;
1365 gettimeofday(&writetime, &Timezone);
1367 fprintf(stderr,"%s failed with code %d\n", as->name, worstCode);
1368 } else if(verbose) {
1369 seconds = writetime.tv_sec + writetime.tv_usec *.000001
1370 -opentime.tv_sec - opentime.tv_usec *.000001;
1371 fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1373 datarate = (xfered >> 20) / seconds;
1374 fprintf(stderr,"Total data rate = %.0f MB/sec. for write\n",
1379 bufchain = tbuf->next;
1382 DestroyConnections();
1384 afs_uint32 md5int[4];
1386 MD5_Final((char *) &md5int[0], &md5);
1387 p = fname + strlen(fname);
1389 if (*(--p) == '/') {
1394 fprintf(stdout, "%08x%08x%08x%08x %s\n",
1395 htonl(md5int[0]), htonl(md5int[1]),
1396 htonl(md5int[2]), htonl(md5int[3]), p);
1402 FindCell(char *cellName)
1404 char name[MAXCELLCHARS];
1406 struct cellLookup *p, *p2;
1407 static struct afsconf_dir *tdir;
1408 struct ktc_principal sname;
1409 struct ktc_token ttoken;
1410 afs_int32 len, code;
1416 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1418 afsconf_GetLocalCell(tdir, name, len);
1419 np = (char *) &name;
1423 p2 = (struct cellLookup *) &Cells;
1424 for (p = Cells; p; p = p->next) {
1425 if (!strcmp((char *)&p->info.name, np)) {
1426 #ifdef NO_AFS_CLIENT
1427 if (!strcmp((char *)&lastcell, np))
1428 code = VLDBInit(1, &p->info);
1434 p2->next = (struct cellLookup *) malloc(sizeof(struct cellLookup));
1436 memset(p, 0, sizeof(struct cellLookup));
1437 p->next = (struct cellLookup *) 0;
1439 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1440 if (afsconf_GetCellInfo(tdir, np, AFSCONF_VLDBSERVICE, &p->info)) {
1441 p2->next = (struct cellLookup *) 0;
1443 p = (struct cellLookup *) 0;
1445 #ifdef NO_AFS_CLIENT
1446 if (code = VLDBInit(1, &p->info))
1447 fprintf(stderr,"VLDBInit failed for cell %s\n", p->info.name);
1449 strcpy((char *)&sname.cell, (char *)&p->info.name);
1450 sname.instance[0] = 0;
1451 strcpy(sname.name, "afs");
1452 code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL);
1456 if ((ttoken.kvno >= 0) && (ttoken.kvno <= 255))
1457 /* this is a kerberos ticket, set scIndex accordingly */
1460 fprintf(stderr,"funny kvno (%d) in ticket, proceeding\n",
1464 p->sc[2] = (struct rx_securityClass *)
1465 rxkad_NewClientSecurityObject(rxkad_clear, &ttoken.sessionKey,
1466 ttoken.kvno, ttoken.ticketLen,
1469 if (p->scIndex == 0)
1470 p->sc[0] = (struct rx_securityClass *)
1471 rxnull_NewClientSecurityObject();
1480 struct rx_connection *
1481 FindRXConnection(afs_uint32 host, u_short port, u_short service,
1482 struct rx_securityClass *securityObject,
1483 int serviceSecurityIndex)
1487 if (!ConnLookupInitialized) {
1488 memset(ConnLookup, 0, MAX_HOSTS * sizeof(struct connectionLookup));
1489 ConnLookupInitialized = 1;
1492 for (i = 0; i < MAX_HOSTS; i++) {
1493 if ((ConnLookup[i].host == host) && (ConnLookup[i].port == port))
1494 return ConnLookup[i].conn;
1495 if (!ConnLookup[i].conn)
1502 ConnLookup[i].conn = rx_NewConnection(host, port, service, securityObject, serviceSecurityIndex);
1503 if (ConnLookup[i].conn) {
1504 ConnLookup[i].host = host;
1505 ConnLookup[i].port = port;
1508 return ConnLookup[i].conn;