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>
40 #include <afs/smb_iocons.h>
42 #include <afs/cm_ioctl.h>
43 #include <afs/pioctl_nt.h>
44 #include <WINNT/syscfg.h>
46 #include <afs/venus.h>
47 #include <afs/afsint.h>
48 #define FSINT_COMMON_XG 1
53 #include <afs/cellconfig.h>
54 #include <afs/afsutil.h>
57 #include <afs/afs_consts.h>
58 #include <afs/afscbint.h>
59 #include <afs/vldbint.h>
60 #include <afs/vlserver.h>
61 #include <afs/volser.h>
62 #include <afs/ptint.h>
65 #include <afs/ihandle.h>
66 #include <afs/vnode.h>
67 #include <afs/com_err.h>
72 #include <hcrypto/md5.h>
74 #include <afs/errors.h>
75 #include <afs/sys_prototypes.h>
76 #include <rx/rx_prototypes.h>
78 #ifdef AFS_PTHREAD_ENV
80 pthread_key_t uclient_key;
83 int readFile(struct cmd_syndesc *as, void *);
84 int writeFile(struct cmd_syndesc *as, void *);
85 struct rx_connection *FindRXConnection(afs_uint32 host, u_short port, u_short service, struct rx_securityClass *securityObject, int serviceSecurityIndex);
86 struct cellLookup * FindCell(char *cellName);
90 static int verbose = 0; /* Set if -verbose option given */
91 static int CBServiceNeeded = 0;
92 static struct timeval starttime, opentime, readtime, writetime;
93 afs_uint64 xfered=0, oldxfered=0;
94 static struct timeval now;
95 static float seconds, datarate, oldseconds;
96 extern int rxInitDone;
98 static afs_int32 rx_mtu = -1;
100 afs_uint64 transid = 0;
101 afs_uint32 expires = 0;
102 afs_uint32 server_List[MAXHOSTSPERCELL];
105 static struct ubik_client *uclient;
106 #define BUFFLEN 65536
107 #define WRITEBUFFLEN 1024*1024*64
115 afs_uint32 offset; /* offset inside the buffer */
116 afs_uint32 buflen; /* total length == BUFFLEN */
117 afs_uint32 used; /* bytes used inside buffer */
121 struct connectionLookup {
124 struct rx_connection *conn;
128 struct cellLookup *next;
129 struct afsconf_cell info;
130 struct rx_securityClass *sc;
135 struct dirLookup *next;
136 struct dirLookup *prev;
138 struct cellLookup *cell;
140 char name[VL_MAXNAMELEN];
143 struct cellLookup *Cells = 0;
144 struct dirLookup *Dirs = 0;
147 #define MAX_HOSTS 256
148 static struct connectionLookup ConnLookup[MAX_HOSTS];
149 static int ConnLookupInitialized = 0;
151 struct FsCmdInputs PioctlInputs;
152 struct FsCmdOutputs PioctlOutputs;
157 seconds = (float)(now.tv_sec + now.tv_usec *.000001
158 -opentime.tv_sec - opentime.tv_usec *.000001);
159 if ((seconds - oldseconds) > 30.) {
161 tmp = xfered - oldxfered;
162 datarate = ((afs_uint32) (tmp >> 20)) / (seconds - oldseconds);
163 fprintf(stderr,"%llu MB transferred, present date rate = %.03f MB/sec.\n",
164 xfered >> 20, datarate);
166 oldseconds = seconds;
171 SetCellFname(char *name)
173 struct afsconf_dir *tdir;
175 strcpy((char *) &cellFname,"/afs/");
177 strcat((char *) &cellFname, name);
179 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
180 afsconf_GetLocalCell(tdir, &cellFname[5], MAXCELLCHARS);
185 main (int argc, char **argv)
188 struct cmd_syndesc *ts;
190 strcpy(pnp, argv[0]);
192 #ifdef AFS_PTHREAD_ENV
193 assert(pthread_key_create(&uclient_key, NULL) == 0);
195 ts = cmd_CreateSyntax("read", readFile, CMD_REQUIRED,
196 "read a file from AFS");
197 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename");
198 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
199 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
200 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
202 ts = cmd_CreateSyntax("fidread", readFile, CMD_REQUIRED,
203 "read on a non AFS-client a file from AFS");
204 cmd_IsAdministratorCommand(ts);
205 cmd_AddParm(ts, "-fid", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
206 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
207 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
208 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
210 ts = cmd_CreateSyntax("write", writeFile, CMD_REQUIRED,
211 "write a file into AFS");
212 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
213 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
214 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
215 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
216 cmd_AddParm(ts, "-synthesize", CMD_SINGLE, CMD_OPTIONAL, "create data pattern of specified length instead reading from stdin");
218 ts = cmd_CreateSyntax("fidwrite", writeFile, CMD_REQUIRED,
219 "write a file into AFS");
220 cmd_IsAdministratorCommand(ts);
221 cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
222 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
223 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
224 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
226 ts = cmd_CreateSyntax("append", writeFile, CMD_REQUIRED,
227 "append to a file in AFS");
228 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
229 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
230 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
232 ts = cmd_CreateSyntax("fidappend", writeFile, CMD_REQUIRED,
233 "append to a file in AFS");
234 cmd_IsAdministratorCommand(ts);
235 cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
236 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
237 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
239 code = cmd_Dispatch(argc, argv);
245 HandleLocalAuth(struct rx_securityClass **sc, afs_int32 *scIndex)
247 static struct afsconf_dir *tdir = NULL;
251 *scIndex = RX_SECIDX_NULL;
253 tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
255 fprintf(stderr,"Could not open configuration directory: %s.\n",
256 AFSDIR_SERVER_ETC_DIRPATH);
259 code = afsconf_ClientAuth(tdir, sc, scIndex);
261 fprintf(stderr,"afsconf_ClientAuth returned %d\n", code);
268 AFS_Lookup(struct rx_connection *conn, AFSFid *dirfid, char *name,
269 AFSFid *outfid, AFSFetchStatus *outstatus, AFSFetchStatus
270 *dirstatus, AFSCallBack *callback, AFSVolSync *sync)
272 afs_int32 code = VBUSY;
273 while (code == VBUSY) {
274 code = RXAFS_Lookup(conn, dirfid, name, outfid, outstatus, dirstatus,
277 fprintf(stderr, "waiting for busy AFS volume %u.\n",
279 #ifdef AFS_PTHREAD_ENV
290 AFS_FetchStatus(struct rx_connection *conn, AFSFid *fid, AFSFetchStatus
291 *Status, AFSCallBack *callback, AFSVolSync *sync)
293 afs_int32 code = VBUSY;
295 while (code == VBUSY) {
296 code = RXAFS_FetchStatus(conn, fid, Status, callback, sync);
298 fprintf(stderr, "waiting for busy AFS volume %u.\n",
300 #ifdef AFS_PTHREAD_ENV
311 StartAFS_FetchData(struct rx_call *call, AFSFid *fid, afs_int32 pos,
314 afs_int32 code = VBUSY;
315 while (code == VBUSY) {
316 code = StartRXAFS_FetchData (call, fid, pos, len);
318 fprintf(stderr, "waiting for busy AFS volume %u.\n",
320 #ifdef AFS_PTHREAD_ENV
331 StartAFS_FetchData64(struct rx_call *call, AFSFid *fid, afs_int64 pos,
334 afs_int32 code = VBUSY;
335 while (code == VBUSY) {
336 code = StartRXAFS_FetchData64 (call, fid, pos, len);
338 fprintf(stderr, "waiting for busy AFS volume %u.\n",
340 #ifdef AFS_PTHREAD_ENV
351 StartAFS_StoreData(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
352 afs_int32 pos, afs_int32 len, afs_int32 len2)
354 afs_int32 code = VBUSY;
355 while (code == VBUSY) {
356 code = StartRXAFS_StoreData (call, fid, status, pos, len, len2);
358 fprintf(stderr, "waiting for busy AFS volume %u.\n",
360 #ifdef AFS_PTHREAD_ENV
371 StartAFS_StoreData64(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
372 afs_int64 pos, afs_int64 len, afs_int64 len2)
374 afs_int32 code = VBUSY;
375 while (code == VBUSY) {
376 code = StartRXAFS_StoreData64 (call, fid, status, pos, len, len2);
378 fprintf(stderr, "waiting for busy AFS volume %u.\n",
380 #ifdef AFS_PTHREAD_ENV
391 SRXAFSCB_CallBack(struct rx_call *rxcall, AFSCBFids *Fids_Array,
392 AFSCBs *CallBack_Array)
398 SRXAFSCB_InitCallBackState(struct rx_call *rxcall)
404 SRXAFSCB_Probe(struct rx_call *rxcall)
410 SRXAFSCB_GetCE(struct rx_call *rxcall,
412 AFSDBCacheEntry * ce)
418 SRXAFSCB_GetLock(struct rx_call *rxcall,
426 SRXAFSCB_XStatsVersion(struct rx_call *rxcall,
427 afs_int32 * versionNumberP)
433 SRXAFSCB_GetXStats(struct rx_call *rxcall,
434 afs_int32 clientVersionNumber,
435 afs_int32 collectionNumber,
436 afs_int32 * srvVersionNumberP,
438 AFSCB_CollData * dataP)
444 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID *a_uuid)
446 if ( !afs_uuid_equal(&uuid, a_uuid) )
454 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
456 return SRXAFSCB_TellMeAboutYourself(a_call, addr, NULL);
460 SRXAFSCB_InitCallBackState2(struct rx_call *a_call, struct interfaceAddr *
467 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID *a_uuid)
473 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
474 afs_uint32 *serverVersion, afs_uint32 *configCount,
481 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
487 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
488 char **a_name, serverList *a_hosts)
494 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
495 afs_int32 *a_srvr_addr, afs_int32 *a_srvr_rank)
501 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call, struct interfaceAddr *
502 addr, Capabilities *capabilities)
506 int cm_noIPAddr; /* number of client network interfaces */
507 int cm_IPAddr[CM_MAXINTERFACE_ADDR]; /* client's IP address in host order */
508 int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
509 int cm_NetMtu[CM_MAXINTERFACE_ADDR]; /* client's MTU sizes */
510 int cm_NetFlags[CM_MAXINTERFACE_ADDR]; /* network flags */
513 cm_noIPAddr = CM_MAXINTERFACE_ADDR;
514 code = syscfg_GetIFInfo(&cm_noIPAddr,
515 cm_IPAddr, cm_SubnetMask,
516 cm_NetMtu, cm_NetFlags);
518 /* return all network interface addresses */
519 addr->numberOfInterfaces = cm_noIPAddr;
520 for ( i=0; i < cm_noIPAddr; i++ ) {
521 addr->addr_in[i] = cm_IPAddr[i];
522 addr->subnetmask[i] = cm_SubnetMask[i];
523 addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ?
524 cm_NetMtu[i] : rx_mtu;
527 addr->numberOfInterfaces = 0;
530 addr->numberOfInterfaces = 0;
532 /* return all network interface addresses */
533 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
534 for ( i=0; i < afs_cb_interface.numberOfInterfaces; i++) {
535 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
536 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
537 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
545 afs_uint32 *dataBuffP;
548 dataBytes = 1 * sizeof(afs_uint32);
549 dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes);
550 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
551 capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
552 capabilities->Capabilities_val = dataBuffP;
558 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
559 char **a_name, serverList *a_hosts)
565 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
566 struct AFSDBCacheEntry64 *a_result)
572 InitializeCBService_LWP(void *unused)
574 struct rx_securityClass *CBsecobj;
575 struct rx_service *CBService;
577 afs_uuid_create(&uuid);
579 CBsecobj = (struct rx_securityClass *)rxnull_NewServerSecurityObject();
581 fprintf(stderr,"rxnull_NewServerSecurityObject failed for callback service.\n");
584 CBService = rx_NewService(0, 1, "afs", &CBsecobj, 1,
585 RXAFSCB_ExecuteRequest);
587 fprintf(stderr,"rx_NewService failed for callback service.\n");
596 InitializeCBService(void)
598 #define RESTOOL_CBPORT 7102
599 #define MAX_PORT_TRIES 1000
600 #define LWP_STACK_SIZE (16 * 1024)
602 #ifdef AFS_PTHREAD_ENV
603 pthread_t CBservicePid;
604 pthread_attr_t tattr;
606 PROCESS CBServiceLWP_ID, parentPid;
611 #ifndef NO_AFS_CLIENT
612 if (!CBServiceNeeded)
615 #ifndef AFS_PTHREAD_ENV
616 code = LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid);
617 if (code != LWP_SUCCESS) {
618 fprintf(stderr,"Unable to initialize LWP support, code %d\n",
624 #if defined(AFS_AIX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI_ENV)
626 InitialCBPort = RESTOOL_CBPORT + random() % 1000;
627 #else /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
628 #if defined(AFS_HPUX_ENV)
630 InitialCBPort = RESTOOL_CBPORT + lrand48() % 1000;
631 #else /* AFS_HPUX_ENV */
632 #if defined AFS_NT40_ENV
634 InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
635 #else /* AFS_NT40_ENV */
637 InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
638 #endif /* AFS_NT40_ENV */
639 #endif /* AFS_HPUX_ENV */
640 #endif /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
642 CBPort = InitialCBPort;
644 code = rx_Init(htons(CBPort));
646 if ((code == RX_ADDRINUSE) &&
647 (CBPort < MAX_PORT_TRIES + InitialCBPort)) {
649 } else if (CBPort < MAX_PORT_TRIES + InitialCBPort) {
650 fprintf(stderr, "rx_Init didn't succeed for callback service."
651 " Tried port numbers %d through %d\n",
652 InitialCBPort, CBPort);
655 fprintf(stderr,"Couldn't initialize callback service "
656 "because too many users are running this program. "
657 "Try again later.\n");
662 #ifdef AFS_PTHREAD_ENV
663 assert(pthread_attr_init(&tattr) == 0);
664 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
665 assert(pthread_create(
666 &CBservicePid, &tattr, InitializeCBService_LWP, 0)
669 code = LWP_CreateProcess(InitializeCBService_LWP, LWP_STACK_SIZE,
670 LWP_MAX_PRIORITY - 2, (int *) 0, "CBService",
672 if (code != LWP_SUCCESS) {
673 fprintf(stderr,"Unable to create the callback service LWP, code %d\n",
682 ScanVnode(char *fname, char *cell)
684 afs_int32 i, code = 0;
687 i = sscanf(fname, "%u.%u.%u",
688 &PioctlInputs.fid.Volume,
689 &PioctlInputs.fid.Vnode,
690 &PioctlInputs.fid.Unique);
692 PioctlInputs.fid.Volume = 0;
693 PioctlInputs.fid.Vnode = 0;
694 PioctlInputs.fid.Unique = 0;
695 fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
699 * The following is used to handle the case of unknown uniquifier. We
700 * just need a valid reference to the volume to direct the RPC to the
701 * right fileserver. Therefore we take the root directory of the volume.
703 if (PioctlInputs.fid.Unique == 0) {
704 PioctlInputs.int32s[0] = PioctlInputs.fid.Vnode;
705 PioctlInputs.fid.Vnode = 1;
706 PioctlInputs.fid.Unique = 1;
712 VLDBInit(int noAuthFlag, struct afsconf_cell *info)
716 code = ugen_ClientInit(noAuthFlag, (char *) AFSDIR_CLIENT_ETC_DIRPATH,
717 info->name, 0, &uclient,
718 NULL, pnp, rxkad_clear,
719 VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
720 0, 0, USER_SERVICE_ID);
726 get_vnode_hosts(char *fname, char **cellp, afs_int32 *hosts, AFSFid *Fid,
729 struct afsconf_dir *tdir;
730 struct vldbentry vldbEntry;
731 afs_int32 i, j, code, *h, len;
732 struct afsconf_cell info;
735 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
737 fprintf(stderr,"Could not process files in configuration directory "
738 "(%s).\n",AFSDIR_CLIENT_ETC_DIRPATH);
743 *cellp = (char *) malloc(MAXCELLCHARS);
744 code = afsconf_GetLocalCell(tdir, *cellp, len);
745 if (code) return code;
747 code = afsconf_GetCellInfo(tdir, *cellp, AFSCONF_VLDBSERVICE, &info);
749 fprintf(stderr,"fs: cell %s not in %s/CellServDB\n",
750 *cellp, AFSDIR_CLIENT_ETC_DIRPATH);
754 i = sscanf(fname, "%u.%u.%u", &Fid->Volume, &Fid->Vnode, &Fid->Unique);
756 fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
759 code = VLDBInit(1, &info);
761 code = ubik_VL_GetEntryByID(uclient, 0, Fid->Volume,
763 if (code == VL_NOENT)
764 fprintf(stderr,"fs: volume %u does not exist in this cell.\n",
766 if (code) return code;
770 if (!onlyRW) mask |= VLSF_RWVOL;
771 for (i=0, j=0; j<vldbEntry.nServers; j++) {
772 if (vldbEntry.serverFlags[j] & mask) {
773 *h++ = ntohl(vldbEntry.serverNumber[j]);
777 for (; i<AFS_MAXHOSTS; i++) *h++ = 0;
782 * Determine which AFS cell file 'fn' lives in, the list of servers that
783 * offer it, and the FID.
786 get_file_cell(char *fn, char **cellp, afs_int32 hosts[AFS_MAXHOSTS], AFSFid *Fid,
787 struct AFSFetchStatus *Status, afs_int32 create)
791 struct ViceIoctl status;
793 afs_int32 *Tmpafs_int32;
795 memset( Status, 0, sizeof(struct AFSFetchStatus));
796 memset(buf, 0, sizeof(buf));
798 status.out_size = sizeof(buf);
802 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
803 if (code && create) {
808 c = strrchr(buf,'\\');
810 c = strrchr(buf,'/');
814 code = pioctl(buf,VIOC_FILE_CELL_NAME, &status, 0);
816 fd = open(fn, O_CREAT, 0644);
819 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
823 fprintf(stderr, "Unable to determine cell for %s\n", fn);
827 fprintf(stderr, "(File might not be in AFS)\n");
829 afs_com_err(pnp, code, (char *) 0);
831 *cellp = (char *) malloc(strlen(buf)+1);
833 SetCellFname(*cellp);
834 memset(buf, 0, sizeof(buf));
838 status.out_size = sizeof(buf);
839 code = pioctl(fn, VIOCWHEREIS, &status, 0);
841 fprintf(stderr, "Unable to determine fileservers for %s\n", fn);
846 afs_com_err(pnp, code, (char *) 0);
848 Tmpafs_int32 = (afs_int32 *)buf;
849 for (j=0;j<AFS_MAXHOSTS;++j) {
850 hosts[j] = Tmpafs_int32[j];
851 if (!Tmpafs_int32[j])
855 memset(buf, 0, sizeof(buf));
857 status.out_size = sizeof(buf);
860 code = pioctl(fn, VIOCGETFID, &status, 0);
862 fprintf(stderr, "Unable to determine FID for %s\n", fn);
866 afs_com_err(pnp, code, (char *) 0);
869 Tmpafs_int32 = (afs_int32 *)buf;
870 Fid->Volume = Tmpafs_int32[1];
871 Fid->Vnode = Tmpafs_int32[2];
872 Fid->Unique = Tmpafs_int32[3];
879 DestroyConnections(void)
883 if (!ConnLookupInitialized) return 0;
884 for (i = 0; i < MAX_HOSTS; i++) {
885 if (!ConnLookup[i].conn) break;
886 RXAFS_GiveUpAllCallBacks(ConnLookup[i].conn);
887 rx_DestroyConnection(ConnLookup[i].conn);
896 LogErrors (int level, const char *fmt, ...)
901 return vfprintf(stderr, fmt, ap);
905 readFile(struct cmd_syndesc *as, void *unused)
910 afs_int32 hosts[AFS_MAXHOSTS];
913 struct rx_connection *RXConn;
914 struct cellLookup *cl;
915 struct rx_call *tcall;
916 struct AFSVolSync tsync;
917 struct AFSFetchStatus OutStatus;
918 struct AFSCallBack CallBack;
921 afs_int64 length, Len;
927 int bufflen = BUFFLEN;
930 /* stdout on Windows defaults to _O_TEXT mode */
931 _setmode(1, _O_BINARY);
934 if (as->name[0] == 'f')
936 if (as->parms[2].items)
938 if (as->parms[3].items) {
944 InitializeCBService();
946 gettimeofday (&starttime, NULL);
947 fname = as->parms[0].items->data;
949 if (as->parms[1].items)
950 cell = as->parms[1].items->data;
952 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
954 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, 0);
956 fprintf(stderr,"File not found %s\n", fname);
960 fprintf(stderr,"%s is a directory, not a file\n", fname);
964 for (j=0;j<AFS_MAXHOSTS;++j) {
967 if (first && as->parms[6].items) {
968 afs_uint32 fields, ip1, ip2, ip3, ip4;
969 fields = sscanf(as->parms[6].items->data, "%d.%d.%d.%d",
970 &ip1, &ip2, &ip3, &ip4);
971 useHost = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
979 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
980 cl->sc, cl->scIndex);
982 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
986 code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
988 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for"
989 " file %s, code was %d\n",
990 useHost, fname, code);
993 gettimeofday(&opentime, NULL);
995 seconds = (float)(opentime.tv_sec + opentime.tv_usec *.000001
996 -starttime.tv_sec - starttime.tv_usec *.000001);
997 fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1000 Len = OutStatus.Length_hi;
1002 Len += OutStatus.Length;
1005 afs_uint32 high, low;
1007 tcall = rx_NewCall(RXConn);
1008 code = StartAFS_FetchData64 (tcall, &Fid, Pos, Len);
1009 if (code == RXGEN_OPCODE) {
1010 afs_int32 tmpPos, tmpLen;
1011 tmpPos = (afs_int32)Pos; tmpLen = (afs_int32)Len;
1012 code = StartAFS_FetchData (tcall, &Fid, tmpPos, tmpLen);
1013 bytes = rx_Read(tcall, (char *)&low, sizeof(afs_int32));
1014 length = ntohl(low);
1015 if (bytes != 4) code = -3;
1017 bytes = rx_Read(tcall, (char *)&high, 4);
1018 length = ntohl(high);
1020 bytes += rx_Read(tcall, (char *)&low, 4);
1021 length += ntohl(low);
1022 if (bytes != 8) code = -3;
1025 if (code == RXGEN_OPCODE) {
1026 fprintf(stderr, "File server for %s might not be running a"
1027 " multi-resident AFS server\n",
1030 fprintf(stderr, "%s for %s ended with error code %d\n",
1031 (char *) &as->name, fname, code);
1035 if (length > bufflen)
1038 len = (afs_int32) length;
1039 buf = (char *)malloc(len);
1041 fprintf(stderr, "couldn't allocate buffer\n");
1044 while (!code && NonZeroInt64(length)) {
1045 if (length > bufflen)
1048 len = (afs_int32) length;
1049 bytes = rx_Read(tcall, (char *) buf, len);
1054 MD5_Update(&md5, buf, len);
1059 gettimeofday(&now, NULL);
1064 code = EndRXAFS_FetchData (tcall, &OutStatus, &CallBack, &tsync);
1065 rx_EndCall(tcall, 0);
1071 gettimeofday(&readtime, NULL);
1073 fprintf(stderr,"%s failed with code %d\n",
1074 (char *) &as->name, worstCode);
1077 afs_uint32 md5int[4];
1079 MD5_Final((char *) &md5int[0], &md5);
1081 p = strrchr(fname,'\\');
1083 p = strrchr(fname,'/');
1090 fprintf(stderr, "%08x%08x%08x%08x %s\n",
1091 htonl(md5int[0]), htonl(md5int[1]),
1092 htonl(md5int[2]), htonl(md5int[3]), p);
1095 seconds = (float)(readtime.tv_sec + readtime.tv_usec *.000001
1096 -opentime.tv_sec - opentime.tv_usec *.000001);
1097 fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1099 datarate = (xfered >> 20) / seconds;
1100 fprintf(stderr,"Total data rate = %.03f MB/sec. for read\n",
1104 DestroyConnections();
1109 writeFile(struct cmd_syndesc *as, void *unused)
1113 afs_int32 code, localcode = 0;
1114 afs_int32 hosts[AFS_MAXHOSTS];
1117 struct rx_connection *RXConn;
1118 struct cellLookup *cl;
1119 struct rx_call *tcall;
1120 struct AFSVolSync tsync;
1121 struct AFSFetchStatus OutStatus;
1122 struct AFSStoreStatus InStatus;
1123 struct AFSCallBack CallBack;
1125 afs_int64 length, Len, synthlength = 0, offset = 0;
1131 afs_int32 byteswritten;
1132 struct wbuf *bufchain = 0;
1133 struct wbuf *previous, *tbuf;
1136 /* stdin on Windows defaults to _O_TEXT mode */
1137 _setmode(0, _O_BINARY);
1140 if (as->name[0] == 'f') {
1142 if (as->name[3] == 'a')
1145 if (as->name[0] == 'a')
1147 if (as->parms[2].items)
1149 if (as->parms[3].items)
1151 if (as->parms[4].items) {
1152 code = util_GetInt64(as->parms[4].items->data, &synthlength);
1154 fprintf(stderr, "Invalid value for synthesize length %s\n",
1155 as->parms[4].items->data);
1160 CBServiceNeeded = 1;
1161 InitializeCBService();
1163 if (as->parms[0].items)
1164 fname = as->parms[0].items->data;
1167 if (as->parms[1].items) cell = as->parms[1].items->data;
1169 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
1173 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, append ? 0 : 1);
1175 fprintf(stderr,"File or directory not found: %s\n",
1179 if (Fid.Vnode & 1) {
1180 fprintf(stderr,"%s is a directory, not a file\n", fname);
1184 fprintf(stderr,"AFS file not found: %s\n", fname);
1187 cl = FindCell(cell);
1188 gettimeofday (&starttime, NULL);
1190 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1191 cl->sc, cl->scIndex);
1193 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1197 code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1199 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for file %s, code was%d\n",
1200 useHost, fname, code);
1203 if (!append && (OutStatus.Length || OutStatus.Length_hi)) {
1204 fprintf(stderr,"AFS file %s not empty, request aborted.\n", fname);
1205 DestroyConnections();
1208 InStatus.Mask = AFS_SETMODE + AFS_FSYNC;
1209 InStatus.UnixModeBits = 0644;
1211 Pos = OutStatus.Length_hi;
1212 Pos = (Pos << 32) | OutStatus.Length;
1215 previous = (struct wbuf *)&bufchain;
1220 while (Len<WRITEBUFFLEN) {
1221 tbuf = (struct wbuf *)malloc(sizeof(struct wbuf));
1224 fprintf(stderr, "Couldn't allocate buffer, aborting\n");
1229 memset(tbuf, 0, sizeof(struct wbuf));
1230 tbuf->buflen = BUFFLEN;
1232 afs_int64 ll, l = tbuf->buflen;
1233 if (l > synthlength)
1235 for (ll = 0; ll < l; ll += 4096) {
1236 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1237 (unsigned int)((offset + ll) >> 32),
1238 (unsigned int)((offset + ll) & 0xffffffff));
1242 tbuf->used = (afs_int32)l;
1244 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1250 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1251 previous->next = tbuf;
1255 gettimeofday(&opentime, NULL);
1257 seconds = (float) (opentime.tv_sec + opentime.tv_usec *.000001
1258 -starttime.tv_sec - starttime.tv_usec *.000001);
1259 fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1263 while (!code && bytes) {
1267 tcall = rx_NewCall(RXConn);
1268 code = StartAFS_StoreData64 (tcall, &Fid, &InStatus, Pos, Len, Pos+Len);
1269 if (code == RXGEN_OPCODE) {
1270 afs_uint32 tmpLen, tmpPos;
1271 tmpPos = (afs_int32) Pos;
1272 tmpLen = (afs_int32) Len;
1273 if (Pos+Len > 0x7fffffff) {
1274 fprintf(stderr,"AFS fileserver does not support files >= 2 GB\n");
1277 code = StartAFS_StoreData (tcall, &Fid, &InStatus, tmpPos, tmpLen,
1281 fprintf(stderr, "StartRXAFS_StoreData had error code %d\n", code);
1287 for (tbuf= bufchain; tbuf; tbuf=tbuf->next) {
1290 byteswritten = rx_Write(tcall, tbuf->buf, tbuf->used);
1291 if (byteswritten != tbuf->used) {
1292 fprintf(stderr,"Only %d instead of %" AFS_INT64_FMT " bytes transferred by rx_Write()\n", byteswritten, length);
1293 fprintf(stderr, "At %" AFS_UINT64_FMT " bytes from the end\n", length);
1297 xfered += tbuf->used;
1298 gettimeofday(&now, NULL);
1301 length -= tbuf->used;
1305 code = EndRXAFS_StoreData64 (tcall, &OutStatus, &tsync);
1307 fprintf(stderr, "EndRXAFS_StoreData64 returned %d\n", code);
1310 code2 = rx_Error(tcall);
1312 fprintf(stderr, "rx_Error returned %d\n", code2);
1315 code2 = rx_EndCall(tcall, localcode);
1317 fprintf(stderr, "rx_EndCall returned %d\n", code2);
1322 fprintf(stderr, "Waiting for busy volume\n");
1329 for (tbuf = bufchain; tbuf; tbuf=tbuf->next) {
1332 afs_int64 ll, l = tbuf->buflen;
1333 if (l > synthlength)
1335 for (ll = 0; ll < l; ll += 4096) {
1336 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1337 (unsigned int)((offset + ll) >> 32),
1338 (unsigned int)((offset + ll) & 0xffffffff));
1342 tbuf->used = (afs_int32) l;
1344 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1348 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1350 bytes += tbuf->used;
1354 gettimeofday(&writetime, NULL);
1356 fprintf(stderr,"%s failed with code %d\n", as->name, worstCode);
1357 } else if(verbose) {
1358 seconds = (float) (writetime.tv_sec + writetime.tv_usec *.000001
1359 -opentime.tv_sec - opentime.tv_usec *.000001);
1360 fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1362 datarate = (xfered >> 20) / seconds;
1363 fprintf(stderr,"Total data rate = %.03f MB/sec. for write\n",
1368 bufchain = tbuf->next;
1371 DestroyConnections();
1373 afs_uint32 md5int[4];
1375 MD5_Final((char *) &md5int[0], &md5);
1377 p = strrchr(fname,'\\');
1379 p = strrchr(fname,'/');
1386 fprintf(stderr, "%08x%08x%08x%08x %s\n",
1387 htonl(md5int[0]), htonl(md5int[1]),
1388 htonl(md5int[2]), htonl(md5int[3]), p);
1394 FindCell(char *cellName)
1396 char name[MAXCELLCHARS];
1398 struct cellLookup *p, *p2;
1399 static struct afsconf_dir *tdir;
1401 afs_int32 len, code;
1407 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1409 afsconf_GetLocalCell(tdir, name, len);
1410 np = (char *) &name;
1414 p2 = (struct cellLookup *) &Cells;
1415 for (p = Cells; p; p = p->next) {
1416 if (!strcmp((char *)&p->info.name, np)) {
1417 #ifdef NO_AFS_CLIENT
1418 if (!strcmp((char *)&lastcell, np))
1419 code = VLDBInit(1, &p->info);
1425 p2->next = (struct cellLookup *) malloc(sizeof(struct cellLookup));
1427 memset(p, 0, sizeof(struct cellLookup));
1428 p->next = (struct cellLookup *) 0;
1430 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1431 if (afsconf_GetCellInfo(tdir, np, AFSCONF_VLDBSERVICE, &p->info)) {
1432 p2->next = (struct cellLookup *) 0;
1434 p = (struct cellLookup *) 0;
1436 #ifdef NO_AFS_CLIENT
1437 if (code = VLDBInit(1, &p->info))
1438 fprintf(stderr,"VLDBInit failed for cell %s\n", p->info.name);
1440 code = afsconf_ClientAuthToken(&p->info, 0, &p->sc, &p->scIndex, &expires);
1442 p->scIndex = RX_SECIDX_NULL;
1443 p->sc = rxnull_NewClientSecurityObject();
1453 struct rx_connection *
1454 FindRXConnection(afs_uint32 host, u_short port, u_short service,
1455 struct rx_securityClass *securityObject,
1456 int serviceSecurityIndex)
1460 if (!ConnLookupInitialized) {
1461 memset(ConnLookup, 0, MAX_HOSTS * sizeof(struct connectionLookup));
1462 ConnLookupInitialized = 1;
1465 for (i = 0; i < MAX_HOSTS; i++) {
1466 if ((ConnLookup[i].host == host) && (ConnLookup[i].port == port))
1467 return ConnLookup[i].conn;
1468 if (!ConnLookup[i].conn)
1475 ConnLookup[i].conn = rx_NewConnection(host, port, service, securityObject, serviceSecurityIndex);
1476 if (ConnLookup[i].conn) {
1477 ConnLookup[i].host = host;
1478 ConnLookup[i].port = port;
1481 return ConnLookup[i].conn;