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>
107 #ifdef AFS_PTHREAD_ENV
109 pthread_key_t uclient_key;
112 int readFile(struct cmd_syndesc *as, void *);
113 int writeFile(struct cmd_syndesc *as, void *);
114 struct rx_connection *FindRXConnection(afs_uint32 host, u_short port, u_short service, struct rx_securityClass *securityObject, int serviceSecurityIndex);
115 struct cellLookup * FindCell(char *cellName);
119 static int verbose = 0; /* Set if -verbose option given */
120 static int CBServiceNeeded = 0;
121 static struct timeval starttime, opentime, readtime, writetime;
122 afs_uint64 xfered=0, oldxfered=0;
123 static struct timeval now;
124 struct timezone Timezone;
125 static float seconds, datarate, oldseconds;
126 extern int rxInitDone;
128 static afs_int32 rx_mtu = -1;
130 afs_uint64 transid = 0;
131 afs_uint32 expires = 0;
132 afs_uint32 server_List[MAXHOSTSPERCELL];
135 static struct ubik_client *uclient;
136 #define BUFFLEN 65536
137 #define WRITEBUFFLEN 1024*1024*64
145 afs_uint32 offset; /* offset inside the buffer */
146 afs_uint32 buflen; /* total length == BUFFLEN */
147 afs_uint32 used; /* bytes used inside buffer */
151 struct connectionLookup {
154 struct rx_connection *conn;
158 struct cellLookup *next;
159 struct afsconf_cell info;
160 struct rx_securityClass *sc;
165 struct dirLookup *next;
166 struct dirLookup *prev;
168 struct cellLookup *cell;
170 char name[VL_MAXNAMELEN];
173 struct cellLookup *Cells = 0;
174 struct dirLookup *Dirs = 0;
177 #define MAX_HOSTS 256
178 static struct connectionLookup ConnLookup[MAX_HOSTS];
179 static int ConnLookupInitialized = 0;
181 struct FsCmdInputs PioctlInputs;
182 struct FsCmdOutputs PioctlOutputs;
187 seconds = (float)(now.tv_sec + now.tv_usec *.000001
188 -opentime.tv_sec - opentime.tv_usec *.000001);
189 if ((seconds - oldseconds) > 30.) {
191 tmp = xfered - oldxfered;
192 datarate = ((afs_uint32) (tmp >> 20)) / (seconds - oldseconds);
193 fprintf(stderr,"%llu MB transferred, present date rate = %.03f MB/sec.\n",
194 xfered >> 20, datarate);
196 oldseconds = seconds;
201 SetCellFname(char *name)
203 struct afsconf_dir *tdir;
205 strcpy((char *) &cellFname,"/afs/");
207 strcat((char *) &cellFname, name);
209 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
210 afsconf_GetLocalCell(tdir, &cellFname[5], MAXCELLCHARS);
215 main (int argc, char **argv)
218 struct cmd_syndesc *ts;
220 strcpy(pnp, argv[0]);
222 #ifdef AFS_PTHREAD_ENV
223 assert(pthread_key_create(&uclient_key, NULL) == 0);
225 ts = cmd_CreateSyntax("read", readFile, CMD_REQUIRED,
226 "read a file from AFS");
227 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename");
228 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
229 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
230 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
232 ts = cmd_CreateSyntax("fidread", readFile, CMD_REQUIRED,
233 "read on a non AFS-client a file from AFS");
234 cmd_IsAdministratorCommand(ts);
235 cmd_AddParm(ts, "-fid", 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);
238 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
240 ts = cmd_CreateSyntax("write", writeFile, CMD_REQUIRED,
241 "write a file into AFS");
242 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
243 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
244 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
245 cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
246 cmd_AddParm(ts, "-synthesize", CMD_SINGLE, CMD_OPTIONAL, "create data pattern of specified length instead reading from stdin");
248 ts = cmd_CreateSyntax("fidwrite", writeFile, CMD_REQUIRED,
249 "write a file into AFS");
250 cmd_IsAdministratorCommand(ts);
251 cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
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");
256 ts = cmd_CreateSyntax("append", writeFile, CMD_REQUIRED,
257 "append to a file in AFS");
258 cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
259 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
260 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
262 ts = cmd_CreateSyntax("fidappend", writeFile, CMD_REQUIRED,
263 "append to a file in AFS");
264 cmd_IsAdministratorCommand(ts);
265 cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
266 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
267 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
269 code = cmd_Dispatch(argc, argv);
275 HandleLocalAuth(struct rx_securityClass **sc, afs_int32 *scIndex)
277 static struct afsconf_dir *tdir = NULL;
281 *scIndex = RX_SECIDX_NULL;
283 tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
285 fprintf(stderr,"Could not open configuration directory: %s.\n",
286 AFSDIR_SERVER_ETC_DIRPATH);
289 code = afsconf_ClientAuth(tdir, sc, scIndex);
291 fprintf(stderr,"afsconf_ClientAuth returned %d\n", code);
298 AFS_Lookup(struct rx_connection *conn, AFSFid *dirfid, char *name,
299 AFSFid *outfid, AFSFetchStatus *outstatus, AFSFetchStatus
300 *dirstatus, AFSCallBack *callback, AFSVolSync *sync)
302 afs_int32 code = VBUSY;
303 while (code == VBUSY) {
304 code = RXAFS_Lookup(conn, dirfid, name, outfid, outstatus, dirstatus,
307 fprintf(stderr, "waiting for busy AFS volume %u.\n",
309 #ifdef AFS_PTHREAD_ENV
320 AFS_FetchStatus(struct rx_connection *conn, AFSFid *fid, AFSFetchStatus
321 *Status, AFSCallBack *callback, AFSVolSync *sync)
323 afs_int32 code = VBUSY;
325 while (code == VBUSY) {
326 code = RXAFS_FetchStatus(conn, fid, Status, callback, sync);
328 fprintf(stderr, "waiting for busy AFS volume %u.\n",
330 #ifdef AFS_PTHREAD_ENV
341 StartAFS_FetchData(struct rx_call *call, AFSFid *fid, afs_int32 pos,
344 afs_int32 code = VBUSY;
345 while (code == VBUSY) {
346 code = StartRXAFS_FetchData (call, fid, pos, len);
348 fprintf(stderr, "waiting for busy AFS volume %u.\n",
350 #ifdef AFS_PTHREAD_ENV
361 StartAFS_FetchData64(struct rx_call *call, AFSFid *fid, afs_int64 pos,
364 afs_int32 code = VBUSY;
365 while (code == VBUSY) {
366 code = StartRXAFS_FetchData64 (call, fid, pos, len);
368 fprintf(stderr, "waiting for busy AFS volume %u.\n",
370 #ifdef AFS_PTHREAD_ENV
381 StartAFS_StoreData(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
382 afs_int32 pos, afs_int32 len, afs_int32 len2)
384 afs_int32 code = VBUSY;
385 while (code == VBUSY) {
386 code = StartRXAFS_StoreData (call, fid, status, pos, len, len2);
388 fprintf(stderr, "waiting for busy AFS volume %u.\n",
390 #ifdef AFS_PTHREAD_ENV
401 StartAFS_StoreData64(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
402 afs_int64 pos, afs_int64 len, afs_int64 len2)
404 afs_int32 code = VBUSY;
405 while (code == VBUSY) {
406 code = StartRXAFS_StoreData64 (call, fid, status, pos, len, len2);
408 fprintf(stderr, "waiting for busy AFS volume %u.\n",
410 #ifdef AFS_PTHREAD_ENV
421 SRXAFSCB_CallBack(struct rx_call *rxcall, AFSCBFids *Fids_Array,
422 AFSCBs *CallBack_Array)
428 SRXAFSCB_InitCallBackState(struct rx_call *rxcall)
434 SRXAFSCB_Probe(struct rx_call *rxcall)
440 SRXAFSCB_GetCE(struct rx_call *rxcall,
442 AFSDBCacheEntry * ce)
448 SRXAFSCB_GetLock(struct rx_call *rxcall,
456 SRXAFSCB_XStatsVersion(struct rx_call *rxcall,
457 afs_int32 * versionNumberP)
463 SRXAFSCB_GetXStats(struct rx_call *rxcall,
464 afs_int32 clientVersionNumber,
465 afs_int32 collectionNumber,
466 afs_int32 * srvVersionNumberP,
468 AFSCB_CollData * dataP)
474 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID *a_uuid)
476 if ( !afs_uuid_equal(&uuid, a_uuid) )
484 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
486 return SRXAFSCB_TellMeAboutYourself(a_call, addr, NULL);
490 SRXAFSCB_InitCallBackState2(struct rx_call *a_call, struct interfaceAddr *
497 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID *a_uuid)
503 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
504 afs_uint32 *serverVersion, afs_uint32 *configCount,
511 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
517 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
518 char **a_name, serverList *a_hosts)
524 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
525 afs_int32 *a_srvr_addr, afs_int32 *a_srvr_rank)
531 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call, struct interfaceAddr *
532 addr, Capabilities *capabilities)
536 int cm_noIPAddr; /* number of client network interfaces */
537 int cm_IPAddr[CM_MAXINTERFACE_ADDR]; /* client's IP address in host order */
538 int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
539 int cm_NetMtu[CM_MAXINTERFACE_ADDR]; /* client's MTU sizes */
540 int cm_NetFlags[CM_MAXINTERFACE_ADDR]; /* network flags */
543 cm_noIPAddr = CM_MAXINTERFACE_ADDR;
544 code = syscfg_GetIFInfo(&cm_noIPAddr,
545 cm_IPAddr, cm_SubnetMask,
546 cm_NetMtu, cm_NetFlags);
548 /* return all network interface addresses */
549 addr->numberOfInterfaces = cm_noIPAddr;
550 for ( i=0; i < cm_noIPAddr; i++ ) {
551 addr->addr_in[i] = cm_IPAddr[i];
552 addr->subnetmask[i] = cm_SubnetMask[i];
553 addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ?
554 cm_NetMtu[i] : rx_mtu;
557 addr->numberOfInterfaces = 0;
560 addr->numberOfInterfaces = 0;
562 /* return all network interface addresses */
563 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
564 for ( i=0; i < afs_cb_interface.numberOfInterfaces; i++) {
565 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
566 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
567 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
575 afs_uint32 *dataBuffP;
578 dataBytes = 1 * sizeof(afs_uint32);
579 dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes);
580 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
581 capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
582 capabilities->Capabilities_val = dataBuffP;
588 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
589 char **a_name, serverList *a_hosts)
595 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
596 struct AFSDBCacheEntry64 *a_result)
602 InitializeCBService_LWP(void *unused)
604 struct rx_securityClass *CBsecobj;
605 struct rx_service *CBService;
607 afs_uuid_create(&uuid);
609 CBsecobj = (struct rx_securityClass *)rxnull_NewServerSecurityObject();
611 fprintf(stderr,"rxnull_NewServerSecurityObject failed for callback service.\n");
614 CBService = rx_NewService(0, 1, "afs", &CBsecobj, 1,
615 RXAFSCB_ExecuteRequest);
617 fprintf(stderr,"rx_NewService failed for callback service.\n");
626 InitializeCBService(void)
628 #define RESTOOL_CBPORT 7102
629 #define MAX_PORT_TRIES 1000
630 #define LWP_STACK_SIZE (16 * 1024)
632 #ifdef AFS_PTHREAD_ENV
633 pthread_t CBservicePid;
634 pthread_attr_t tattr;
636 PROCESS CBServiceLWP_ID, parentPid;
641 #ifndef NO_AFS_CLIENT
642 if (!CBServiceNeeded)
645 #ifndef AFS_PTHREAD_ENV
646 code = LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid);
647 if (code != LWP_SUCCESS) {
648 fprintf(stderr,"Unable to initialize LWP support, code %d\n",
654 #if defined(AFS_AIX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI_ENV)
656 InitialCBPort = RESTOOL_CBPORT + random() % 1000;
657 #else /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
658 #if defined(AFS_HPUX_ENV)
660 InitialCBPort = RESTOOL_CBPORT + lrand48() % 1000;
661 #else /* AFS_HPUX_ENV */
662 #if defined AFS_NT40_ENV
664 InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
665 #else /* AFS_NT40_ENV */
667 InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
668 #endif /* AFS_NT40_ENV */
669 #endif /* AFS_HPUX_ENV */
670 #endif /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
672 CBPort = InitialCBPort;
674 code = rx_Init(htons(CBPort));
676 if ((code == RX_ADDRINUSE) &&
677 (CBPort < MAX_PORT_TRIES + InitialCBPort)) {
679 } else if (CBPort < MAX_PORT_TRIES + InitialCBPort) {
680 fprintf(stderr, "rx_Init didn't succeed for callback service."
681 " Tried port numbers %d through %d\n",
682 InitialCBPort, CBPort);
685 fprintf(stderr,"Couldn't initialize callback service "
686 "because too many users are running this program. "
687 "Try again later.\n");
692 #ifdef AFS_PTHREAD_ENV
693 assert(pthread_attr_init(&tattr) == 0);
694 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
695 assert(pthread_create(
696 &CBservicePid, &tattr, InitializeCBService_LWP, 0)
699 code = LWP_CreateProcess(InitializeCBService_LWP, LWP_STACK_SIZE,
700 LWP_MAX_PRIORITY - 2, (int *) 0, "CBService",
702 if (code != LWP_SUCCESS) {
703 fprintf(stderr,"Unable to create the callback service LWP, code %d\n",
712 ScanVnode(char *fname, char *cell)
714 afs_int32 i, code = 0;
717 i = sscanf(fname, "%u.%u.%u",
718 &PioctlInputs.fid.Volume,
719 &PioctlInputs.fid.Vnode,
720 &PioctlInputs.fid.Unique);
722 PioctlInputs.fid.Volume = 0;
723 PioctlInputs.fid.Vnode = 0;
724 PioctlInputs.fid.Unique = 0;
725 fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
729 * The following is used to handle the case of unknown uniquifier. We
730 * just need a valid reference to the volume to direct the RPC to the
731 * right fileserver. Therefore we take the root directory of the volume.
733 if (PioctlInputs.fid.Unique == 0) {
734 PioctlInputs.int32s[0] = PioctlInputs.fid.Vnode;
735 PioctlInputs.fid.Vnode = 1;
736 PioctlInputs.fid.Unique = 1;
742 VLDBInit(int noAuthFlag, struct afsconf_cell *info)
746 code = ugen_ClientInit(noAuthFlag, (char *) AFSDIR_CLIENT_ETC_DIRPATH,
747 info->name, 0, &uclient,
748 NULL, pnp, rxkad_clear,
749 VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
750 0, 0, USER_SERVICE_ID);
756 get_vnode_hosts(char *fname, char **cellp, afs_int32 *hosts, AFSFid *Fid,
759 struct afsconf_dir *tdir;
760 struct vldbentry vldbEntry;
761 afs_int32 i, j, code, *h, len;
762 struct afsconf_cell info;
765 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
767 fprintf(stderr,"Could not process files in configuration directory "
768 "(%s).\n",AFSDIR_CLIENT_ETC_DIRPATH);
773 *cellp = (char *) malloc(MAXCELLCHARS);
774 code = afsconf_GetLocalCell(tdir, *cellp, len);
775 if (code) return code;
777 code = afsconf_GetCellInfo(tdir, *cellp, AFSCONF_VLDBSERVICE, &info);
779 fprintf(stderr,"fs: cell %s not in %s/CellServDB\n",
780 *cellp, AFSDIR_CLIENT_ETC_DIRPATH);
784 i = sscanf(fname, "%u.%u.%u", &Fid->Volume, &Fid->Vnode, &Fid->Unique);
786 fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
789 code = VLDBInit(1, &info);
791 code = ubik_VL_GetEntryByID(uclient, 0, Fid->Volume,
793 if (code == VL_NOENT)
794 fprintf(stderr,"fs: volume %u does not exist in this cell.\n",
796 if (code) return code;
800 if (!onlyRW) mask |= VLSF_RWVOL;
801 for (i=0, j=0; j<vldbEntry.nServers; j++) {
802 if (vldbEntry.serverFlags[j] & mask) {
803 *h++ = ntohl(vldbEntry.serverNumber[j]);
807 for (; i<AFS_MAXHOSTS; i++) *h++ = 0;
812 * Determine which AFS cell file 'fn' lives in, the list of servers that
813 * offer it, and the FID.
816 get_file_cell(char *fn, char **cellp, afs_int32 hosts[AFS_MAXHOSTS], AFSFid *Fid,
817 struct AFSFetchStatus *Status, afs_int32 create)
821 struct ViceIoctl status;
823 afs_int32 *Tmpafs_int32;
825 memset( Status, 0, sizeof(struct AFSFetchStatus));
826 memset(buf, 0, sizeof(buf));
828 status.out_size = sizeof(buf);
832 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
833 if (code && create) {
838 c = strrchr(buf,'\\');
840 c = strrchr(buf,'/');
844 code = pioctl(buf,VIOC_FILE_CELL_NAME, &status, 0);
846 fd = open(fn, O_CREAT, 0644);
849 code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
853 fprintf(stderr, "Unable to determine cell for %s\n", fn);
857 fprintf(stderr, "(File might not be in AFS)\n");
859 afs_com_err(pnp, code, (char *) 0);
861 *cellp = (char *) malloc(strlen(buf)+1);
863 SetCellFname(*cellp);
864 memset(buf, 0, sizeof(buf));
868 status.out_size = sizeof(buf);
869 code = pioctl(fn, VIOCWHEREIS, &status, 0);
871 fprintf(stderr, "Unable to determine fileservers for %s\n", fn);
876 afs_com_err(pnp, code, (char *) 0);
878 Tmpafs_int32 = (afs_int32 *)buf;
879 for (j=0;j<AFS_MAXHOSTS;++j) {
880 hosts[j] = Tmpafs_int32[j];
881 if (!Tmpafs_int32[j])
885 memset(buf, 0, sizeof(buf));
887 status.out_size = sizeof(buf);
890 code = pioctl(fn, VIOCGETFID, &status, 0);
892 fprintf(stderr, "Unable to determine FID for %s\n", fn);
896 afs_com_err(pnp, code, (char *) 0);
899 Tmpafs_int32 = (afs_int32 *)buf;
900 Fid->Volume = Tmpafs_int32[1];
901 Fid->Vnode = Tmpafs_int32[2];
902 Fid->Unique = Tmpafs_int32[3];
909 DestroyConnections(void)
913 if (!ConnLookupInitialized) return 0;
914 for (i = 0; i < MAX_HOSTS; i++) {
915 if (!ConnLookup[i].conn) break;
916 RXAFS_GiveUpAllCallBacks(ConnLookup[i].conn);
917 rx_DestroyConnection(ConnLookup[i].conn);
926 LogErrors (int level, const char *fmt, ...)
931 return vfprintf(stderr, fmt, ap);
935 readFile(struct cmd_syndesc *as, void *unused)
940 afs_int32 hosts[AFS_MAXHOSTS];
943 struct rx_connection *RXConn;
944 struct cellLookup *cl;
945 struct rx_call *tcall;
946 struct AFSVolSync tsync;
947 struct AFSFetchStatus OutStatus;
948 struct AFSCallBack CallBack;
951 afs_int64 length, Len;
957 int bufflen = BUFFLEN;
960 /* stdout on Windows defaults to _O_TEXT mode */
961 _setmode(1, _O_BINARY);
964 if (as->name[0] == 'f')
966 if (as->parms[2].items)
968 if (as->parms[3].items) {
974 InitializeCBService();
976 gettimeofday (&starttime, &Timezone);
977 fname = as->parms[0].items->data;
979 if (as->parms[1].items)
980 cell = as->parms[1].items->data;
982 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
984 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, 0);
986 fprintf(stderr,"File not found %s\n", fname);
990 fprintf(stderr,"%s is a directory, not a file\n", fname);
994 for (j=0;j<AFS_MAXHOSTS;++j) {
997 if (first && as->parms[6].items) {
998 afs_uint32 fields, ip1, ip2, ip3, ip4;
999 fields = sscanf(as->parms[6].items->data, "%d.%d.%d.%d",
1000 &ip1, &ip2, &ip3, &ip4);
1001 useHost = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
1009 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1010 cl->sc, cl->scIndex);
1012 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1016 code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1018 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for"
1019 " file %s, code was %d\n",
1020 useHost, fname, code);
1023 gettimeofday(&opentime, &Timezone);
1025 seconds = (float)(opentime.tv_sec + opentime.tv_usec *.000001
1026 -starttime.tv_sec - starttime.tv_usec *.000001);
1027 fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1030 Len = OutStatus.Length_hi;
1032 Len += OutStatus.Length;
1035 afs_uint32 high, low;
1037 tcall = rx_NewCall(RXConn);
1038 code = StartAFS_FetchData64 (tcall, &Fid, Pos, Len);
1039 if (code == RXGEN_OPCODE) {
1040 afs_int32 tmpPos, tmpLen;
1041 tmpPos = (afs_int32)Pos; tmpLen = (afs_int32)Len;
1042 code = StartAFS_FetchData (tcall, &Fid, tmpPos, tmpLen);
1043 bytes = rx_Read(tcall, (char *)&low, sizeof(afs_int32));
1044 length = ntohl(low);
1045 if (bytes != 4) code = -3;
1047 bytes = rx_Read(tcall, (char *)&high, 4);
1048 length = ntohl(high);
1050 bytes += rx_Read(tcall, (char *)&low, 4);
1051 length += ntohl(low);
1052 if (bytes != 8) code = -3;
1055 if (code == RXGEN_OPCODE) {
1056 fprintf(stderr, "File server for %s might not be running a"
1057 " multi-resident AFS server\n",
1060 fprintf(stderr, "%s for %s ended with error code %d\n",
1061 (char *) &as->name, fname, code);
1065 if (length > bufflen)
1068 len = (afs_int32) length;
1069 buf = (char *)malloc(len);
1071 fprintf(stderr, "couldn't allocate buffer\n");
1074 while (!code && NonZeroInt64(length)) {
1075 if (length > bufflen)
1078 len = (afs_int32) length;
1079 bytes = rx_Read(tcall, (char *) buf, len);
1084 MD5_Update(&md5, buf, len);
1089 gettimeofday(&now, &Timezone);
1094 code = EndRXAFS_FetchData (tcall, &OutStatus, &CallBack, &tsync);
1095 rx_EndCall(tcall, 0);
1101 gettimeofday(&readtime, &Timezone);
1103 fprintf(stderr,"%s failed with code %d\n",
1104 (char *) &as->name, worstCode);
1107 afs_uint32 md5int[4];
1109 MD5_Final((char *) &md5int[0], &md5);
1111 p = strrchr(fname,'\\');
1113 p = strrchr(fname,'/');
1120 fprintf(stderr, "%08x%08x%08x%08x %s\n",
1121 htonl(md5int[0]), htonl(md5int[1]),
1122 htonl(md5int[2]), htonl(md5int[3]), p);
1125 seconds = (float)(readtime.tv_sec + readtime.tv_usec *.000001
1126 -opentime.tv_sec - opentime.tv_usec *.000001);
1127 fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1129 datarate = (xfered >> 20) / seconds;
1130 fprintf(stderr,"Total data rate = %.03f MB/sec. for read\n",
1134 DestroyConnections();
1139 writeFile(struct cmd_syndesc *as, void *unused)
1143 afs_int32 code, localcode = 0;
1144 afs_int32 hosts[AFS_MAXHOSTS];
1147 struct rx_connection *RXConn;
1148 struct cellLookup *cl;
1149 struct rx_call *tcall;
1150 struct AFSVolSync tsync;
1151 struct AFSFetchStatus OutStatus;
1152 struct AFSStoreStatus InStatus;
1153 struct AFSCallBack CallBack;
1155 afs_int64 length, Len, synthlength = 0, offset = 0;
1161 afs_int32 byteswritten;
1162 struct wbuf *bufchain = 0;
1163 struct wbuf *previous, *tbuf;
1166 /* stdin on Windows defaults to _O_TEXT mode */
1167 _setmode(0, _O_BINARY);
1170 if (as->name[0] == 'f') {
1172 if (as->name[3] == 'a')
1175 if (as->name[0] == 'a')
1177 if (as->parms[2].items)
1179 if (as->parms[3].items)
1181 if (as->parms[4].items) {
1182 code = util_GetInt64(as->parms[4].items->data, &synthlength);
1184 fprintf(stderr, "Invalid value for synthesize length %s\n",
1185 as->parms[4].items->data);
1190 CBServiceNeeded = 1;
1191 InitializeCBService();
1193 if (as->parms[0].items)
1194 fname = as->parms[0].items->data;
1197 if (as->parms[1].items) cell = as->parms[1].items->data;
1199 code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
1203 code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, append ? 0 : 1);
1205 fprintf(stderr,"File or directory not found: %s\n",
1209 if (Fid.Vnode & 1) {
1210 fprintf(stderr,"%s is a directory, not a file\n", fname);
1214 fprintf(stderr,"AFS file not found: %s\n", fname);
1217 cl = FindCell(cell);
1218 gettimeofday (&starttime, &Timezone);
1220 RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
1221 cl->sc, cl->scIndex);
1223 fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
1227 code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
1229 fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for file %s, code was%d\n",
1230 useHost, fname, code);
1233 if (!append && (OutStatus.Length || OutStatus.Length_hi)) {
1234 fprintf(stderr,"AFS file %s not empty, request aborted.\n", fname);
1235 DestroyConnections();
1238 InStatus.Mask = AFS_SETMODE + AFS_FSYNC;
1239 InStatus.UnixModeBits = 0644;
1241 Pos = OutStatus.Length_hi;
1242 Pos = (Pos << 32) | OutStatus.Length;
1245 previous = (struct wbuf *)&bufchain;
1250 while (Len<WRITEBUFFLEN) {
1251 tbuf = (struct wbuf *)malloc(sizeof(struct wbuf));
1254 fprintf(stderr, "Couldn't allocate buffer, aborting\n");
1259 memset(tbuf, 0, sizeof(struct wbuf));
1260 tbuf->buflen = BUFFLEN;
1262 afs_int64 ll, l = tbuf->buflen;
1263 if (l > synthlength)
1265 for (ll = 0; ll < l; ll += 4096) {
1266 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1267 (unsigned int)((offset + ll) >> 32),
1268 (unsigned int)((offset + ll) & 0xffffffff));
1272 tbuf->used = (afs_int32)l;
1274 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1280 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1281 previous->next = tbuf;
1285 gettimeofday(&opentime, &Timezone);
1287 seconds = (float) (opentime.tv_sec + opentime.tv_usec *.000001
1288 -starttime.tv_sec - starttime.tv_usec *.000001);
1289 fprintf(stderr,"Startup to find the file took %.3f sec.\n",
1293 while (!code && bytes) {
1297 tcall = rx_NewCall(RXConn);
1298 code = StartAFS_StoreData64 (tcall, &Fid, &InStatus, Pos, Len, Pos+Len);
1299 if (code == RXGEN_OPCODE) {
1300 afs_uint32 tmpLen, tmpPos;
1301 tmpPos = (afs_int32) Pos;
1302 tmpLen = (afs_int32) Len;
1303 if (Pos+Len > 0x7fffffff) {
1304 fprintf(stderr,"AFS fileserver does not support files >= 2 GB\n");
1307 code = StartAFS_StoreData (tcall, &Fid, &InStatus, tmpPos, tmpLen,
1311 fprintf(stderr, "StartRXAFS_StoreData had error code %d\n", code);
1317 for (tbuf= bufchain; tbuf; tbuf=tbuf->next) {
1320 byteswritten = rx_Write(tcall, tbuf->buf, tbuf->used);
1321 if (byteswritten != tbuf->used) {
1322 fprintf(stderr,"Only %d instead of %" AFS_INT64_FMT " bytes transferred by rx_Write()\n", byteswritten, length);
1323 fprintf(stderr, "At %" AFS_UINT64_FMT " bytes from the end\n", length);
1327 xfered += tbuf->used;
1328 gettimeofday(&now, &Timezone);
1331 length -= tbuf->used;
1335 code = EndRXAFS_StoreData64 (tcall, &OutStatus, &tsync);
1337 fprintf(stderr, "EndRXAFS_StoreData64 returned %d\n", code);
1340 code2 = rx_Error(tcall);
1342 fprintf(stderr, "rx_Error returned %d\n", code2);
1345 code2 = rx_EndCall(tcall, localcode);
1347 fprintf(stderr, "rx_EndCall returned %d\n", code2);
1352 fprintf(stderr, "Waiting for busy volume\n");
1359 for (tbuf = bufchain; tbuf; tbuf=tbuf->next) {
1362 afs_int64 ll, l = tbuf->buflen;
1363 if (l > synthlength)
1365 for (ll = 0; ll < l; ll += 4096) {
1366 sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
1367 (unsigned int)((offset + ll) >> 32),
1368 (unsigned int)((offset + ll) & 0xffffffff));
1372 tbuf->used = (afs_int32) l;
1374 tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
1378 MD5_Update(&md5, &tbuf->buf, tbuf->used);
1380 bytes += tbuf->used;
1384 gettimeofday(&writetime, &Timezone);
1386 fprintf(stderr,"%s failed with code %d\n", as->name, worstCode);
1387 } else if(verbose) {
1388 seconds = (float) (writetime.tv_sec + writetime.tv_usec *.000001
1389 -opentime.tv_sec - opentime.tv_usec *.000001);
1390 fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
1392 datarate = (xfered >> 20) / seconds;
1393 fprintf(stderr,"Total data rate = %.03f MB/sec. for write\n",
1398 bufchain = tbuf->next;
1401 DestroyConnections();
1403 afs_uint32 md5int[4];
1405 MD5_Final((char *) &md5int[0], &md5);
1407 p = strrchr(fname,'\\');
1409 p = strrchr(fname,'/');
1416 fprintf(stderr, "%08x%08x%08x%08x %s\n",
1417 htonl(md5int[0]), htonl(md5int[1]),
1418 htonl(md5int[2]), htonl(md5int[3]), p);
1424 FindCell(char *cellName)
1426 char name[MAXCELLCHARS];
1428 struct cellLookup *p, *p2;
1429 static struct afsconf_dir *tdir;
1431 afs_int32 len, code;
1437 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1439 afsconf_GetLocalCell(tdir, name, len);
1440 np = (char *) &name;
1444 p2 = (struct cellLookup *) &Cells;
1445 for (p = Cells; p; p = p->next) {
1446 if (!strcmp((char *)&p->info.name, np)) {
1447 #ifdef NO_AFS_CLIENT
1448 if (!strcmp((char *)&lastcell, np))
1449 code = VLDBInit(1, &p->info);
1455 p2->next = (struct cellLookup *) malloc(sizeof(struct cellLookup));
1457 memset(p, 0, sizeof(struct cellLookup));
1458 p->next = (struct cellLookup *) 0;
1460 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1461 if (afsconf_GetCellInfo(tdir, np, AFSCONF_VLDBSERVICE, &p->info)) {
1462 p2->next = (struct cellLookup *) 0;
1464 p = (struct cellLookup *) 0;
1466 #ifdef NO_AFS_CLIENT
1467 if (code = VLDBInit(1, &p->info))
1468 fprintf(stderr,"VLDBInit failed for cell %s\n", p->info.name);
1470 code = afsconf_ClientAuthToken(&p->info, 0, &p->sc, &p->scIndex, &expires);
1472 p->scIndex = RX_SECIDX_NULL;
1473 p->sc = rxnull_NewClientSecurityObject();
1483 struct rx_connection *
1484 FindRXConnection(afs_uint32 host, u_short port, u_short service,
1485 struct rx_securityClass *securityObject,
1486 int serviceSecurityIndex)
1490 if (!ConnLookupInitialized) {
1491 memset(ConnLookup, 0, MAX_HOSTS * sizeof(struct connectionLookup));
1492 ConnLookupInitialized = 1;
1495 for (i = 0; i < MAX_HOSTS; i++) {
1496 if ((ConnLookup[i].host == host) && (ConnLookup[i].port == port))
1497 return ConnLookup[i].conn;
1498 if (!ConnLookup[i].conn)
1505 ConnLookup[i].conn = rx_NewConnection(host, port, service, securityObject, serviceSecurityIndex);
1506 if (ConnLookup[i].conn) {
1507 ConnLookup[i].host = host;
1508 ConnLookup[i].port = port;
1511 return ConnLookup[i].conn;