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>
34 #include <sys/types.h>
45 #include <afs/smb_iocons.h>
47 #include <afs/cm_ioctl.h>
48 #include <afs/pioctl_nt.h>
50 #include <sys/param.h>
52 #include <sys/ioctl.h>
53 #include <sys/socket.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
60 #include <afs/venus.h>
63 #include <afs/afsint.h>
64 #define FSINT_COMMON_XG 1
72 #include <afs/cellconfig.h>
73 #include <afs/afsutil.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>
84 #include <afs/ihandle.h>
85 #include <afs/vnode.h>
86 #include <afs/com_err.h>
94 #include <sys/malloc.h>
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"
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
114 pthread_key_t uclient_key;
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);
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];
137 static struct ubik_client *uclient;
138 #define BUFFLEN 65536
139 #define WRITEBUFFLEN 1024*1024*64
147 afs_uint32 offset; /* offset inside the buffer */
148 afs_uint32 buflen; /* total length == BUFFLEN */
149 afs_uint32 used; /* bytes used inside buffer */
153 struct connectionLookup {
156 struct rx_connection *conn;
160 struct cellLookup *next;
161 struct afsconf_cell info;
162 struct rx_securityClass *sc[3];
167 struct dirLookup *next;
168 struct dirLookup *prev;
170 struct cellLookup *cell;
172 char name[VL_MAXNAMELEN];
175 struct cellLookup *Cells = 0;
176 struct dirLookup *Dirs = 0;
179 #define MAX_HOSTS 256
180 static struct connectionLookup ConnLookup[MAX_HOSTS];
181 static int ConnLookupInitialized = 0;
183 struct FsCmdInputs PioctlInputs;
184 struct FsCmdOutputs PioctlOutputs;
189 seconds = (float)(now.tv_sec + now.tv_usec *.000001
190 -opentime.tv_sec - opentime.tv_usec *.000001);
191 if ((seconds - oldseconds) > 30.) {
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);
198 oldseconds = seconds;
203 SetCellFname(char *name)
205 struct afsconf_dir *tdir;
207 strcpy((char *) &cellFname,"/afs/");
209 strcat((char *) &cellFname, name);
211 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
212 afsconf_GetLocalCell(tdir, &cellFname[5], MAXCELLCHARS);
217 main (int argc, char **argv)
220 struct cmd_syndesc *ts;
222 strcpy(pnp, argv[0]);
224 #ifdef AFS_PTHREAD_ENV
225 assert(pthread_key_create(&uclient_key, NULL) == 0);
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");
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");
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");
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");
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);
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);
271 code = cmd_Dispatch(argc, argv);
277 HandleLocalAuth(struct rx_securityClass **sc[3], afs_int32 *scIndex)
279 static struct afsconf_dir *tdir = NULL;
280 struct ktc_principal sname;
281 struct ktc_token ttoken;
283 struct ktc_encryptionKey key;
288 tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
290 fprintf(stderr,"Could not open configuration directory: %s.\n",
291 AFSDIR_SERVER_ETC_DIRPATH);
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);
300 fprintf(stderr,"afsconf_GetLatestKey returned %d\n", code);
304 des_init_random_number_generator(ktc_to_cblock(&key));
305 code = des_random_key(ktc_to_cblock(&ttoken.sessionKey));
307 fprintf(stderr,"des_random_key returned %d\n", code);
310 ttoken.ticketLen = MAXKTCTICKETLEN;
311 code = tkt_MakeTicket(ttoken.ticket, &ttoken.ticketLen, &key,
312 AUTH_SUPERUSER, "", sname.cell,
314 &ttoken.sessionKey, host,
315 sname.name, sname.instance);
320 *sc[2] = (struct rx_securityClass *)
321 rxkad_NewClientSecurityObject(rxkad_clear,
322 &ttoken.sessionKey, ttoken.kvno,
323 ttoken.ticketLen, ttoken.ticket);
326 *sc[0] = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
331 AFS_Lookup(struct rx_connection *conn, AFSFid *dirfid, char *name,
332 AFSFid *outfid, AFSFetchStatus *outstatus, AFSFetchStatus
333 *dirstatus, AFSCallBack *callback, AFSVolSync *sync)
335 afs_int32 code = VBUSY;
336 while (code == VBUSY) {
337 code = RXAFS_Lookup(conn, dirfid, name, outfid, outstatus, dirstatus,
340 fprintf(stderr, "waiting for busy AFS volume %u.\n",
342 #ifdef AFS_PTHREAD_ENV
353 AFS_FetchStatus(struct rx_connection *conn, AFSFid *fid, AFSFetchStatus
354 *Status, AFSCallBack *callback, AFSVolSync *sync)
356 afs_int32 code = VBUSY;
358 while (code == VBUSY) {
359 code = RXAFS_FetchStatus(conn, fid, Status, callback, sync);
361 fprintf(stderr, "waiting for busy AFS volume %u.\n",
363 #ifdef AFS_PTHREAD_ENV
374 StartAFS_FetchData(struct rx_call *call, AFSFid *fid, afs_int32 pos,
377 afs_int32 code = VBUSY;
378 while (code == VBUSY) {
379 code = StartRXAFS_FetchData (call, fid, pos, len);
381 fprintf(stderr, "waiting for busy AFS volume %u.\n",
383 #ifdef AFS_PTHREAD_ENV
394 StartAFS_FetchData64(struct rx_call *call, AFSFid *fid, afs_int64 pos,
397 afs_int32 code = VBUSY;
398 while (code == VBUSY) {
399 code = StartRXAFS_FetchData64 (call, fid, pos, len);
401 fprintf(stderr, "waiting for busy AFS volume %u.\n",
403 #ifdef AFS_PTHREAD_ENV
414 StartAFS_StoreData(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
415 afs_int32 pos, afs_int32 len, afs_int32 len2)
417 afs_int32 code = VBUSY;
418 while (code == VBUSY) {
419 code = StartRXAFS_StoreData (call, fid, status, pos, len, len2);
421 fprintf(stderr, "waiting for busy AFS volume %u.\n",
423 #ifdef AFS_PTHREAD_ENV
434 StartAFS_StoreData64(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
435 afs_int64 pos, afs_int64 len, afs_int64 len2)
437 afs_int32 code = VBUSY;
438 while (code == VBUSY) {
439 code = StartRXAFS_StoreData64 (call, fid, status, pos, len, len2);
441 fprintf(stderr, "waiting for busy AFS volume %u.\n",
443 #ifdef AFS_PTHREAD_ENV
454 SRXAFSCB_CallBack(struct rx_call *rxcall, AFSCBFids *Fids_Array,
455 AFSCBs *CallBack_Array)
461 SRXAFSCB_InitCallBackState(struct rx_call *rxcall)
467 SRXAFSCB_Probe(struct rx_call *rxcall)
473 SRXAFSCB_GetCE(struct rx_call *rxcall,
475 AFSDBCacheEntry * ce)
481 SRXAFSCB_GetLock(struct rx_call *rxcall,
489 SRXAFSCB_XStatsVersion(struct rx_call *rxcall,
490 afs_int32 * versionNumberP)
496 SRXAFSCB_GetXStats(struct rx_call *rxcall,
497 afs_int32 clientVersionNumber,
498 afs_int32 collectionNumber,
499 afs_int32 * srvVersionNumberP,
501 AFSCB_CollData * dataP)
507 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID *a_uuid)
514 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
518 addr->numberOfInterfaces = 0;
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]);
534 SRXAFSCB_InitCallBackState2(struct rx_call *a_call, struct interfaceAddr *
541 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID *a_uuid)
547 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
548 afs_uint32 *serverVersion, afs_uint32 *configCount,
555 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
561 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
562 char **a_name, serverList *a_hosts)
568 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
569 afs_int32 *a_srvr_addr, afs_int32 *a_srvr_rank)
575 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call, struct interfaceAddr *
576 addr, Capabilities *capabilities)
582 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
583 char **a_name, serverList *a_hosts)
589 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
590 struct AFSDBCacheEntry64 *a_result)
596 InitializeCBService_LWP(void *unused)
598 struct rx_securityClass *CBsecobj;
599 struct rx_service *CBService;
601 afs_uuid_create(&uuid);
603 CBsecobj = (struct rx_securityClass *)rxnull_NewServerSecurityObject();
605 fprintf(stderr,"rxnull_NewServerSecurityObject failed for callback service.\n");
608 CBService = rx_NewService(0, 1, "afs", &CBsecobj, 1,
609 RXAFSCB_ExecuteRequest);
611 fprintf(stderr,"rx_NewService failed for callback service.\n");
620 InitializeCBService(void)
622 #define RESTOOL_CBPORT 7102
623 #define MAX_PORT_TRIES 1000
624 #define LWP_STACK_SIZE (16 * 1024)
626 #ifdef AFS_PTHREAD_ENV
627 pthread_t CBservicePid;
628 pthread_attr_t tattr;
630 PROCESS CBServiceLWP_ID, parentPid;
635 #ifndef NO_AFS_CLIENT
636 if (!CBServiceNeeded)
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",
648 #if defined(AFS_AIX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI_ENV)
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)
654 InitialCBPort = RESTOOL_CBPORT + lrand48() % 1000;
655 #else /* AFS_HPUX_ENV */
656 #if defined AFS_NT40_ENV
658 InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
659 #else /* AFS_NT40_ENV */
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 */
666 CBPort = InitialCBPort;
668 code = rx_Init(htons(CBPort));
670 if ((code == RX_ADDRINUSE) &&
671 (CBPort < MAX_PORT_TRIES + InitialCBPort)) {
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);
679 fprintf(stderr,"Couldn't initialize callback service "
680 "because too many users are running this program. "
681 "Try again later.\n");
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)
693 code = LWP_CreateProcess(InitializeCBService_LWP, LWP_STACK_SIZE,
694 LWP_MAX_PRIORITY - 2, (int *) 0, "CBService",
696 if (code != LWP_SUCCESS) {
697 fprintf(stderr,"Unable to create the callback service LWP, code %d\n",
706 ScanVnode(char *fname, char *cell)
708 afs_int32 i, code = 0;
711 i = sscanf(fname, "%u.%u.%u",
712 &PioctlInputs.fid.Volume,
713 &PioctlInputs.fid.Vnode,
714 &PioctlInputs.fid.Unique);
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);
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.
727 if (PioctlInputs.fid.Unique == 0) {
728 PioctlInputs.int32s[0] = PioctlInputs.fid.Vnode;
729 PioctlInputs.fid.Vnode = 1;
730 PioctlInputs.fid.Unique = 1;
736 VLDBInit(int noAuthFlag, struct afsconf_cell *info)
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);
750 get_vnode_hosts(char *fname, char **cellp, afs_int32 *hosts, AFSFid *Fid,
753 struct afsconf_dir *tdir;
754 struct vldbentry vldbEntry;
755 afs_int32 i, j, code, *h, len;
756 struct afsconf_cell info;
759 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
761 fprintf(stderr,"Could not process files in configuration directory "
762 "(%s).\n",AFSDIR_CLIENT_ETC_DIRPATH);
767 *cellp = (char *) malloc(MAXCELLCHARS);
768 code = afsconf_GetLocalCell(tdir, *cellp, len);
769 if (code) return code;
771 code = afsconf_GetCellInfo(tdir, *cellp, AFSCONF_VLDBSERVICE, &info);
773 fprintf(stderr,"fs: cell %s not in %s/CellServDB\n",
774 *cellp, AFSDIR_CLIENT_ETC_DIRPATH);
778 i = sscanf(fname, "%u.%u.%u", &Fid->Volume, &Fid->Vnode, &Fid->Unique);
780 fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
783 code = VLDBInit(1, &info);
785 code = ubik_VL_GetEntryByID(uclient, 0, Fid->Volume,
787 if (code == VL_NOENT)
788 fprintf(stderr,"fs: volume %u does not exist in this cell.\n",
790 if (code) return code;
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]);
801 for (; i<AFS_MAXHOSTS; i++) *h++ = 0;
806 * Determine which AFS cell file 'fn' lives in, the list of servers that
807 * offer it, and the FID.
810 get_file_cell(char *fn, char **cellp, afs_int32 hosts[AFS_MAXHOSTS], AFSFid *Fid,
811 struct AFSFetchStatus *Status, afs_int32 create)
815 struct ViceIoctl status;
817 afs_int32 *Tmpafs_int32;
819 memset( Status, 0, sizeof(struct AFSFetchStatus));
820 memset(buf, 0, sizeof(buf));
822 status.out_size = sizeof(buf);
826 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
827 if (code && create) {
831 if ((c = strrchr(buf,'/'))) {
833 code = pioctl(buf,VIOC_FILE_CELL_NAME, &status, 0);
835 fd = open(fn, O_CREAT, 0644);
838 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
842 fprintf(stderr, "Unable to determine cell for %s\n", fn);
846 fprintf(stderr, "(File might not be in AFS)\n");
848 afs_com_err(pnp, code, (char *) 0);
850 *cellp = (char *) malloc(strlen(buf)+1);
852 SetCellFname(*cellp);
853 memset(buf, 0, sizeof(buf));
857 status.out_size = sizeof(buf);
858 code = pioctl(fn, VIOCWHEREIS, &status, 0);
860 fprintf(stderr, "Unable to determine fileservers for %s\n", fn);
865 afs_com_err(pnp, code, (char *) 0);
867 Tmpafs_int32 = (afs_int32 *)buf;
868 for (j=0;j<AFS_MAXHOSTS;++j) {
869 hosts[j] = Tmpafs_int32[j];
870 if (!Tmpafs_int32[j])
874 memset(buf, 0, sizeof(buf));
876 status.out_size = sizeof(buf);
879 code = pioctl(fn, VIOCGETFID, &status, 0);
881 fprintf(stderr, "Unable to determine FID for %s\n", fn);
885 afs_com_err(pnp, code, (char *) 0);
888 Tmpafs_int32 = (afs_int32 *)buf;
889 Fid->Volume = Tmpafs_int32[1];
890 Fid->Vnode = Tmpafs_int32[2];
891 Fid->Unique = Tmpafs_int32[3];
898 DestroyConnections(void)
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);
915 LogErrors (int level, const char *fmt, ...)
920 return vfprintf(stderr, fmt, ap);
924 readFile(struct cmd_syndesc *as, void *unused)
929 afs_int32 hosts[AFS_MAXHOSTS];
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;
940 afs_int64 length, Len;
946 int bufflen = BUFFLEN;
950 if (as->name[0] == 'f')
952 if (as->parms[2].items)
954 if (as->parms[3].items) {
960 InitializeCBService();
962 gettimeofday (&starttime, &Timezone);
963 fname = as->parms[0].items->data;
965 if (as->parms[1].items)
966 cell = as->parms[1].items->data;
968 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
970 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, 0);
972 fprintf(stderr,"File not found %s\n", fname);
976 fprintf(stderr,"%s is a directory, not a file\n", fname);
980 for (j=0;j<AFS_MAXHOSTS;++j) {
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;
995 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
996 cl->sc[cl->scIndex], cl->scIndex);
998 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1002 #ifndef NO_AFS_CLIENT
1004 #endif /* NO_AFS_CLIENT */
1005 code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1007 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for"
1008 " file %s, code was %d\n",
1009 useHost, fname, code);
1012 #ifndef NO_AFS_CLIENT
1014 #endif /* NO_AFS_CLIENT */
1015 gettimeofday(&opentime, &Timezone);
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",
1022 Len = OutStatus.Length_hi;
1024 Len += OutStatus.Length;
1027 afs_uint32 high, low;
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;
1039 bytes = rx_Read(tcall, (char *)&high, 4);
1040 length = ntohl(high);
1042 bytes += rx_Read(tcall, (char *)&low, 4);
1043 length += ntohl(low);
1044 if (bytes != 8) code = -3;
1047 if (code == RXGEN_OPCODE) {
1048 fprintf(stderr, "File server for %s might not be running a"
1049 " multi-resident AFS server\n",
1052 fprintf(stderr, "%s for %s ended with error code %d\n",
1053 (char *) &as->name, fname, code);
1057 if (length > bufflen)
1060 len = (afs_int32) length;
1061 buf = (char *)malloc(len);
1063 fprintf(stderr, "couldn't allocate buffer\n");
1066 while (!code && NonZeroInt64(length)) {
1067 if (length > bufflen)
1070 len = (afs_int32) length;
1071 bytes = rx_Read(tcall, (char *) buf, len);
1076 MD5_Update(&md5, buf, len);
1081 gettimeofday(&now, &Timezone);
1086 code = EndRXAFS_FetchData (tcall, &OutStatus, &CallBack, &tsync);
1087 rx_EndCall(tcall, 0);
1093 gettimeofday(&readtime, &Timezone);
1095 fprintf(stderr,"%s failed with code %d\n",
1096 (char *) &as->name, worstCode);
1099 afs_uint32 md5int[4];
1101 MD5_Final((char *) &md5int[0], &md5);
1102 p = fname + strlen(fname);
1104 if (*(--p) == '/') {
1109 fprintf(stderr, "%08x%08x%08x%08x %s\n",
1110 htonl(md5int[0]), htonl(md5int[1]),
1111 htonl(md5int[2]), htonl(md5int[3]), p);
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",
1118 datarate = (xfered >> 20) / seconds;
1119 fprintf(stderr,"Total data rate = %.0f MB/sec. for read\n",
1123 DestroyConnections();
1128 writeFile(struct cmd_syndesc *as, void *unused)
1132 afs_int32 code, localcode = 0;
1133 afs_int32 hosts[AFS_MAXHOSTS];
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;
1145 afs_int64 length, Len, synthlength = 0, offset = 0;
1151 afs_int32 byteswritten;
1152 struct wbuf *bufchain = 0;
1153 struct wbuf *previous, *tbuf;
1157 if (as->name[0] == 'f') {
1159 if (as->name[3] == 'a')
1162 if (as->name[0] == 'a')
1164 if (as->parms[2].items)
1166 if (as->parms[3].items)
1168 if (as->parms[4].items) {
1169 code = util_GetInt64(as->parms[4].items->data, &synthlength);
1171 fprintf(stderr, "Invalid value for synthesize length %s\n",
1172 as->parms[4].items->data);
1177 CBServiceNeeded = 1;
1178 InitializeCBService();
1180 if (as->parms[0].items)
1181 fname = as->parms[0].items->data;
1184 if (as->parms[1].items) cell = as->parms[1].items->data;
1186 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
1190 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, append ? 0 : 1);
1192 fprintf(stderr,"File or directory not found: %s\n",
1196 if (Fid.Vnode & 1) {
1197 fprintf(stderr,"%s is a directory, not a file\n", fname);
1201 fprintf(stderr,"AFS file not found: %s\n", fname);
1204 cl = FindCell(cell);
1205 gettimeofday (&starttime, &Timezone);
1207 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1208 cl->sc[cl->scIndex], cl->scIndex);
1210 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1214 code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1216 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for file %s, code was%d\n",
1217 useHost, fname, code);
1220 if (!append && (OutStatus.Length || OutStatus.Length_hi)) {
1221 fprintf(stderr,"AFS file %s not empty, request aborted.\n", fname);
1222 DestroyConnections();
1225 InStatus.Mask = AFS_SETMODE + AFS_FSYNC;
1226 InStatus.UnixModeBits = 0644;
1228 Pos = OutStatus.Length_hi;
1229 Pos = (Pos << 32) | OutStatus.Length;
1232 previous = (struct wbuf *)&bufchain;
1237 while (Len<WRITEBUFFLEN) {
1238 tbuf = (struct wbuf *)malloc(sizeof(struct wbuf));
1241 fprintf(stderr, "Couldn't allocate buffer, aborting\n");
1246 memset(tbuf, 0, sizeof(struct wbuf));
1247 tbuf->buflen = BUFFLEN;
1249 afs_int64 ll, l = tbuf->buflen;
1250 if (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));
1259 tbuf->used = (afs_int32)l;
1261 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1267 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1268 previous->next = tbuf;
1272 gettimeofday(&opentime, &Timezone);
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",
1280 while (!code && bytes) {
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");
1294 code = StartAFS_StoreData (tcall, &Fid, &InStatus, tmpPos, tmpLen,
1298 fprintf(stderr, "StartRXAFS_StoreData had error code %d\n", code);
1304 for (tbuf= bufchain; tbuf; tbuf=tbuf->next) {
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);
1314 xfered += tbuf->used;
1315 gettimeofday(&now, &Timezone);
1318 length -= tbuf->used;
1322 code = EndRXAFS_StoreData64 (tcall, &OutStatus, &tsync);
1324 fprintf(stderr, "EndRXAFS_StoreData64 returned %d\n", code);
1327 code2 = rx_Error(tcall);
1329 fprintf(stderr, "rx_Error returned %d\n", code2);
1332 code2 = rx_EndCall(tcall, localcode);
1334 fprintf(stderr, "rx_EndCall returned %d\n", code2);
1339 fprintf(stderr, "Waiting for busy volume\n");
1346 for (tbuf = bufchain; tbuf; tbuf=tbuf->next) {
1349 afs_int64 ll, l = tbuf->buflen;
1350 if (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));
1359 tbuf->used = (afs_int32) l;
1361 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1365 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1367 bytes += tbuf->used;
1371 gettimeofday(&writetime, &Timezone);
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",
1379 datarate = (xfered >> 20) / seconds;
1380 fprintf(stderr,"Total data rate = %.0f MB/sec. for write\n",
1385 bufchain = tbuf->next;
1388 DestroyConnections();
1390 afs_uint32 md5int[4];
1392 MD5_Final((char *) &md5int[0], &md5);
1393 p = fname + strlen(fname);
1395 if (*(--p) == '/') {
1400 fprintf(stdout, "%08x%08x%08x%08x %s\n",
1401 htonl(md5int[0]), htonl(md5int[1]),
1402 htonl(md5int[2]), htonl(md5int[3]), p);
1408 FindCell(char *cellName)
1410 char name[MAXCELLCHARS];
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;
1422 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1424 afsconf_GetLocalCell(tdir, name, len);
1425 np = (char *) &name;
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);
1440 p2->next = (struct cellLookup *) malloc(sizeof(struct cellLookup));
1442 memset(p, 0, sizeof(struct cellLookup));
1443 p->next = (struct cellLookup *) 0;
1445 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1446 if (afsconf_GetCellInfo(tdir, np, AFSCONF_VLDBSERVICE, &p->info)) {
1447 p2->next = (struct cellLookup *) 0;
1449 p = (struct cellLookup *) 0;
1451 #ifdef NO_AFS_CLIENT
1452 if (code = VLDBInit(1, &p->info))
1453 fprintf(stderr,"VLDBInit failed for cell %s\n", p->info.name);
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);
1462 if ((ttoken.kvno >= 0) && (ttoken.kvno <= 255))
1463 /* this is a kerberos ticket, set scIndex accordingly */
1466 fprintf(stderr,"funny kvno (%d) in ticket, proceeding\n",
1470 p->sc[2] = (struct rx_securityClass *)
1471 rxkad_NewClientSecurityObject(rxkad_clear, &ttoken.sessionKey,
1472 ttoken.kvno, ttoken.ticketLen,
1475 if (p->scIndex == 0)
1476 p->sc[0] = (struct rx_securityClass *)
1477 rxnull_NewClientSecurityObject();
1486 struct rx_connection *
1487 FindRXConnection(afs_uint32 host, u_short port, u_short service,
1488 struct rx_securityClass *securityObject,
1489 int serviceSecurityIndex)
1493 if (!ConnLookupInitialized) {
1494 memset(ConnLookup, 0, MAX_HOSTS * sizeof(struct connectionLookup));
1495 ConnLookupInitialized = 1;
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)
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;
1514 return ConnLookup[i].conn;