--- /dev/null
+/*
+ * Copyright (c) 2007, Hartmut Reuter,
+ * RZG, Max-Planck-Institut f. Plasmaphysik.
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <afsconfig.h>
+#include <afs/param.h>
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef AFS_NT40_ENV
+#include <fcntl.h>
+#else
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include <fcntl.h>
+#endif
+#include <sys/stat.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <afs/vice.h>
+#include <afs/cmd.h>
+#include <afs/auth.h>
+#include <afs/cellconfig.h>
+#include <afs/afsutil.h>
+#include <rx/rx.h>
+#include <rx/xdr.h>
+#include <afs/venus.h>
+#include <afs/afscbint.h>
+#define FSINT_COMMON_XG 1
+#include <afs/afsint.h>
+#include <afs/vldbint.h>
+#include <afs/vlserver.h>
+#include <afs/volser.h>
+#include <afs/ptint.h>
+#include <afs/dir.h>
+#include <afs/nfs.h>
+#include <afs/ihandle.h>
+#include <afs/namei_ops.h>
+#include <afs/vnode.h>
+#include <afs/com_err.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
+#include <sys/time.h>
+#include <netdb.h>
+#ifdef AFS_DARWIN_ENV
+#include <sys/malloc.h>
+#else
+#include <malloc.h>
+#endif
+#include <afs/errors.h>
+#include <afs/sys_prototypes.h>
+#include <des_prototypes.h>
+#include <rx_prototypes.h>
+#include "../rxkad/md5.h"
+#define MAXHOSTS 13
+#ifdef O_LARGEFILE
+#define afs_stat stat64
+#define afs_fstat fstat64
+#define afs_open open64
+#else /* !O_LARGEFILE */
+#define afs_stat stat
+#define afs_fstat fstat
+#define afs_open open
+#endif /* !O_LARGEFILE */
+#ifdef AFS_PTHREAD_ENV
+#include <assert.h>
+pthread_key_t uclient_key;
+#endif
+
+int readFile(struct cmd_syndesc *as, void *);
+int writeFile(struct cmd_syndesc *as, void *);
+struct rx_connection *FindRXConnection(afs_uint32 host, u_short port, u_short service, struct rx_securityClass *securityObject, int serviceSecurityIndex);
+struct cellLookup * FindCell(char *cellName);
+
+char pnp[255];
+int rxInitDone = 0;
+static int verbose = 0; /* Set if -verbose option given */
+static int CBServiceNeeded = 0;
+static struct timeval starttime, opentime, readtime, writetime;
+afs_uint64 xfered=0, oldxfered=0;
+static struct timeval now;
+struct timezone Timezone;
+static float seconds, datarate, oldseconds;
+extern int rxInitDone;
+afs_uint64 transid = 0;
+afs_uint32 expires = 0;
+afs_uint32 server_List[MAXHOSTSPERCELL];
+char tmpstr[1024];
+char tmpstr2[1024];
+static struct ubik_client *uclient;
+#define BUFFLEN 65536
+#define WRITEBUFFLEN 1024*1024*64
+
+afsUUID uuid;
+MD5_CTX md5;
+int md5sum = 0;
+
+struct wbuf {
+ struct wbuf *next;
+ afs_uint32 offset; /* offset inside the buffer */
+ afs_uint32 buflen; /* total length == BUFFLEN */
+ afs_uint32 used; /* bytes used inside buffer */
+ char buf[BUFFLEN];
+};
+
+struct connectionLookup {
+ afs_uint32 host;
+ u_short port;
+ struct rx_connection *conn;
+};
+
+struct cellLookup {
+ struct cellLookup *next;
+ struct afsconf_cell info;
+ struct rx_securityClass *sc[3];
+ afs_int32 scIndex;
+};
+
+struct dirLookup {
+ struct dirLookup *next;
+ struct dirLookup *prev;
+ afs_int32 host;
+ struct cellLookup *cell;
+ AFSFid fid;
+ char name[VL_MAXNAMELEN];
+};
+
+struct cellLookup *Cells = 0;
+struct dirLookup *Dirs = 0;
+char cellFname[256];
+
+#define MAX_HOSTS 256
+static struct connectionLookup ConnLookup[MAX_HOSTS];
+static int ConnLookupInitialized = 0;
+
+struct FsCmdInputs PioctlInputs;
+struct FsCmdOutputs PioctlOutputs;
+
+void
+printDatarate(void)
+{
+ seconds = now.tv_sec + now.tv_usec *.000001
+ -opentime.tv_sec - opentime.tv_usec *.000001;
+ if ((seconds - oldseconds) > 30.) {
+ afs_int64 tmp;
+ tmp = xfered - oldxfered;
+ datarate = ((afs_uint32) (tmp >> 20)) / (seconds - oldseconds);
+ fprintf(stderr,"%llu MB transferred, present date rate = %.0f MB/sec.\n",
+ xfered >> 20, datarate);
+ oldxfered = xfered;
+ oldseconds = seconds;
+ }
+}
+
+void
+SetCellFname(char *name)
+{
+ struct afsconf_dir *tdir;
+
+ strcpy((char *) &cellFname,"/afs/");
+ if (name)
+ strcat((char *) &cellFname, name);
+ else {
+ tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
+ afsconf_GetLocalCell(tdir, &cellFname[5], MAXCELLCHARS);
+ }
+}
+
+afs_int32
+main (int argc, char **argv)
+{
+ afs_int32 code;
+ struct cmd_syndesc *ts;
+
+ strcpy(pnp, argv[0]);
+
+#ifdef AFS_PTHREAD_ENV
+ assert(pthread_key_create(&uclient_key, NULL) == 0);
+#endif
+ ts = cmd_CreateSyntax("read", readFile, CMD_REQUIRED,
+ "read a file from AFS");
+ cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename");
+ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
+ cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
+ cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
+
+ ts = cmd_CreateSyntax("fidread", readFile, CMD_REQUIRED,
+ "read on a non AFS-client a file from AFS");
+ cmd_IsAdministratorCommand(ts);
+ cmd_AddParm(ts, "-fid", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
+ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
+ cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
+ cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
+
+ ts = cmd_CreateSyntax("write", writeFile, CMD_REQUIRED,
+ "write a file into AFS");
+ cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
+ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
+ cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
+ cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
+ cmd_AddParm(ts, "-synthesize", CMD_SINGLE, CMD_OPTIONAL, "create data pattern of specified length instead reading from stdin");
+
+ ts = cmd_CreateSyntax("fidwrite", writeFile, CMD_REQUIRED,
+ "write a file into AFS");
+ cmd_IsAdministratorCommand(ts);
+ cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
+ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
+ cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
+ cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum");
+
+ ts = cmd_CreateSyntax("append", writeFile, CMD_REQUIRED,
+ "append to a file in AFS");
+ cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "AFS-filename");
+ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
+ cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
+
+ ts = cmd_CreateSyntax("fidappend", writeFile, CMD_REQUIRED,
+ "append to a file in AFS");
+ cmd_IsAdministratorCommand(ts);
+ cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, "volume.vnode.uniquifier");
+ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname");
+ cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *) 0);
+
+ code = cmd_Dispatch(argc, argv);
+ exit (0);
+}
+
+AFS_UNUSED
+afs_int32
+HandleLocalAuth(struct rx_securityClass **sc[3], afs_int32 *scIndex)
+{
+ static struct afsconf_dir *tdir = NULL;
+ struct ktc_principal sname;
+ struct ktc_token ttoken;
+ int kvno;
+ struct ktc_encryptionKey key;
+ afs_uint32 host = 0;
+ char *cell;
+ afs_int32 code;
+
+ tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
+ if (!tdir) {
+ fprintf(stderr,"Could not open configuration directory: %s.\n",
+ AFSDIR_SERVER_ETC_DIRPATH);
+ return -1;
+ }
+ cell = tdir->cellName;
+ strcpy(sname.cell, cell);
+ sname.instance[0] = 0;
+ strcpy(sname.name, "afs");
+ code=afsconf_GetLatestKey(tdir, &kvno, &key);
+ if (code) {
+ fprintf(stderr,"afsconf_GetLatestKey returned %d\n", code);
+ return -1;
+ }
+ ttoken.kvno = kvno;
+ des_init_random_number_generator(ktc_to_cblock(&key));
+ code = des_random_key(ktc_to_cblock(&ttoken.sessionKey));
+ if (code) {
+ fprintf(stderr,"des_random_key returned %d\n", code);
+ return -1;
+ }
+ ttoken.ticketLen = MAXKTCTICKETLEN;
+ code = tkt_MakeTicket(ttoken.ticket, &ttoken.ticketLen, &key,
+ AUTH_SUPERUSER, "", sname.cell,
+ 0, 0xffffffff,
+ &ttoken.sessionKey, host,
+ sname.name, sname.instance);
+ if (code)
+ *scIndex = 0;
+ else {
+ *scIndex = 2;
+ *sc[2] = (struct rx_securityClass *)
+ rxkad_NewClientSecurityObject(rxkad_clear,
+ &ttoken.sessionKey, ttoken.kvno,
+ ttoken.ticketLen, ttoken.ticket);
+ }
+ if (*scIndex == 0)
+ *sc[0] = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
+ return 0;
+}
+
+afs_int32
+AFS_Lookup(struct rx_connection *conn, AFSFid *dirfid, char *name,
+ AFSFid *outfid, AFSFetchStatus *outstatus, AFSFetchStatus
+ *dirstatus, AFSCallBack *callback, AFSVolSync *sync)
+{
+ afs_int32 code = VBUSY;
+ while (code == VBUSY) {
+ code = RXAFS_Lookup(conn, dirfid, name, outfid, outstatus, dirstatus,
+ callback, sync);
+ if (code == VBUSY) {
+ fprintf(stderr, "waiting for busy AFS volume %u.\n",
+ dirfid->Volume);
+#ifdef AFS_PTHREAD_ENV
+ sleep(10);
+#else
+ IOMGR_Sleep(10);
+#endif
+ }
+ }
+ return code;
+}
+
+afs_int32
+AFS_FetchStatus(struct rx_connection *conn, AFSFid *fid, AFSFetchStatus
+ *Status, AFSCallBack *callback, AFSVolSync *sync)
+{
+ afs_int32 code = VBUSY;
+
+ while (code == VBUSY) {
+ code = RXAFS_FetchStatus(conn, fid, Status, callback, sync);
+ if (code == VBUSY) {
+ fprintf(stderr, "waiting for busy AFS volume %u.\n",
+ fid->Volume);
+#ifdef AFS_PTHREAD_ENV
+ sleep(10);
+#else
+ IOMGR_Sleep(10);
+#endif
+ }
+ }
+ return code;
+}
+
+afs_int32
+StartAFS_FetchData(struct rx_call *call, AFSFid *fid, afs_int32 pos,
+ afs_int32 len)
+{
+ afs_int32 code = VBUSY;
+ while (code == VBUSY) {
+ code = StartRXAFS_FetchData (call, fid, pos, len);
+ if (code == VBUSY) {
+ fprintf(stderr, "waiting for busy AFS volume %u.\n",
+ fid->Volume);
+#ifdef AFS_PTHREAD_ENV
+ sleep(10);
+#else
+ IOMGR_Sleep(10);
+#endif
+ }
+ }
+ return code;
+}
+
+afs_int32
+StartAFS_FetchData64(struct rx_call *call, AFSFid *fid, afs_int64 pos,
+ afs_int64 len)
+{
+ afs_int32 code = VBUSY;
+ while (code == VBUSY) {
+ code = StartRXAFS_FetchData64 (call, fid, pos, len);
+ if (code == VBUSY) {
+ fprintf(stderr, "waiting for busy AFS volume %u.\n",
+ fid->Volume);
+#ifdef AFS_PTHREAD_ENV
+ sleep(10);
+#else
+ IOMGR_Sleep(10);
+#endif
+ }
+ }
+ return code;
+}
+
+afs_int32
+StartAFS_StoreData(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
+ afs_int32 pos, afs_int32 len, afs_int32 len2)
+{
+ afs_int32 code = VBUSY;
+ while (code == VBUSY) {
+ code = StartRXAFS_StoreData (call, fid, status, pos, len, len2);
+ if (code == VBUSY) {
+ fprintf(stderr, "waiting for busy AFS volume %u.\n",
+ fid->Volume);
+#ifdef AFS_PTHREAD_ENV
+ sleep(10);
+#else
+ IOMGR_Sleep(10);
+#endif
+ }
+ }
+ return code;
+}
+
+afs_uint32
+StartAFS_StoreData64(struct rx_call *call, AFSFid *fid, AFSStoreStatus *status,
+ afs_int64 pos, afs_int64 len, afs_int64 len2)
+{
+ afs_int32 code = VBUSY;
+ while (code == VBUSY) {
+ code = StartRXAFS_StoreData64 (call, fid, status, pos, len, len2);
+ if (code == VBUSY) {
+ fprintf(stderr, "waiting for busy AFS volume %u.\n",
+ fid->Volume);
+#ifdef AFS_PTHREAD_ENV
+ sleep(10);
+#else
+ IOMGR_Sleep(10);
+#endif
+ }
+ }
+ return code;
+}
+
+afs_int32
+SRXAFSCB_CallBack(struct rx_call *rxcall, AFSCBFids *Fids_Array,
+ AFSCBs *CallBack_Array)
+{
+ return 0;
+}
+
+afs_int32
+SRXAFSCB_InitCallBackState(struct rx_call *rxcall)
+{
+ return 0;
+}
+
+afs_int32
+SRXAFSCB_Probe(struct rx_call *rxcall)
+{
+ return 0;
+}
+
+afs_int32
+SRXAFSCB_GetCE(struct rx_call *rxcall,
+ afs_int32 index,
+ AFSDBCacheEntry * ce)
+{
+ return(0);
+}
+
+afs_int32
+SRXAFSCB_GetLock(struct rx_call *rxcall,
+ afs_int32 index,
+ AFSDBLock * lock)
+{
+ return(0);
+}
+
+afs_int32
+SRXAFSCB_XStatsVersion(struct rx_call *rxcall,
+ afs_int32 * versionNumberP)
+{
+ return(0);
+}
+
+afs_int32
+SRXAFSCB_GetXStats(struct rx_call *rxcall,
+ afs_int32 clientVersionNumber,
+ afs_int32 collectionNumber,
+ afs_int32 * srvVersionNumberP,
+ afs_int32 * timeP,
+ AFSCB_CollData * dataP)
+{
+ return(0);
+}
+
+afs_int32
+SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID *a_uuid)
+{
+ return(0);
+}
+
+
+afs_int32
+SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
+{
+ int code = 0;
+
+ addr->numberOfInterfaces = 0;
+ addr->uuid = uuid;
+#ifdef notdef
+ /* return all network interface addresses */
+ addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
+ for ( i=0; i < afs_cb_interface.numberOfInterfaces; i++) {
+ addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
+ addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
+ addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
+ }
+#endif
+
+ return code;
+}
+
+afs_int32
+SRXAFSCB_InitCallBackState2(struct rx_call *a_call, struct interfaceAddr *
+ addr)
+{
+ return RXGEN_OPCODE;
+}
+
+afs_int32
+SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID *a_uuid)
+{
+ return 0;
+}
+
+afs_int32
+SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
+ afs_uint32 *serverVersion, afs_uint32 *configCount,
+ cacheConfig *config)
+{
+ return RXGEN_OPCODE;
+}
+
+afs_int32
+SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
+{
+ return RXGEN_OPCODE;
+}
+
+afs_int32
+SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
+ char **a_name, serverList *a_hosts)
+{
+ return RXGEN_OPCODE;
+}
+
+afs_int32
+SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
+ afs_int32 *a_srvr_addr, afs_int32 *a_srvr_rank)
+{
+ return RXGEN_OPCODE;
+}
+
+afs_int32
+SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call, struct interfaceAddr *
+ addr, Capabilities *capabilities)
+{
+ return RXGEN_OPCODE;
+}
+
+afs_int32
+SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
+ char **a_name, serverList *a_hosts)
+{
+ return RXGEN_OPCODE;
+}
+
+afs_int32
+SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
+ struct AFSDBCacheEntry64 *a_result)
+{
+ return RXGEN_OPCODE;
+}
+
+void *
+InitializeCBService_LWP(void *unused)
+{
+ struct rx_securityClass *CBsecobj;
+ struct rx_service *CBService;
+
+ afs_uuid_create(&uuid);
+
+ CBsecobj = (struct rx_securityClass *)rxnull_NewServerSecurityObject();
+ if (!CBsecobj) {
+ fprintf(stderr,"rxnull_NewServerSecurityObject failed for callback service.\n");
+ exit(1);
+ }
+ CBService = rx_NewService(0, 1, "afs", &CBsecobj, 1,
+ RXAFSCB_ExecuteRequest);
+ if (!CBService) {
+ fprintf(stderr,"rx_NewService failed for callback service.\n");
+ exit(1);
+ }
+ rx_StartServer(1);
+ return 0;
+}
+
+
+int
+InitializeCBService(void)
+{
+#define RESTOOL_CBPORT 7102
+#define MAX_PORT_TRIES 1000
+#define LWP_STACK_SIZE (16 * 1024)
+ afs_int32 code;
+#ifdef AFS_PTHREAD_ENV
+ pthread_t CBservicePid, parentPid;
+ pthread_attr_t tattr;
+#else
+ PROCESS CBServiceLWP_ID, parentPid;
+#endif
+ int InitialCBPort;
+ int CBPort;
+
+#ifndef NO_AFS_CLIENT
+ if (!CBServiceNeeded)
+ return 0;
+#endif
+#ifndef AFS_PTHREAD_ENV
+ code = LWP_InitializeProcessSupport(LWP_MAX_PRIORITY - 2, &parentPid);
+ if (code != LWP_SUCCESS) {
+ fprintf(stderr,"Unable to initialize LWP support, code %d\n",
+ code);
+ exit(1);
+ }
+#endif
+
+#if defined(AFS_AIX_ENV) || defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI_ENV)
+ srandom(getpid());
+ InitialCBPort = RESTOOL_CBPORT + random() % 1000;
+#else /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
+#if defined(AFS_HPUX_ENV)
+ srand48(getpid());
+ InitialCBPort = RESTOOL_CBPORT + lrand48() % 1000;
+#else /* AFS_HPUX_ENV */
+ srand(getpid());
+ InitialCBPort = RESTOOL_CBPORT + rand() % 1000;
+#endif /* AFS_HPUX_ENV */
+#endif /* AFS_AIX_ENV || AFS_SUN_ENV || AFS_OSF_ENV || AFS_SGI_ENV */
+
+ CBPort = InitialCBPort;
+ do {
+ code = rx_Init(htons(CBPort));
+ if (code) {
+ if ((code == RX_ADDRINUSE) &&
+ (CBPort < MAX_PORT_TRIES + InitialCBPort)) {
+ CBPort++;
+ } else if (CBPort < MAX_PORT_TRIES + InitialCBPort) {
+ fprintf(stderr, "rx_Init didn't succeed for callback service."
+ " Tried port numbers %d through %d\n",
+ InitialCBPort, CBPort);
+ exit(1);
+ } else {
+ fprintf(stderr,"Couldn't initialize callback service "
+ "because too many users are running this program. "
+ "Try again later.\n");
+ exit(1);
+ }
+ }
+ } while(code);
+#ifdef AFS_PTHREAD_ENV
+ assert(pthread_attr_init(&tattr) == 0);
+ assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
+ assert(pthread_create(
+ &CBservicePid, &tattr, InitializeCBService_LWP, 0)
+ == 0);
+#else
+ code = LWP_CreateProcess(InitializeCBService_LWP, LWP_STACK_SIZE,
+ LWP_MAX_PRIORITY - 2, (int *) 0, "CBService",
+ &CBServiceLWP_ID);
+ if (code != LWP_SUCCESS) {
+ fprintf(stderr,"Unable to create the callback service LWP, code %d\n",
+ code);
+ exit(1);
+ }
+#endif
+ return 0;
+}
+
+int
+ScanVnode(char *fname, char *cell)
+{
+ afs_int32 i, code = 0;
+
+ SetCellFname(cell);
+ i = sscanf(fname, "%u.%u.%u",
+ &PioctlInputs.fid.Volume,
+ &PioctlInputs.fid.Vnode,
+ &PioctlInputs.fid.Unique);
+ if (i != 3) {
+ PioctlInputs.fid.Volume = 0;
+ PioctlInputs.fid.Vnode = 0;
+ PioctlInputs.fid.Unique = 0;
+ fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
+ code = EINVAL;
+ }
+ /*
+ * The following is used to handle the case of unknown uniquifier. We
+ * just need a valid reference to the volume to direct the RPC to the
+ * right fileserver. Therefore we take the root directory of the volume.
+ */
+ if (PioctlInputs.fid.Unique == 0) {
+ PioctlInputs.int32s[0] = PioctlInputs.fid.Vnode;
+ PioctlInputs.fid.Vnode = 1;
+ PioctlInputs.fid.Unique = 1;
+ }
+ return code;
+}
+
+int
+VLDBInit(int noAuthFlag, struct afsconf_cell *info)
+{
+ afs_int32 code;
+
+ code = ugen_ClientInit(noAuthFlag, (char *) AFSDIR_CLIENT_ETC_DIRPATH,
+ info->name, 0, &uclient,
+ NULL, pnp, rxkad_clear,
+ VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
+ 0, 0, USER_SERVICE_ID);
+ rxInitDone = 1;
+ return code;
+}
+
+afs_int32
+get_vnode_hosts(char *fname, char **cellp, afs_int32 *hosts, AFSFid *Fid,
+ int onlyRW)
+{
+ struct afsconf_dir *tdir;
+ struct vldbentry vldbEntry;
+ afs_int32 i, j, code, *h, len;
+ struct afsconf_cell info;
+ afs_int32 mask;
+
+ tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
+ if (!tdir) {
+ fprintf(stderr,"Could not process files in configuration directory "
+ "(%s).\n",AFSDIR_CLIENT_ETC_DIRPATH);
+ return -1;
+ }
+ if (!*cellp) {
+ len = MAXCELLCHARS;
+ *cellp = (char *) malloc(MAXCELLCHARS);
+ code = afsconf_GetLocalCell(tdir, *cellp, len);
+ if (code) return code;
+ }
+ code = afsconf_GetCellInfo(tdir, *cellp, AFSCONF_VLDBSERVICE, &info);
+ if (code) {
+ fprintf(stderr,"fs: cell %s not in %s/CellServDB\n",
+ *cellp, AFSDIR_CLIENT_ETC_DIRPATH);
+ return code;
+ }
+
+ i = sscanf(fname, "%u.%u.%u", &Fid->Volume, &Fid->Vnode, &Fid->Unique);
+ if (i != 3) {
+ fprintf(stderr,"fs: invalid vnode triple: %s\n", fname);
+ return 1;
+ }
+ code = VLDBInit(1, &info);
+ if (code == 0) {
+ code = ubik_VL_GetEntryByID(uclient, 0, Fid->Volume,
+ -1, &vldbEntry);
+ if (code == VL_NOENT)
+ fprintf(stderr,"fs: volume %u does not exist in this cell.\n",
+ Fid->Volume);
+ if (code) return code;
+ }
+ h = hosts;
+ mask = VLSF_RWVOL;
+ if (!onlyRW) mask |= VLSF_RWVOL;
+ for (i=0, j=0; j<vldbEntry.nServers; j++) {
+ if (vldbEntry.serverFlags[j] & mask) {
+ *h++ = ntohl(vldbEntry.serverNumber[j]);
+ i++;
+ }
+ }
+ for (; i<MAXHOSTS; i++) *h++ = 0;
+ return 0;
+}
+
+/* get_file_cell()
+ * Determine which AFS cell file 'fn' lives in, the list of servers that
+ * offer it, and the FID.
+ */
+afs_int32
+get_file_cell(char *fn, char **cellp, afs_int32 hosts[MAXHOSTS], AFSFid *Fid,
+ struct AFSFetchStatus *Status, afs_int32 create)
+{
+ afs_int32 code;
+ char buf[256];
+ struct ViceIoctl status;
+ int j;
+ afs_int32 *Tmpafs_int32;
+
+ memset((char *) Status, 0, sizeof(struct AFSFetchStatus));
+ memset(buf, 0, sizeof(buf));
+ status.in_size = 0;
+ status.out_size = sizeof(buf);
+ status.in = buf;
+ status.out = buf;
+ errno = 0;
+ code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
+ if (code && create) {
+ char *c;
+ int fd;
+ strcpy(buf,fn);
+ if ((c = strrchr(buf,'/'))) {
+ *c = 0;
+ code = pioctl(buf,VIOC_FILE_CELL_NAME, &status, 0);
+ if (!code) {
+ fd = open(fn, O_CREAT, 0644);
+ close(fd);
+ }
+ code = pioctl(fn, VIOC_FILE_CELL_NAME, &status, 0);
+ }
+ }
+ if (code) {
+ fprintf(stderr, "Unable to determine cell for %s\n", fn);
+ if (errno) {
+ perror(fn);
+ if (errno == EINVAL)
+ fprintf(stderr, "(File might not be in AFS)\n");
+ } else
+ afs_com_err(pnp, code, (char *) 0);
+ } else {
+ *cellp = (char *) malloc(strlen(buf)+1);
+ strcpy(*cellp, buf);
+ SetCellFname(*cellp);
+ memset(buf, 0, sizeof(buf));
+ status.in = 0;
+ status.in_size = 0;
+ status.out = buf;
+ status.out_size = sizeof(buf);
+ code = pioctl(fn, VIOCWHEREIS, &status, 0);
+ if (code) {
+ fprintf(stderr, "Unable to determine fileservers for %s\n", fn);
+ if (errno) {
+ perror(fn);
+ }
+ else
+ afs_com_err(pnp, code, (char *) 0);
+ } else {
+ Tmpafs_int32 = (afs_int32 *)buf;
+ for (j=0;j<MAXHOSTS;++j) {
+ hosts[j] = Tmpafs_int32[j];
+ if (!Tmpafs_int32[j])
+ break;
+ }
+ }
+ memset(buf, 0, sizeof(buf));
+ status.in_size = 0;
+ status.out_size = sizeof(buf);
+ status.in = 0;
+ status.out = buf;
+ code = pioctl(fn, VIOCGETFID, &status, 0);
+ if (code) {
+ fprintf(stderr, "Unable to determine FID for %s\n", fn);
+ if (errno) {
+ perror(fn);
+ } else {
+ afs_com_err(pnp, code, (char *) 0);
+ }
+ } else {
+ afs_int32 saveCommand, saveVolume;
+
+ Tmpafs_int32 = (afs_int32 *)buf;
+ Fid->Volume = Tmpafs_int32[1];
+ Fid->Vnode = Tmpafs_int32[2];
+ Fid->Unique = Tmpafs_int32[3];
+ status.in_size = sizeof(struct FsCmdInputs);
+ status.out_size = sizeof(struct FsCmdOutputs);
+ status.in = (char *) &PioctlInputs;
+ status.out = (char *) &PioctlOutputs;
+ saveCommand = PioctlInputs.command;
+ saveVolume = PioctlInputs.fid.Volume;
+ PioctlInputs.command = 0;
+ PioctlInputs.fid.Volume = 0;
+ if (!pioctl(fn, VIOC_FS_CMD, &status, 0))
+ memcpy((char *)Status, &PioctlOutputs.status,
+ sizeof(struct AFSFetchStatus));
+ PioctlInputs.command = saveCommand;
+ PioctlInputs.fid.Volume = saveVolume;
+ if (create && (Status->Length || Status->Length_hi)) {
+ fprintf(stderr,"AFS file %s not empty, request aborted.\n",
+ fn);
+ exit(-5);
+ }
+ }
+ }
+ return code;
+}
+
+int
+DestroyConnections(void)
+{
+ int i;
+
+ if (!ConnLookupInitialized) return 0;
+ for (i = 0; i < MAX_HOSTS; i++) {
+ if (!ConnLookup[i].conn) break;
+ RXAFS_GiveUpAllCallBacks(ConnLookup[i].conn);
+ rx_DestroyConnection(ConnLookup[i].conn);
+ }
+ if (!rxInitDone)
+ rx_Finalize();
+ return 0;
+}
+
+
+int
+LogErrors (int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ return vfprintf(stderr, fmt, ap);
+}
+
+int
+readFile(struct cmd_syndesc *as, void *unused)
+{
+ char *fname;
+ char *cell = 0;
+ afs_int32 code;
+ afs_int32 hosts[MAXHOSTS];
+ AFSFid Fid;
+ int i, j;
+ struct rx_connection *RXConn;
+ struct cellLookup *cl;
+ struct rx_call *tcall;
+ struct AFSVolSync tsync;
+ struct AFSFetchStatus OutStatus;
+ struct AFSCallBack CallBack;
+ afs_int64 Pos;
+ afs_int32 len;
+ afs_int64 length, Len;
+ u_char vnode = 0;
+ u_char first = 1;
+ int bytes;
+ int worstCode = 0;
+ char *buf = 0;
+ int bufflen = BUFFLEN;
+
+ i=0;
+
+ if (as->name[0] == 'f')
+ vnode = 1;
+ if (as->parms[2].items)
+ verbose = 1;
+ if (as->parms[3].items) {
+ md5sum = 1;
+ MD5_Init(&md5);
+ }
+
+ CBServiceNeeded = 1;
+ InitializeCBService();
+
+ gettimeofday (&starttime, &Timezone);
+ fname = as->parms[0].items->data;
+ cell = 0;
+ if (as->parms[1].items)
+ cell = as->parms[1].items->data;
+ if (vnode)
+ code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
+ else
+ code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, 0);
+ if (code) {
+ fprintf(stderr,"File not found %s\n", fname);
+ return code;
+ }
+ if (Fid.Vnode & 1) {
+ fprintf(stderr,"%s is a directory, not a file\n", fname);
+ return ENOENT;
+ }
+ cl = FindCell(cell);
+ for (j=0;j<MAXHOSTS;++j) {
+ int useHost;
+
+ if (first && as->parms[6].items) {
+ afs_uint32 fields, ip1, ip2, ip3, ip4;
+ fields = sscanf(as->parms[6].items->data, "%d.%d.%d.%d",
+ &ip1, &ip2, &ip3, &ip4);
+ useHost = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
+ j--;
+ } else {
+ if (!hosts[j])
+ break;
+ useHost = hosts[j];
+ }
+ first = 0;
+ RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
+ cl->sc[cl->scIndex], cl->scIndex);
+ if (!RXConn) {
+ fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
+ useHost);
+ continue;
+ }
+#ifndef NO_AFS_CLIENT
+ if (vnode) {
+#endif /* NO_AFS_CLIENT */
+ code = AFS_FetchStatus(RXConn, &Fid, &OutStatus, &CallBack, &tsync);
+ if (code) {
+ fprintf(stderr,"RXAFS_FetchStatus failed to server 0x%X for"
+ " file %s, code was %d\n",
+ useHost, fname, code);
+ continue;
+ }
+#ifndef NO_AFS_CLIENT
+ }
+#endif /* NO_AFS_CLIENT */
+ gettimeofday(&opentime, &Timezone);
+ if (verbose) {
+ seconds = opentime.tv_sec + opentime.tv_usec *.000001
+ -starttime.tv_sec - starttime.tv_usec *.000001;
+ fprintf(stderr,"Startup to find the file took %.3f sec.\n",
+ seconds);
+ }
+ Len = OutStatus.Length_hi;
+ Len <<= 32;
+ Len += OutStatus.Length;
+ ZeroInt64(Pos);
+ {
+ afs_uint32 high, low;
+
+ tcall = rx_NewCall(RXConn);
+ code = StartAFS_FetchData64 (tcall, &Fid, Pos, Len);
+ if (code == RXGEN_OPCODE) {
+ afs_uint32 tmpPos, tmpLen;
+ tmpPos = Pos; tmpLen = Len;
+ code = StartAFS_FetchData (tcall, &Fid, Pos, Len);
+ bytes = rx_Read(tcall, (char *)&low, sizeof(afs_int32));
+ length = ntohl(low);
+ if (bytes != 4) code = -3;
+ } else if (!code) {
+ bytes = rx_Read(tcall, (char *)&high, 4);
+ length = ntohl(high);
+ length <<= 32;
+ bytes += rx_Read(tcall, (char *)&low, 4);
+ length += ntohl(low);
+ if (bytes != 8) code = -3;
+ }
+ if (code) {
+ if (code == RXGEN_OPCODE) {
+ fprintf(stderr, "File server for %s might not be running a"
+ " multi-resident AFS server\n",
+ fname);
+ } else {
+ fprintf(stderr, "%s for %s ended with error code %d\n",
+ (char *) &as->name, fname, code);
+ exit(1);
+ }
+ }
+ if (length > bufflen)
+ len = bufflen;
+ else
+ len = length;
+ buf = (char *)malloc(len);
+ if (!buf) {
+ fprintf(stderr, "couldn't allocate buffer\n");
+ exit(1);
+ }
+ while (!code && NonZeroInt64(length)) {
+ if (length > bufflen)
+ len = bufflen;
+ else
+ len = length;
+ bytes = rx_Read(tcall, (char *) buf, len);
+ if (bytes != len) {
+ code = -3;
+ }
+ if (md5sum)
+ MD5_Update(&md5, buf, len);
+ if (!code)
+ write(1, buf, len);
+ length -= len;
+ xfered += len;
+ gettimeofday(&now, &Timezone);
+ if (verbose)
+ printDatarate();
+ }
+ worstCode = code;
+ code = EndRXAFS_FetchData (tcall, &OutStatus, &CallBack, &tsync);
+ rx_EndCall(tcall, 0);
+ if (!worstCode)
+ worstCode = code;
+ }
+ break;
+ }
+ gettimeofday(&readtime, &Timezone);
+ if (worstCode) {
+ fprintf(stderr,"%s failed with code %d\n",
+ (char *) &as->name, worstCode);
+ } else {
+ if (md5sum) {
+ afs_uint32 md5int[4];
+ char *p;
+ MD5_Final((char *) &md5int[0], &md5);
+ p = fname + strlen(fname);
+ while (p > fname) {
+ if (*(--p) == '/') {
+ ++p;
+ break;
+ }
+ }
+ fprintf(stderr, "%08x%08x%08x%08x %s\n",
+ htonl(md5int[0]), htonl(md5int[1]),
+ htonl(md5int[2]), htonl(md5int[3]), p);
+ }
+ if(verbose) {
+ seconds = readtime.tv_sec + readtime.tv_usec *.000001
+ -opentime.tv_sec - opentime.tv_usec *.000001;
+ fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
+ xfered, seconds);
+ datarate = (xfered >> 20) / seconds;
+ fprintf(stderr,"Total data rate = %.0f MB/sec. for read\n",
+ datarate);
+ }
+ }
+ DestroyConnections();
+ return worstCode;
+}
+
+int
+writeFile(struct cmd_syndesc *as, void *unused)
+{
+ char *fname = NULL;
+ char *cell = 0;
+ afs_int32 code, localcode = 0;
+ afs_int32 hosts[MAXHOSTS];
+ afs_uint32 useHost;
+ AFSFid Fid;
+ int i;
+ struct rx_connection *RXConn;
+ struct cellLookup *cl;
+ struct rx_call *tcall;
+ struct AFSVolSync tsync;
+ struct AFSFetchStatus OutStatus;
+ struct AFSStoreStatus InStatus;
+ afs_int64 Pos;
+ afs_int64 length, Len, synthlength = 0, offset = 0;
+ u_char vnode = 0;
+ int bytes;
+ int worstCode = 0;
+ int append = 0;
+ int synthesize = 0;
+ afs_int32 byteswritten;
+ struct wbuf *bufchain = 0;
+ struct wbuf *previous, *tbuf;
+
+ i=0;
+
+ if (as->name[0] == 'f') {
+ vnode = 1;
+ if (as->name[3] == 'a')
+ append = 1;
+ } else
+ if (as->name[0] == 'a')
+ append = 1;
+ if (as->parms[2].items)
+ verbose = 1;
+ if (as->parms[3].items)
+ md5sum = 1;
+ if (as->parms[4].items) {
+ code = util_GetInt64(as->parms[4].items->data, &synthlength);
+ if (code) {
+ fprintf(stderr, "Invalid value for synthesize length %s\n",
+ as->parms[4].items->data);
+ return code;
+ }
+ synthesize = 1;
+ }
+ CBServiceNeeded = 1;
+ InitializeCBService();
+
+ if (as->parms[0].items)
+ fname = as->parms[0].items->data;
+
+ cell = 0;
+ if (as->parms[1].items) cell = as->parms[1].items->data;
+ if (vnode) {
+ code = get_vnode_hosts(fname, &cell, hosts, &Fid, 1);
+ if (code)
+ return code;
+ } else
+ code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, append ? 0 : 1);
+ if (code) {
+ if (code != -5)
+ fprintf(stderr,"File or directory not found: %s\n",
+ fname);
+ return code;
+ }
+ if (Fid.Vnode & 1) {
+ fprintf(stderr,"%s is a directory, not a file\n", fname);
+ return ENOENT;
+ }
+ if (!hosts[0]) {
+ fprintf(stderr,"AFS file not found: %s\n", fname);
+ return ENOENT;
+ }
+ cl = FindCell(cell);
+ gettimeofday (&starttime, &Timezone);
+ useHost = hosts[0];
+ RXConn = FindRXConnection(useHost, htons(AFSCONF_FILEPORT), 1,
+ cl->sc[cl->scIndex], cl->scIndex);
+ if (!RXConn) {
+ fprintf(stderr,"rx_NewConnection failed to server 0x%X\n",
+ hosts[0]);
+ return -1;
+ }
+ InStatus.Mask = AFS_SETMODE + AFS_FSYNC;
+ InStatus.UnixModeBits = 0644;
+ if (append) {
+ Pos = OutStatus.Length_hi;
+ Pos = (Pos << 32) | OutStatus.Length;
+ } else
+ Pos = 0;
+ previous = (struct wbuf *)&bufchain;
+ if (md5sum)
+ MD5_Init(&md5);
+
+ Len = 0;
+ while (Len<WRITEBUFFLEN) {
+ tbuf = (struct wbuf *)malloc(sizeof(struct wbuf));
+ if (!tbuf) {
+ if (!bufchain) {
+ fprintf(stderr, "Couldn't allocate buffer, aborting\n");
+ exit(1);
+ }
+ break;
+ }
+ memset(tbuf, 0, sizeof(struct wbuf));
+ tbuf->buflen = BUFFLEN;
+ if (synthesize) {
+ afs_int32 ll, l = tbuf->buflen;
+ if (l > synthlength)
+ l = synthlength;
+ for (ll = 0; ll < l; ll += 4096) {
+ sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
+ (unsigned int)(offset >> 32),
+ (unsigned int)(offset & 0xffffffff) + ll);
+ }
+ offset += l;
+ synthlength -= l;
+ tbuf->used = l;
+ } else
+ tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
+ if (!tbuf->used) {
+ free(tbuf);
+ break;
+ }
+ if (md5sum)
+ MD5_Update(&md5, &tbuf->buf, tbuf->used);
+ previous->next = tbuf;
+ previous = tbuf;
+ Len += tbuf->used;
+ }
+ gettimeofday(&opentime, &Timezone);
+ if (verbose) {
+ seconds = opentime.tv_sec + opentime.tv_usec *.000001
+ -starttime.tv_sec - starttime.tv_usec *.000001;
+ fprintf(stderr,"Startup to find the file took %.3f sec.\n",
+ seconds);
+ }
+ bytes = Len;
+ while (!code && bytes) {
+ afs_int32 code2;
+ Len = bytes;
+ restart:
+ tcall = rx_NewCall(RXConn);
+ code = StartAFS_StoreData64 (tcall, &Fid, &InStatus, Pos, Len, Pos+Len);
+ if (code == RXGEN_OPCODE) {
+ afs_uint32 tmpLen, tmpPos;
+ tmpPos = Pos;
+ tmpLen = Len;
+ if (Pos+Len > 0x7fffffff) {
+ fprintf(stderr,"AFS fileserver does not support files >= 2 GB\n");
+ return EFBIG;
+ }
+ code = StartAFS_StoreData (tcall, &Fid, &InStatus, tmpPos, tmpLen,
+ tmpPos+tmpLen);
+ }
+ if (code) {
+ fprintf(stderr, "StartRXAFS_StoreData had error code %d\n", code);
+ return code;
+ }
+ length = Len;
+ tbuf = bufchain;
+ if (Len) {
+ for (tbuf= bufchain; tbuf; tbuf=tbuf->next) {
+ if (!tbuf->used)
+ break;
+ byteswritten = rx_Write(tcall, tbuf->buf, tbuf->used);
+ if (byteswritten != tbuf->used) {
+ fprintf(stderr,"Only %d instead of %" AFS_INT64_FMT " bytes transferred by rx_Write()\n", byteswritten, length);
+ fprintf(stderr, "At %" AFS_UINT64_FMT " bytes from the end\n", length);
+ code = -4;
+ break;
+ }
+ xfered += tbuf->used;
+ gettimeofday(&now, &Timezone);
+ if (verbose)
+ printDatarate();
+ length -= tbuf->used;
+ }
+ }
+ worstCode = code;
+ code = EndRXAFS_StoreData64 (tcall, &OutStatus, &tsync);
+ if (code) {
+ fprintf(stderr, "EndRXAFS_StoreData64 returned %d\n", code);
+ worstCode = code;
+ }
+ code2 = rx_Error(tcall);
+ if (code2) {
+ fprintf(stderr, "rx_Error returned %d\n", code2);
+ worstCode = code2;
+ }
+ code2 = rx_EndCall(tcall, localcode);
+ if (code2) {
+ fprintf(stderr, "rx_EndCall returned %d\n", code2);
+ worstCode = code2;
+ }
+ code = worstCode;
+ if (code == 110) {
+ fprintf(stderr, "Waiting for busy volume\n");
+ sleep(10);
+ goto restart;
+ }
+ Pos += Len;
+ bytes = 0;
+ if (!code) {
+ for (tbuf = bufchain; tbuf; tbuf=tbuf->next) {
+ tbuf->offset = 0;
+ if (synthesize) {
+ afs_int32 ll, l = tbuf->buflen;
+ if (l > synthlength)
+ l = synthlength;
+ for (ll = 0; ll < l; ll += 4096) {
+ sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n",
+ (unsigned int)(offset >> 32),
+ (unsigned int)(offset & 0xffffffff) + ll);
+ }
+ offset += l;
+ synthlength -= l;
+ tbuf->used = l;
+ } else
+ tbuf->used = read(0, &tbuf->buf, tbuf->buflen);
+ if (!tbuf->used)
+ break;
+ if (md5sum)
+ MD5_Update(&md5, &tbuf->buf, tbuf->used);
+ Len += tbuf->used;
+ bytes += tbuf->used;
+ }
+ }
+ }
+ gettimeofday(&writetime, &Timezone);
+ if (worstCode) {
+ fprintf(stderr,"%s failed with code %d\n", as->name, worstCode);
+ } else if(verbose) {
+ seconds = writetime.tv_sec + writetime.tv_usec *.000001
+ -opentime.tv_sec - opentime.tv_usec *.000001;
+ fprintf(stderr,"Transfer of %llu bytes took %.3f sec.\n",
+ xfered, seconds);
+ datarate = (xfered >> 20) / seconds;
+ fprintf(stderr,"Total data rate = %.0f MB/sec. for write\n",
+ datarate);
+ }
+ while (bufchain) {
+ tbuf = bufchain;
+ bufchain = tbuf->next;
+ free(tbuf);
+ }
+ DestroyConnections();
+ if (md5sum) {
+ afs_uint32 md5int[4];
+ char *p;
+ MD5_Final((char *) &md5int[0], &md5);
+ p = fname + strlen(fname);
+ while (p > fname) {
+ if (*(--p) == '/') {
+ ++p;
+ break;
+ }
+ }
+ fprintf(stdout, "%08x%08x%08x%08x %s\n",
+ htonl(md5int[0]), htonl(md5int[1]),
+ htonl(md5int[2]), htonl(md5int[3]), p);
+ }
+ return worstCode;
+}
+
+struct cellLookup *
+FindCell(char *cellName)
+{
+ char name[MAXCELLCHARS];
+ char *np;
+ struct cellLookup *p, *p2;
+ static struct afsconf_dir *tdir;
+ struct ktc_principal sname;
+ struct ktc_token ttoken;
+ afs_int32 len, code;
+
+ if (cellName) {
+ np = cellName;
+ } else {
+ if (!tdir)
+ tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
+ len = MAXCELLCHARS;
+ afsconf_GetLocalCell(tdir, name, len);
+ np = (char *) &name;
+ }
+ SetCellFname(np);
+
+ p2 = (struct cellLookup *) &Cells;
+ for (p = Cells; p; p = p->next) {
+ if (!strcmp((char *)&p->info.name, np)) {
+#ifdef NO_AFS_CLIENT
+ if (!strcmp((char *)&lastcell, np))
+ code = VLDBInit(1, &p->info);
+#endif
+ return p;
+ }
+ p2 = p;
+ }
+ p2->next = (struct cellLookup *) malloc(sizeof(struct cellLookup));
+ p = p2->next;
+ memset(p, 0, sizeof(struct cellLookup));
+ p->next = (struct cellLookup *) 0;
+ if (!tdir)
+ tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
+ if (afsconf_GetCellInfo(tdir, np, AFSCONF_VLDBSERVICE, &p->info)) {
+ p2->next = (struct cellLookup *) 0;
+ free(p);
+ p = (struct cellLookup *) 0;
+ } else {
+#ifdef NO_AFS_CLIENT
+ if (code = VLDBInit(1, &p->info))
+ fprintf(stderr,"VLDBInit failed for cell %s\n", p->info.name);
+#endif
+ strcpy((char *)&sname.cell, (char *)&p->info.name);
+ sname.instance[0] = 0;
+ strcpy(sname.name, "afs");
+ code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL);
+ if (code)
+ p->scIndex = 0;
+ else {
+ if ((ttoken.kvno >= 0) && (ttoken.kvno <= 255))
+ /* this is a kerberos ticket, set scIndex accordingly */
+ p->scIndex = 2;
+ else {
+ fprintf(stderr,"funny kvno (%d) in ticket, proceeding\n",
+ ttoken.kvno);
+ p->scIndex = 2;
+ }
+ p->sc[2] = (struct rx_securityClass *)
+ rxkad_NewClientSecurityObject(rxkad_clear, &ttoken.sessionKey,
+ ttoken.kvno, ttoken.ticketLen,
+ ttoken.ticket);
+ }
+ if (p->scIndex == 0)
+ p->sc[0] = (struct rx_securityClass *)
+ rxnull_NewClientSecurityObject();
+ }
+
+ if (p)
+ return p;
+ else
+ return 0;
+}
+
+struct rx_connection *
+FindRXConnection(afs_uint32 host, u_short port, u_short service,
+ struct rx_securityClass *securityObject,
+ int serviceSecurityIndex)
+{
+ int i;
+
+ if (!ConnLookupInitialized) {
+ memset(ConnLookup, 0, MAX_HOSTS * sizeof(struct connectionLookup));
+ ConnLookupInitialized = 1;
+ }
+
+ for (i = 0; i < MAX_HOSTS; i++) {
+ if ((ConnLookup[i].host == host) && (ConnLookup[i].port == port))
+ return ConnLookup[i].conn;
+ if (!ConnLookup[i].conn)
+ break;
+ }
+
+ if (i >= MAX_HOSTS)
+ return 0;
+
+ ConnLookup[i].conn = rx_NewConnection(host, port, service, securityObject, serviceSecurityIndex);
+ if (ConnLookup[i].conn) {
+ ConnLookup[i].host = host;
+ ConnLookup[i].port = port;
+ }
+
+ return ConnLookup[i].conn;
+}