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>
37 #include <sys/types.h>
48 #include <afs/smb_iocons.h>
50 #include <afs/cm_ioctl.h>
51 #include <afs/pioctl_nt.h>
52 #include <WINNT/syscfg.h>
54 #include <sys/param.h>
56 #include <sys/ioctl.h>
57 #include <sys/socket.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
64 #include <afs/venus.h>
67 #include <afs/afsint.h>
68 #define FSINT_COMMON_XG 1
76 #include <afs/cellconfig.h>
77 #include <afs/afsutil.h>
80 #include <afs/afs_consts.h>
81 #include <afs/afscbint.h>
82 #include <afs/vldbint.h>
83 #include <afs/vlserver.h>
84 #include <afs/volser.h>
85 #include <afs/ptint.h>
88 #include <afs/ihandle.h>
89 #include <afs/vnode.h>
90 #include <afs/com_err.h>
98 #include <sys/malloc.h>
102 #include <afs/errors.h>
103 #include <afs/sys_prototypes.h>
104 #include <rx/rx_prototypes.h>
105 #include <hcrypto/md5.h>
108 #define afs_stat stat64
109 #define afs_fstat fstat64
110 #define afs_open open64
111 #else /* !O_LARGEFILE */
112 #define afs_stat stat
113 #define afs_fstat fstat
114 #define afs_open open
115 #endif /* !O_LARGEFILE */
116 #ifdef AFS_PTHREAD_ENV
118 pthread_key_t uclient_key;
121 int readFile(struct cmd_syndesc *as, void *);
122 int writeFile(struct cmd_syndesc *as, void *);
123 struct rx_connection *FindRXConnection(afs_uint32 host, u_short port, u_short service, struct rx_securityClass *securityObject, int serviceSecurityIndex);
124 struct cellLookup * FindCell(char *cellName);
128 static int verbose = 0; /* Set if -verbose option given */
129 static int CBServiceNeeded = 0;
130 static struct timeval starttime, opentime, readtime, writetime;
131 afs_uint64 xfered=0, oldxfered=0;
132 static struct timeval now;
133 struct timezone Timezone;
134 static float seconds, datarate, oldseconds;
135 extern int rxInitDone;
137 static afs_int32 rx_mtu = -1;
139 afs_uint64 transid = 0;
140 afs_uint32 expires = 0;
141 afs_uint32 server_List[MAXHOSTSPERCELL];
144 static struct ubik_client *uclient;
145 #define BUFFLEN 65536
146 #define WRITEBUFFLEN 1024*1024*64
154 afs_uint32 offset; /* offset inside the buffer */
155 afs_uint32 buflen; /* total length == BUFFLEN */
156 afs_uint32 used; /* bytes used inside buffer */
160 struct connectionLookup {
163 struct rx_connection *conn;
167 struct cellLookup *next;
168 struct afsconf_cell info;
169 struct rx_securityClass *sc;
174 struct dirLookup *next;
175 struct dirLookup *prev;
177 struct cellLookup *cell;
179 char name[VL_MAXNAMELEN];
182 struct cellLookup *Cells = 0;
183 struct dirLookup *Dirs = 0;
186 #define MAX_HOSTS 256
187 static struct connectionLookup ConnLookup[MAX_HOSTS];
188 static int ConnLookupInitialized = 0;
190 struct FsCmdInputs PioctlInputs;
191 struct FsCmdOutputs PioctlOutputs;
196 seconds = (float)(now.tv_sec + now.tv_usec *.000001
197 -opentime.tv_sec - opentime.tv_usec *.000001);
198 if ((seconds - oldseconds) > 30.) {
200 tmp = xfered - oldxfered;
201 datarate = ((afs_uint32) (tmp >> 20)) / (seconds - oldseconds);
202 fprintf(stderr,"%llu MB transferred, present date rate = %.03f MB/sec.\n",
203 xfered >> 20, datarate);
205 oldseconds = seconds;
210 SetCellFname(char *name)
212 struct afsconf_dir *tdir;
214 strcpy((char *) &cellFname,"/afs/");
216 strcat((char *) &cellFname, name);
218 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
219 afsconf_GetLocalCell(tdir, &cellFname[5], MAXCELLCHARS);
224 main (int argc, char **argv)
227 struct cmd_syndesc *ts;
229 strcpy(pnp, argv[0]);
231 #ifdef AFS_PTHREAD_ENV
232 assert(pthread_key_create(&uclient_key, NULL) == 0);
234 ts = cmd_CreateSyntax("read", readFile, CMD_REQUIRED,
235 "read a file from AFS");
236 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename");
237 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
238 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
239 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
241 ts = cmd_CreateSyntax("fidread", readFile, CMD_REQUIRED,
242 "read on a non AFS-client a file from AFS");
243 cmd_IsAdministratorCommand(ts);
244 cmd_AddParm(ts, "-fid", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
245 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
246 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
247 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
249 ts = cmd_CreateSyntax("write", writeFile, CMD_REQUIRED,
250 "write a file into AFS");
251 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
252 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
253 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
254 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
255 cmd_AddParm(ts, "-synthesize", CMD_SINGLE, CMD_OPTIONAL, "create data pattern of specified length instead reading from stdin");
257 ts = cmd_CreateSyntax("fidwrite", writeFile, CMD_REQUIRED,
258 "write a file into AFS");
259 cmd_IsAdministratorCommand(ts);
260 cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
261 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
262 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
263 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
265 ts = cmd_CreateSyntax("append", writeFile, CMD_REQUIRED,
266 "append to a file in AFS");
267 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
268 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
269 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
271 ts = cmd_CreateSyntax("fidappend", writeFile, CMD_REQUIRED,
272 "append to a file in AFS");
273 cmd_IsAdministratorCommand(ts);
274 cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
275 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
276 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
278 code = cmd_Dispatch(argc, argv);
284 HandleLocalAuth(struct rx_securityClass **sc, afs_int32 *scIndex)
286 static struct afsconf_dir *tdir = NULL;
290 *scIndex = RX_SECIDX_NULL;
292 tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
294 fprintf(stderr,"Could not open configuration directory: %s.\n",
295 AFSDIR_SERVER_ETC_DIRPATH);
298 code = afsconf_ClientAuth(tdir, sc, scIndex);
300 fprintf(stderr,"afsconf_ClientAuth returned %d\n", code);
307 AFS_Lookup(struct rx_connection *conn, AFSFid *dirfid, char *name,
308 AFSFid *outfid, AFSFetchStatus *outstatus, AFSFetchStatus
309 *dirstatus, AFSCallBack *callback, AFSVolSync *sync)
311 afs_int32 code = VBUSY;
312 while (code == VBUSY) {
313 code = RXAFS_Lookup(conn, dirfid, name, outfid, outstatus, dirstatus,
316 fprintf(stderr, "waiting for busy AFS volume %u.\n",
318 #ifdef AFS_PTHREAD_ENV
329 AFS_FetchStatus(struct rx_connection *conn, AFSFid *fid, AFSFetchStatus
330 *Status, AFSCallBack *callback, AFSVolSync *sync)
332 afs_int32 code = VBUSY;
334 while (code == VBUSY) {
335 code = RXAFS_FetchStatus(conn, fid, Status, callback, sync);
337 fprintf(stderr, "waiting for busy AFS volume %u.\n",
339 #ifdef AFS_PTHREAD_ENV
350 StartAFS_FetchData(struct rx_call *call, AFSFid *fid, afs_int32 pos,
353 afs_int32 code = VBUSY;
354 while (code == VBUSY) {
355 code = StartRXAFS_FetchData (call, fid, pos, len);
357 fprintf(stderr, "waiting for busy AFS volume %u.\n",
359 #ifdef AFS_PTHREAD_ENV
370 StartAFS_FetchData64(struct rx_call *call, AFSFid *fid, afs_int64 pos,
373 afs_int32 code = VBUSY;
374 while (code == VBUSY) {
375 code = StartRXAFS_FetchData64 (call, fid, pos, len);
377 fprintf(stderr, "waiting for busy AFS volume %u.\n",
379 #ifdef AFS_PTHREAD_ENV
390 StartAFS_StoreData(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
391 afs_int32 pos, afs_int32 len, afs_int32 len2)
393 afs_int32 code = VBUSY;
394 while (code == VBUSY) {
395 code = StartRXAFS_StoreData (call, fid, status, pos, len, len2);
397 fprintf(stderr, "waiting for busy AFS volume %u.\n",
399 #ifdef AFS_PTHREAD_ENV
410 StartAFS_StoreData64(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
411 afs_int64 pos, afs_int64 len, afs_int64 len2)
413 afs_int32 code = VBUSY;
414 while (code == VBUSY) {
415 code = StartRXAFS_StoreData64 (call, fid, status, pos, len, len2);
417 fprintf(stderr, "waiting for busy AFS volume %u.\n",
419 #ifdef AFS_PTHREAD_ENV
430 SRXAFSCB_CallBack(struct rx_call *rxcall, AFSCBFids *Fids_Array,
431 AFSCBs *CallBack_Array)
437 SRXAFSCB_InitCallBackState(struct rx_call *rxcall)
443 SRXAFSCB_Probe(struct rx_call *rxcall)
449 SRXAFSCB_GetCE(struct rx_call *rxcall,
451 AFSDBCacheEntry * ce)
457 SRXAFSCB_GetLock(struct rx_call *rxcall,
465 SRXAFSCB_XStatsVersion(struct rx_call *rxcall,
466 afs_int32 * versionNumberP)
472 SRXAFSCB_GetXStats(struct rx_call *rxcall,
473 afs_int32 clientVersionNumber,
474 afs_int32 collectionNumber,
475 afs_int32 * srvVersionNumberP,
477 AFSCB_CollData * dataP)
483 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID *a_uuid)
485 if ( !afs_uuid_equal(&uuid, a_uuid) )
493 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
495 return SRXAFSCB_TellMeAboutYourself(a_call, addr, NULL);
499 SRXAFSCB_InitCallBackState2(struct rx_call *a_call, struct interfaceAddr *
506 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID *a_uuid)
512 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
513 afs_uint32 *serverVersion, afs_uint32 *configCount,
520 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
526 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
527 char **a_name, serverList *a_hosts)
533 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
534 afs_int32 *a_srvr_addr, afs_int32 *a_srvr_rank)
540 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call, struct interfaceAddr *
541 addr, Capabilities *capabilities)
545 int cm_noIPAddr; /* number of client network interfaces */
546 int cm_IPAddr[CM_MAXINTERFACE_ADDR]; /* client's IP address in host order */
547 int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
548 int cm_NetMtu[CM_MAXINTERFACE_ADDR]; /* client's MTU sizes */
549 int cm_NetFlags[CM_MAXINTERFACE_ADDR]; /* network flags */
552 cm_noIPAddr = CM_MAXINTERFACE_ADDR;
553 code = syscfg_GetIFInfo(&cm_noIPAddr,
554 cm_IPAddr, cm_SubnetMask,
555 cm_NetMtu, cm_NetFlags);
557 /* return all network interface addresses */
558 addr->numberOfInterfaces = cm_noIPAddr;
559 for ( i=0; i < cm_noIPAddr; i++ ) {
560 addr->addr_in[i] = cm_IPAddr[i];
561 addr->subnetmask[i] = cm_SubnetMask[i];
562 addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ?
563 cm_NetMtu[i] : rx_mtu;
566 addr->numberOfInterfaces = 0;
569 addr->numberOfInterfaces = 0;
571 /* return all network interface addresses */
572 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
573 for ( i=0; i < afs_cb_interface.numberOfInterfaces; i++) {
574 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
575 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
576 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
584 afs_uint32 *dataBuffP;
587 dataBytes = 1 * sizeof(afs_uint32);
588 dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes);
589 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
590 capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
591 capabilities->Capabilities_val = dataBuffP;
597 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
598 char **a_name, serverList *a_hosts)
604 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
605 struct AFSDBCacheEntry64 *a_result)
611 InitializeCBService_LWP(void *unused)
613 struct rx_securityClass *CBsecobj;
614 struct rx_service *CBService;
616 afs_uuid_create(&uuid);
618 CBsecobj = (struct rx_securityClass *)rxnull_NewServerSecurityObject();
620 fprintf(stderr,"rxnull_NewServerSecurityObject failed for callback service.\n");
623 CBService = rx_NewService(0, 1, "afs", &CBsecobj, 1,
624 RXAFSCB_ExecuteRequest);
626 fprintf(stderr,"rx_NewService failed for callback service.\n");
635 InitializeCBService(void)
637 #define RESTOOL_CBPORT 7102
638 #define MAX_PORT_TRIES 1000
639 #define LWP_STACK_SIZE (16 * 1024)
641 #ifdef AFS_PTHREAD_ENV
642 pthread_t CBservicePid;
643 pthread_attr_t tattr;
645 PROCESS CBServiceLWP_ID, parentPid;
650 #ifndef NO_AFS_CLIENT
651 if (!CBServiceNeeded)
654 #ifndef AFS_PTHREAD_ENV
655 code = LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid);
656 if (code != LWP_SUCCESS) {
657 fprintf(stderr,"Unable to initialize LWP support, code %d\n",
663 #if defined(AFS_AIX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI_ENV)
665 InitialCBPort = RESTOOL_CBPORT + random() % 1000;
666 #else /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
667 #if defined(AFS_HPUX_ENV)
669 InitialCBPort = RESTOOL_CBPORT + lrand48() % 1000;
670 #else /* AFS_HPUX_ENV */
671 #if defined AFS_NT40_ENV
673 InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
674 #else /* AFS_NT40_ENV */
676 InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
677 #endif /* AFS_NT40_ENV */
678 #endif /* AFS_HPUX_ENV */
679 #endif /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
681 CBPort = InitialCBPort;
683 code = rx_Init(htons(CBPort));
685 if ((code == RX_ADDRINUSE) &&
686 (CBPort < MAX_PORT_TRIES + InitialCBPort)) {
688 } else if (CBPort < MAX_PORT_TRIES + InitialCBPort) {
689 fprintf(stderr, "rx_Init didn't succeed for callback service."
690 " Tried port numbers %d through %d\n",
691 InitialCBPort, CBPort);
694 fprintf(stderr,"Couldn't initialize callback service "
695 "because too many users are running this program. "
696 "Try again later.\n");
701 #ifdef AFS_PTHREAD_ENV
702 assert(pthread_attr_init(&tattr) == 0);
703 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
704 assert(pthread_create(
705 &CBservicePid, &tattr, InitializeCBService_LWP, 0)
708 code = LWP_CreateProcess(InitializeCBService_LWP, LWP_STACK_SIZE,
709 LWP_MAX_PRIORITY - 2, (int *) 0, "CBService",
711 if (code != LWP_SUCCESS) {
712 fprintf(stderr,"Unable to create the callback service LWP, code %d\n",
721 ScanVnode(char *fname, char *cell)
723 afs_int32 i, code = 0;
726 i = sscanf(fname, "%u.%u.%u",
727 &PioctlInputs.fid.Volume,
728 &PioctlInputs.fid.Vnode,
729 &PioctlInputs.fid.Unique);
731 PioctlInputs.fid.Volume = 0;
732 PioctlInputs.fid.Vnode = 0;
733 PioctlInputs.fid.Unique = 0;
734 fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
738 * The following is used to handle the case of unknown uniquifier. We
739 * just need a valid reference to the volume to direct the RPC to the
740 * right fileserver. Therefore we take the root directory of the volume.
742 if (PioctlInputs.fid.Unique == 0) {
743 PioctlInputs.int32s[0] = PioctlInputs.fid.Vnode;
744 PioctlInputs.fid.Vnode = 1;
745 PioctlInputs.fid.Unique = 1;
751 VLDBInit(int noAuthFlag, struct afsconf_cell *info)
755 code = ugen_ClientInit(noAuthFlag, (char *) AFSDIR_CLIENT_ETC_DIRPATH,
756 info->name, 0, &uclient,
757 NULL, pnp, rxkad_clear,
758 VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
759 0, 0, USER_SERVICE_ID);
765 get_vnode_hosts(char *fname, char **cellp, afs_int32 *hosts, AFSFid *Fid,
768 struct afsconf_dir *tdir;
769 struct vldbentry vldbEntry;
770 afs_int32 i, j, code, *h, len;
771 struct afsconf_cell info;
774 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
776 fprintf(stderr,"Could not process files in configuration directory "
777 "(%s).\n",AFSDIR_CLIENT_ETC_DIRPATH);
782 *cellp = (char *) malloc(MAXCELLCHARS);
783 code = afsconf_GetLocalCell(tdir, *cellp, len);
784 if (code) return code;
786 code = afsconf_GetCellInfo(tdir, *cellp, AFSCONF_VLDBSERVICE, &info);
788 fprintf(stderr,"fs: cell %s not in %s/CellServDB\n",
789 *cellp, AFSDIR_CLIENT_ETC_DIRPATH);
793 i = sscanf(fname, "%u.%u.%u", &Fid->Volume, &Fid->Vnode, &Fid->Unique);
795 fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
798 code = VLDBInit(1, &info);
800 code = ubik_VL_GetEntryByID(uclient, 0, Fid->Volume,
802 if (code == VL_NOENT)
803 fprintf(stderr,"fs: volume %u does not exist in this cell.\n",
805 if (code) return code;
809 if (!onlyRW) mask |= VLSF_RWVOL;
810 for (i=0, j=0; j<vldbEntry.nServers; j++) {
811 if (vldbEntry.serverFlags[j] & mask) {
812 *h++ = ntohl(vldbEntry.serverNumber[j]);
816 for (; i<AFS_MAXHOSTS; i++) *h++ = 0;
821 * Determine which AFS cell file 'fn' lives in, the list of servers that
822 * offer it, and the FID.
825 get_file_cell(char *fn, char **cellp, afs_int32 hosts[AFS_MAXHOSTS], AFSFid *Fid,
826 struct AFSFetchStatus *Status, afs_int32 create)
830 struct ViceIoctl status;
832 afs_int32 *Tmpafs_int32;
834 memset( Status, 0, sizeof(struct AFSFetchStatus));
835 memset(buf, 0, sizeof(buf));
837 status.out_size = sizeof(buf);
841 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
842 if (code && create) {
847 c = strrchr(buf,'\\');
849 c = strrchr(buf,'/');
853 code = pioctl(buf,VIOC_FILE_CELL_NAME, &status, 0);
855 fd = open(fn, O_CREAT, 0644);
858 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
862 fprintf(stderr, "Unable to determine cell for %s\n", fn);
866 fprintf(stderr, "(File might not be in AFS)\n");
868 afs_com_err(pnp, code, (char *) 0);
870 *cellp = (char *) malloc(strlen(buf)+1);
872 SetCellFname(*cellp);
873 memset(buf, 0, sizeof(buf));
877 status.out_size = sizeof(buf);
878 code = pioctl(fn, VIOCWHEREIS, &status, 0);
880 fprintf(stderr, "Unable to determine fileservers for %s\n", fn);
885 afs_com_err(pnp, code, (char *) 0);
887 Tmpafs_int32 = (afs_int32 *)buf;
888 for (j=0;j<AFS_MAXHOSTS;++j) {
889 hosts[j] = Tmpafs_int32[j];
890 if (!Tmpafs_int32[j])
894 memset(buf, 0, sizeof(buf));
896 status.out_size = sizeof(buf);
899 code = pioctl(fn, VIOCGETFID, &status, 0);
901 fprintf(stderr, "Unable to determine FID for %s\n", fn);
905 afs_com_err(pnp, code, (char *) 0);
908 Tmpafs_int32 = (afs_int32 *)buf;
909 Fid->Volume = Tmpafs_int32[1];
910 Fid->Vnode = Tmpafs_int32[2];
911 Fid->Unique = Tmpafs_int32[3];
918 DestroyConnections(void)
922 if (!ConnLookupInitialized) return 0;
923 for (i = 0; i < MAX_HOSTS; i++) {
924 if (!ConnLookup[i].conn) break;
925 RXAFS_GiveUpAllCallBacks(ConnLookup[i].conn);
926 rx_DestroyConnection(ConnLookup[i].conn);
935 LogErrors (int level, const char *fmt, ...)
940 return vfprintf(stderr, fmt, ap);
944 readFile(struct cmd_syndesc *as, void *unused)
949 afs_int32 hosts[AFS_MAXHOSTS];
952 struct rx_connection *RXConn;
953 struct cellLookup *cl;
954 struct rx_call *tcall;
955 struct AFSVolSync tsync;
956 struct AFSFetchStatus OutStatus;
957 struct AFSCallBack CallBack;
960 afs_int64 length, Len;
966 int bufflen = BUFFLEN;
969 /* stdout on Windows defaults to _O_TEXT mode */
970 _setmode(1, _O_BINARY);
973 if (as->name[0] == 'f')
975 if (as->parms[2].items)
977 if (as->parms[3].items) {
983 InitializeCBService();
985 gettimeofday (&starttime, &Timezone);
986 fname = as->parms[0].items->data;
988 if (as->parms[1].items)
989 cell = as->parms[1].items->data;
991 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
993 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, 0);
995 fprintf(stderr,"File not found %s\n", fname);
999 fprintf(stderr,"%s is a directory, not a file\n", fname);
1002 cl = FindCell(cell);
1003 for (j=0;j<AFS_MAXHOSTS;++j) {
1006 if (first && as->parms[6].items) {
1007 afs_uint32 fields, ip1, ip2, ip3, ip4;
1008 fields = sscanf(as->parms[6].items->data, "%d.%d.%d.%d",
1009 &ip1, &ip2, &ip3, &ip4);
1010 useHost = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
1018 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1019 cl->sc, cl->scIndex);
1021 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1025 code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1027 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for"
1028 " file %s, code was %d\n",
1029 useHost, fname, code);
1032 gettimeofday(&opentime, &Timezone);
1034 seconds = (float)(opentime.tv_sec + opentime.tv_usec *.000001
1035 -starttime.tv_sec - starttime.tv_usec *.000001);
1036 fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1039 Len = OutStatus.Length_hi;
1041 Len += OutStatus.Length;
1044 afs_uint32 high, low;
1046 tcall = rx_NewCall(RXConn);
1047 code = StartAFS_FetchData64 (tcall, &Fid, Pos, Len);
1048 if (code == RXGEN_OPCODE) {
1049 afs_int32 tmpPos, tmpLen;
1050 tmpPos = (afs_int32)Pos; tmpLen = (afs_int32)Len;
1051 code = StartAFS_FetchData (tcall, &Fid, tmpPos, tmpLen);
1052 bytes = rx_Read(tcall, (char *)&low, sizeof(afs_int32));
1053 length = ntohl(low);
1054 if (bytes != 4) code = -3;
1056 bytes = rx_Read(tcall, (char *)&high, 4);
1057 length = ntohl(high);
1059 bytes += rx_Read(tcall, (char *)&low, 4);
1060 length += ntohl(low);
1061 if (bytes != 8) code = -3;
1064 if (code == RXGEN_OPCODE) {
1065 fprintf(stderr, "File server for %s might not be running a"
1066 " multi-resident AFS server\n",
1069 fprintf(stderr, "%s for %s ended with error code %d\n",
1070 (char *) &as->name, fname, code);
1074 if (length > bufflen)
1077 len = (afs_int32) length;
1078 buf = (char *)malloc(len);
1080 fprintf(stderr, "couldn't allocate buffer\n");
1083 while (!code && NonZeroInt64(length)) {
1084 if (length > bufflen)
1087 len = (afs_int32) length;
1088 bytes = rx_Read(tcall, (char *) buf, len);
1093 MD5_Update(&md5, buf, len);
1098 gettimeofday(&now, &Timezone);
1103 code = EndRXAFS_FetchData (tcall, &OutStatus, &CallBack, &tsync);
1104 rx_EndCall(tcall, 0);
1110 gettimeofday(&readtime, &Timezone);
1112 fprintf(stderr,"%s failed with code %d\n",
1113 (char *) &as->name, worstCode);
1116 afs_uint32 md5int[4];
1118 MD5_Final((char *) &md5int[0], &md5);
1120 p = strrchr(fname,'\\');
1122 p = strrchr(fname,'/');
1129 fprintf(stderr, "%08x%08x%08x%08x %s\n",
1130 htonl(md5int[0]), htonl(md5int[1]),
1131 htonl(md5int[2]), htonl(md5int[3]), p);
1134 seconds = (float)(readtime.tv_sec + readtime.tv_usec *.000001
1135 -opentime.tv_sec - opentime.tv_usec *.000001);
1136 fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1138 datarate = (xfered >> 20) / seconds;
1139 fprintf(stderr,"Total data rate = %.03f MB/sec. for read\n",
1143 DestroyConnections();
1148 writeFile(struct cmd_syndesc *as, void *unused)
1152 afs_int32 code, localcode = 0;
1153 afs_int32 hosts[AFS_MAXHOSTS];
1156 struct rx_connection *RXConn;
1157 struct cellLookup *cl;
1158 struct rx_call *tcall;
1159 struct AFSVolSync tsync;
1160 struct AFSFetchStatus OutStatus;
1161 struct AFSStoreStatus InStatus;
1162 struct AFSCallBack CallBack;
1164 afs_int64 length, Len, synthlength = 0, offset = 0;
1170 afs_int32 byteswritten;
1171 struct wbuf *bufchain = 0;
1172 struct wbuf *previous, *tbuf;
1175 /* stdin on Windows defaults to _O_TEXT mode */
1176 _setmode(0, _O_BINARY);
1179 if (as->name[0] == 'f') {
1181 if (as->name[3] == 'a')
1184 if (as->name[0] == 'a')
1186 if (as->parms[2].items)
1188 if (as->parms[3].items)
1190 if (as->parms[4].items) {
1191 code = util_GetInt64(as->parms[4].items->data, &synthlength);
1193 fprintf(stderr, "Invalid value for synthesize length %s\n",
1194 as->parms[4].items->data);
1199 CBServiceNeeded = 1;
1200 InitializeCBService();
1202 if (as->parms[0].items)
1203 fname = as->parms[0].items->data;
1206 if (as->parms[1].items) cell = as->parms[1].items->data;
1208 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
1212 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, append ? 0 : 1);
1214 fprintf(stderr,"File or directory not found: %s\n",
1218 if (Fid.Vnode & 1) {
1219 fprintf(stderr,"%s is a directory, not a file\n", fname);
1223 fprintf(stderr,"AFS file not found: %s\n", fname);
1226 cl = FindCell(cell);
1227 gettimeofday (&starttime, &Timezone);
1229 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1230 cl->sc, cl->scIndex);
1232 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1236 code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1238 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for file %s, code was%d\n",
1239 useHost, fname, code);
1242 if (!append && (OutStatus.Length || OutStatus.Length_hi)) {
1243 fprintf(stderr,"AFS file %s not empty, request aborted.\n", fname);
1244 DestroyConnections();
1247 InStatus.Mask = AFS_SETMODE + AFS_FSYNC;
1248 InStatus.UnixModeBits = 0644;
1250 Pos = OutStatus.Length_hi;
1251 Pos = (Pos << 32) | OutStatus.Length;
1254 previous = (struct wbuf *)&bufchain;
1259 while (Len<WRITEBUFFLEN) {
1260 tbuf = (struct wbuf *)malloc(sizeof(struct wbuf));
1263 fprintf(stderr, "Couldn't allocate buffer, aborting\n");
1268 memset(tbuf, 0, sizeof(struct wbuf));
1269 tbuf->buflen = BUFFLEN;
1271 afs_int64 ll, l = tbuf->buflen;
1272 if (l > synthlength)
1274 for (ll = 0; ll < l; ll += 4096) {
1275 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1276 (unsigned int)((offset + ll) >> 32),
1277 (unsigned int)((offset + ll) & 0xffffffff));
1281 tbuf->used = (afs_int32)l;
1283 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1289 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1290 previous->next = tbuf;
1294 gettimeofday(&opentime, &Timezone);
1296 seconds = (float) (opentime.tv_sec + opentime.tv_usec *.000001
1297 -starttime.tv_sec - starttime.tv_usec *.000001);
1298 fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1302 while (!code && bytes) {
1306 tcall = rx_NewCall(RXConn);
1307 code = StartAFS_StoreData64 (tcall, &Fid, &InStatus, Pos, Len, Pos+Len);
1308 if (code == RXGEN_OPCODE) {
1309 afs_uint32 tmpLen, tmpPos;
1310 tmpPos = (afs_int32) Pos;
1311 tmpLen = (afs_int32) Len;
1312 if (Pos+Len > 0x7fffffff) {
1313 fprintf(stderr,"AFS fileserver does not support files >= 2 GB\n");
1316 code = StartAFS_StoreData (tcall, &Fid, &InStatus, tmpPos, tmpLen,
1320 fprintf(stderr, "StartRXAFS_StoreData had error code %d\n", code);
1326 for (tbuf= bufchain; tbuf; tbuf=tbuf->next) {
1329 byteswritten = rx_Write(tcall, tbuf->buf, tbuf->used);
1330 if (byteswritten != tbuf->used) {
1331 fprintf(stderr,"Only %d instead of %" AFS_INT64_FMT " bytes transferred by rx_Write()\n", byteswritten, length);
1332 fprintf(stderr, "At %" AFS_UINT64_FMT " bytes from the end\n", length);
1336 xfered += tbuf->used;
1337 gettimeofday(&now, &Timezone);
1340 length -= tbuf->used;
1344 code = EndRXAFS_StoreData64 (tcall, &OutStatus, &tsync);
1346 fprintf(stderr, "EndRXAFS_StoreData64 returned %d\n", code);
1349 code2 = rx_Error(tcall);
1351 fprintf(stderr, "rx_Error returned %d\n", code2);
1354 code2 = rx_EndCall(tcall, localcode);
1356 fprintf(stderr, "rx_EndCall returned %d\n", code2);
1361 fprintf(stderr, "Waiting for busy volume\n");
1368 for (tbuf = bufchain; tbuf; tbuf=tbuf->next) {
1371 afs_int64 ll, l = tbuf->buflen;
1372 if (l > synthlength)
1374 for (ll = 0; ll < l; ll += 4096) {
1375 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1376 (unsigned int)((offset + ll) >> 32),
1377 (unsigned int)((offset + ll) & 0xffffffff));
1381 tbuf->used = (afs_int32) l;
1383 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1387 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1389 bytes += tbuf->used;
1393 gettimeofday(&writetime, &Timezone);
1395 fprintf(stderr,"%s failed with code %d\n", as->name, worstCode);
1396 } else if(verbose) {
1397 seconds = (float) (writetime.tv_sec + writetime.tv_usec *.000001
1398 -opentime.tv_sec - opentime.tv_usec *.000001);
1399 fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1401 datarate = (xfered >> 20) / seconds;
1402 fprintf(stderr,"Total data rate = %.03f MB/sec. for write\n",
1407 bufchain = tbuf->next;
1410 DestroyConnections();
1412 afs_uint32 md5int[4];
1414 MD5_Final((char *) &md5int[0], &md5);
1416 p = strrchr(fname,'\\');
1418 p = strrchr(fname,'/');
1425 fprintf(stderr, "%08x%08x%08x%08x %s\n",
1426 htonl(md5int[0]), htonl(md5int[1]),
1427 htonl(md5int[2]), htonl(md5int[3]), p);
1433 FindCell(char *cellName)
1435 char name[MAXCELLCHARS];
1437 struct cellLookup *p, *p2;
1438 static struct afsconf_dir *tdir;
1440 afs_int32 len, code;
1446 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1448 afsconf_GetLocalCell(tdir, name, len);
1449 np = (char *) &name;
1453 p2 = (struct cellLookup *) &Cells;
1454 for (p = Cells; p; p = p->next) {
1455 if (!strcmp((char *)&p->info.name, np)) {
1456 #ifdef NO_AFS_CLIENT
1457 if (!strcmp((char *)&lastcell, np))
1458 code = VLDBInit(1, &p->info);
1464 p2->next = (struct cellLookup *) malloc(sizeof(struct cellLookup));
1466 memset(p, 0, sizeof(struct cellLookup));
1467 p->next = (struct cellLookup *) 0;
1469 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1470 if (afsconf_GetCellInfo(tdir, np, AFSCONF_VLDBSERVICE, &p->info)) {
1471 p2->next = (struct cellLookup *) 0;
1473 p = (struct cellLookup *) 0;
1475 #ifdef NO_AFS_CLIENT
1476 if (code = VLDBInit(1, &p->info))
1477 fprintf(stderr,"VLDBInit failed for cell %s\n", p->info.name);
1479 code = afsconf_ClientAuthToken(&p->info, 0, &p->sc, &p->scIndex, &expires);
1481 p->scIndex = RX_SECIDX_NULL;
1482 p->sc = rxnull_NewClientSecurityObject();
1492 struct rx_connection *
1493 FindRXConnection(afs_uint32 host, u_short port, u_short service,
1494 struct rx_securityClass *securityObject,
1495 int serviceSecurityIndex)
1499 if (!ConnLookupInitialized) {
1500 memset(ConnLookup, 0, MAX_HOSTS * sizeof(struct connectionLookup));
1501 ConnLookupInitialized = 1;
1504 for (i = 0; i < MAX_HOSTS; i++) {
1505 if ((ConnLookup[i].host == host) && (ConnLookup[i].port == port))
1506 return ConnLookup[i].conn;
1507 if (!ConnLookup[i].conn)
1514 ConnLookup[i].conn = rx_NewConnection(host, port, service, securityObject, serviceSecurityIndex);
1515 if (ConnLookup[i].conn) {
1516 ConnLookup[i].host = host;
1517 ConnLookup[i].port = port;
1520 return ConnLookup[i].conn;