From e475ca5410dcb79b26c9c5e79ccdb9d9f2357a86 Mon Sep 17 00:00:00 2001 From: Chaz Chandler Date: Tue, 20 Jul 2010 10:25:20 -0400 Subject: [PATCH] afsio: rewrite using libafscp afsio is a utility for file transfer to and from AFS file space without the help of the AFS client/cache manager. Using libafscp, this (partially rewritten) version of afsio is able to accomplish (1) authenticated access to an AFS path or FID (an existing KerberosV ticket is required), (2) fall back on unauthenticated ("anonymous") access if authentication (token acquisition) fails, and (3) work independtly of the AFS cache manager (afsd need not be running, though CellServDB and ThisCell are currently required). issues: 1) libvldbint and libafsint are not compiled pthreaded. we link in what we need. this should be changed when we are all-pthreaded. 2) venus is not a pthreaded-directory otherwise. same deal: in an all-pthreaded universe, undo the bodge that we do here. 3) venus is not an all-krb5 directory either. slight ick. Reviewed-on: http://gerrit.openafs.org/4381 Tested-by: BuildBot Reviewed-by: Derrick Brashear (cherry picked from commit 94d44d59e3d18f1d450e495a55fdd927e7584948) Change-Id: Ibe140c58970f1b4f2f9e7f016e55d770f8cdcc09 Reviewed-on: http://gerrit.openafs.org/5383 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- Makefile.in | 2 +- NTMakefile | 11 +- acinclude.m4 | 3 +- src/WINNT/afsd/NTMakefile | 24 +- src/config/afsconfig-windows.h | 3 + src/libafscp/Makefile.in | 3 + src/libafscp/NTMakefile | 1 + src/libafscp/afscp_dir.c | 4 + src/libafscp/afscp_fid.c | 4 + src/libafscp/afscp_roken.c | 243 +++++ src/libafscp/afscp_search.h | 57 + src/libafscp/afscp_volume.c | 4 + src/venus/Makefile.in | 52 +- src/venus/afsio.c | 1873 ++++++++++++-------------------- 14 files changed, 1064 insertions(+), 1220 deletions(-) create mode 100644 src/libafscp/afscp_roken.c create mode 100644 src/libafscp/afscp_search.h diff --git a/Makefile.in b/Makefile.in index c4bc12bb57..e9f9a828c8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -340,7 +340,7 @@ dvolser: project tviced usd libafsrpc libafsauthent volser echo Not building DAFS volser for ${SYS_NAME} ;; \ esac -venus: cmd comerr volser ptserver +venus: cmd comerr volser ptserver libafscp +${COMPILE_PART1} venus ${COMPILE_PART2} +${COMPILE_PART1} venus/test ${COMPILE_PART2} diff --git a/NTMakefile b/NTMakefile index 4b96d5db1c..305b9b9119 100644 --- a/NTMakefile +++ b/NTMakefile @@ -68,6 +68,13 @@ afsreg_headers: $(NTMAKE_HEADERS) $(CD) ..\..\.. +libafscp_headers: + @echo ***** $@ + $(DOCD) $(SRC)\libafscp + $(CD) $(SRC)\libafscp + $(NTMAKE_HEADERS) + $(CD) ..\..\.. + lwp_headers: @echo ***** $@ $(DOCD) $(SRC)\lwp @@ -480,7 +487,7 @@ client_osi: license $(NTMAKE) $(CD) ..\..\.. -afsd: client_osi +afsd: client_osi libafscp @echo ***** $@ $(DOCD) $(SRC)\WINNT\$@ $(CD) $(SRC)\WINNT\$@ @@ -648,7 +655,7 @@ rpctestlib: fsint libafsrpc $(NTMAKE) $(CD) ..\.. -libafscp: util afs volser vlserver rx auth fsint afsdobjs +libafscp: libafscp_headers util afs volser vlserver rx auth fsint afsdobjs @echo ***** $@ $(DOCD) $(SRC)\$@ $(CD) $(SRC)\$@ diff --git a/acinclude.m4 b/acinclude.m4 index db9b0e9fb2..2444a9b6e6 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1248,6 +1248,7 @@ AC_CHECK_HEADERS(security/pam_modules.h ucontext.h regex.h sys/statvfs.h sys/sta AC_CHECK_HEADERS(linux/errqueue.h,,,[#include ]) AC_CHECK_HEADERS(et/com_err.h) AC_CHECK_HEADERS(ncurses.h curses.h) +AC_CHECK_HEADERS(search.h) AC_CHECK_TYPES([fsblkcnt_t],,,[ #include @@ -1297,7 +1298,7 @@ else fi AC_SUBST(BUILD_LOGIN) -AC_CHECK_FUNCS(snprintf strlcat strlcpy flock getrlimit) +AC_CHECK_FUNCS(snprintf strlcat strlcpy flock getrlimit strnlen tsearch) AC_CHECK_FUNCS(setprogname getprogname sigaction mkstemp vsnprintf strerror strcasestr) AC_CHECK_FUNCS(setvbuf vsyslog getcwd) AC_CHECK_FUNCS(regcomp regexec regerror) diff --git a/src/WINNT/afsd/NTMakefile b/src/WINNT/afsd/NTMakefile index e94f1f28fe..a892552221 100644 --- a/src/WINNT/afsd/NTMakefile +++ b/src/WINNT/afsd/NTMakefile @@ -395,7 +395,6 @@ EXELIBS3 = \ $(DESTDIR)\lib\afs\afscmd.lib \ $(DESTDIR)\lib\afsrxkad.lib - # klog.exe $(EXEDIR)\klog.exe: $(OUT)\cklog.obj $(OUT)\klog.res $(EXELIBS) $(EXECONLINK) dnsapi.lib mpr.lib iphlpapi.lib shell32.lib @@ -468,7 +467,7 @@ $(EXEDIR)\fs.exe: $(FSOBJS) $(OUT)\fs.res $(EXELIBS) $(SYMSTORE_IMPORT) # cmdebug.exe -$(EXEDIR)\cmdebug.exe: $(CMDBGOBJS) $(OUT)\cmdebug.res $(EXELIBS2) +$(EXEDIR)\cmdebug.exe: $(CMDBGOBJS) $(OUT)\cmdebug.res $(EXECONLINK) $(EXELIBS2) dnsapi.lib mpr.lib iphlpapi.lib shell32.lib rpcrt4.lib $(_VC_MANIFEST_EMBED_EXE) $(EXEPREP) @@ -476,8 +475,25 @@ $(EXEDIR)\cmdebug.exe: $(CMDBGOBJS) $(OUT)\cmdebug.res $(EXELIBS2) $(SYMSTORE_IMPORT) # afsio.exe -$(EXEDIR)\afsio.exe: $(AFSIOOBJS) $(OUT)\afsio.res $(RXOBJS) $(AFSD_EXELIBS) $(EXELIBS3) - $(EXECONLINK) $(RXOBJS) $(AFSD_EXELIBS) $(EXELIBS3) dnsapi.lib mpr.lib iphlpapi.lib shell32.lib rpcrt4.lib +AFSCPLIB = \ + $(DESTDIR)\lib\afs\afscp.lib + +!IF "$(CPU)" == "IA64" || "$(CPU)" == "AMD64" || "$(CPU)" == "ALPHA64" +KFWLIBS = \ + ..\kfw\lib\$(CPU)\krb5_64.lib \ + ..\kfw\lib\$(CPU)\comerr64.lib \ + dnsapi.lib mpr.lib delayimp.lib +LINKOPTS = /DELAYLOAD:krb5_64.dll /DELAYLOAD:comerr64.dll +!else +KFWLIBS = \ + ..\kfw\lib\$(CPU)\krb5_32.lib \ + ..\kfw\lib\$(CPU)\comerr32.lib \ + dnsapi.lib mpr.lib delayimp.lib +LINKOPTS = /DELAYLOAD:krbv4w32.dll /DELAYLOAD:krb5_32.dll /DELAYLOAD:comerr32.dll +!endif + +$(EXEDIR)\afsio.exe: $(AFSIOOBJS) $(OUT)\afsio.res $(RXOBJS) $(AFSD_EXELIBS) $(EXELIBS3) $(AFSCPLIB) + $(EXECONLINK) $(KFWLIBS) dnsapi.lib mpr.lib iphlpapi.lib shell32.lib rpcrt4.lib $(_VC_MANIFEST_EMBED_EXE) $(EXEPREP) $(CODESIGN_USERLAND) diff --git a/src/config/afsconfig-windows.h b/src/config/afsconfig-windows.h index f6c9d92a3b..016bbd25f3 100644 --- a/src/config/afsconfig-windows.h +++ b/src/config/afsconfig-windows.h @@ -64,6 +64,9 @@ /* Define if you have the socket function. */ #define HAVE_SOCKET +/* Define if you have the strnlen function. */ +#define HAVE_STRNLEN 1 + /* Define if you have the header file. */ #undef HAVE_DIRECT_H diff --git a/src/libafscp/Makefile.in b/src/libafscp/Makefile.in index 0b8664bd34..cac4dee708 100644 --- a/src/libafscp/Makefile.in +++ b/src/libafscp/Makefile.in @@ -23,6 +23,7 @@ LIBOBJS = \ afscp_init.o \ afscp_util.o \ afscp_dirops.o \ + afscp_roken.o \ afscp_acl.o all: \ @@ -30,6 +31,8 @@ all: \ ${TOP_LIBDIR}/libafscp.a \ depinstall +afscp_roken.o: afscp_roken.c + ${CCRULE} afscp_callback.o: afscp_callback.c ${CCRULE} afscp_server.o: afscp_server.c diff --git a/src/libafscp/NTMakefile b/src/libafscp/NTMakefile index e614078659..5217674517 100644 --- a/src/libafscp/NTMakefile +++ b/src/libafscp/NTMakefile @@ -35,6 +35,7 @@ LIBOBJS =\ $(OUT)\afscp_init.obj \ $(OUT)\afscp_util.obj \ $(OUT)\afscp_dirops.obj \ + $(OUT)\afscp_roken.obj \ $(OUT)\afscp_acl.obj \ $(OUT)\AFS_component_version_number.obj diff --git a/src/libafscp/afscp_dir.c b/src/libafscp/afscp_dir.c index 64506b9eb4..f80e8ef554 100644 --- a/src/libafscp/afscp_dir.c +++ b/src/libafscp/afscp_dir.c @@ -27,7 +27,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifdef HAVE_SEARCH_H #include +#else +#include "afscp_search.h" +#endif #include #include diff --git a/src/libafscp/afscp_fid.c b/src/libafscp/afscp_fid.c index f3397005ca..812e09a090 100644 --- a/src/libafscp/afscp_fid.c +++ b/src/libafscp/afscp_fid.c @@ -27,7 +27,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifdef HAVE_SEARCH_H #include +#else +#include "afscp_search.h" +#endif #include #include diff --git a/src/libafscp/afscp_roken.c b/src/libafscp/afscp_roken.c new file mode 100644 index 0000000000..6c11305fcc --- /dev/null +++ b/src/libafscp/afscp_roken.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 1995 - 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR 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. + */ + +/* this file can go away when roken appears in this branch */ +#include +#include "afscp.h" +#include "afscp_internal.h" + +#ifdef ROKEN_LIB_FUNCTION +#error this file can go away when roken appears in this branch +#endif + +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif + +#ifndef HAVE_STRNLEN +ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL +strnlen(const char *s, size_t len) +{ + size_t i; + + for(i = 0; i < len && s[i]; i++) + ; + return i; +} +#endif + +#ifndef HAVE_TSEARCH +/* + * Tree search generalized from Knuth (6.2.2) Algorithm T just like + * the AT&T man page says. + * + * The node_t structure is for internal use only, lint doesn't grok it. + * + * Written by reading the System V Interface Definition, not the code. + * + * Totally public domain. + * + * $NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $ + * $NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $ + * $NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ + * $NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ + */ + +#include +#include +#include "afscp_search.h" + +typedef struct node { + char *key; + struct node *llink, *rlink; +} node_t; + +#ifndef __DECONST +#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) +#endif + +/* + * find or insert datum into search tree + * + * Parameters: + * vkey: key to be located + * vrootp: address of tree root + */ + +ROKEN_LIB_FUNCTION void * +rk_tsearch(const void *vkey, void **vrootp, + int (*compar)(const void *, const void *)) +{ + node_t *q; + node_t **rootp = (node_t **)vrootp; + + if (rootp == NULL) + return NULL; + + while (*rootp != NULL) { /* Knuth's T1: */ + int r; + + if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */ + return *rootp; /* we found it! */ + + rootp = (r < 0) ? + &(*rootp)->llink : /* T3: follow left branch */ + &(*rootp)->rlink; /* T4: follow right branch */ + } + + q = malloc(sizeof(node_t)); /* T5: key not found */ + if (q != 0) { /* make new node */ + *rootp = q; /* link new node to old */ + /* LINTED const castaway ok */ + q->key = __DECONST(void *, vkey); /* initialize new node */ + q->llink = q->rlink = NULL; + } + return q; +} + +/* + * Walk the nodes of a tree + * + * Parameters: + * root: Root of the tree to be walked + */ +static void +trecurse(const node_t *root, void (*action)(const void *, VISIT, int), + int level) +{ + + if (root->llink == NULL && root->rlink == NULL) + (*action)(root, leaf, level); + else { + (*action)(root, preorder, level); + if (root->llink != NULL) + trecurse(root->llink, action, level + 1); + (*action)(root, postorder, level); + if (root->rlink != NULL) + trecurse(root->rlink, action, level + 1); + (*action)(root, endorder, level); + } +} + +/* + * Walk the nodes of a tree + * + * Parameters: + * vroot: Root of the tree to be walked + */ +ROKEN_LIB_FUNCTION void +rk_twalk(const void *vroot, + void (*action)(const void *, VISIT, int)) +{ + if (vroot != NULL && action != NULL) + trecurse(vroot, action, 0); +} + +/* + * delete node with given key + * + * vkey: key to be deleted + * vrootp: address of the root of the tree + * compar: function to carry out node comparisons + */ +ROKEN_LIB_FUNCTION void * +rk_tdelete(const void * __restrict vkey, void ** __restrict vrootp, + int (*compar)(const void *, const void *)) +{ + node_t **rootp = (node_t **)vrootp; + node_t *p, *q, *r; + int cmp; + + if (rootp == NULL || (p = *rootp) == NULL) + return NULL; + + while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) { + p = *rootp; + rootp = (cmp < 0) ? + &(*rootp)->llink : /* follow llink branch */ + &(*rootp)->rlink; /* follow rlink branch */ + if (*rootp == NULL) + return NULL; /* key not found */ + } + r = (*rootp)->rlink; /* D1: */ + if ((q = (*rootp)->llink) == NULL) /* Left NULL? */ + q = r; + else if (r != NULL) { /* Right link is NULL? */ + if (r->llink == NULL) { /* D2: Find successor */ + r->llink = q; + q = r; + } else { /* D3: Find NULL link */ + for (q = r->llink; q->llink != NULL; q = r->llink) + r = q; + r->llink = q->rlink; + q->llink = (*rootp)->llink; + q->rlink = (*rootp)->rlink; + } + } + free(*rootp); /* D4: Free node */ + *rootp = q; /* link parent to new node */ + return p; +} + +/* + * find a node, or return 0 + * + * Parameters: + * vkey: key to be found + * vrootp: address of the tree root + */ +ROKEN_LIB_FUNCTION void * +rk_tfind(const void *vkey, void * const *vrootp, + int (*compar)(const void *, const void *)) +{ + node_t **rootp = (node_t **)vrootp; + + if (rootp == NULL) + return NULL; + + while (*rootp != NULL) { /* T1: */ + int r; + + if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */ + return *rootp; /* key found */ + rootp = (r < 0) ? + &(*rootp)->llink : /* T3: follow left branch */ + &(*rootp)->rlink; /* T4: follow right branch */ + } + return NULL; +} +#endif diff --git a/src/libafscp/afscp_search.h b/src/libafscp/afscp_search.h new file mode 100644 index 0000000000..6b9afdb8a4 --- /dev/null +++ b/src/libafscp/afscp_search.h @@ -0,0 +1,57 @@ +/*- + * Written by J.T. Conklin + * Public domain. + * + * $NetBSD: search.h,v 1.12 1999/02/22 10:34:28 christos Exp $ + */ + +#ifndef _rk_SEARCH_H_ +#define _rk_SEARCH_H_ 1 + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +#ifdef __cplusplus +#define ROKEN_CPP_START extern "C" { +#define ROKEN_CPP_END } +#else +#define ROKEN_CPP_START +#define ROKEN_CPP_END +#endif + +#ifndef _WIN32 +#include +#endif +#include + +typedef enum { + preorder, + postorder, + endorder, + leaf +} VISIT; + +ROKEN_CPP_START + +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL rk_tdelete(const void * __restrict, void ** __restrict, + int (*)(const void *, const void *)); +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL rk_tfind(const void *, void * const *, + int (*)(const void *, const void *)); +ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL rk_tsearch(const void *, void **, int (*)(const void *, const void *)); +ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL rk_twalk(const void *, void (*)(const void *, VISIT, int)); + +ROKEN_CPP_END + +#define tdelete rk_tdelete +#define tfind rk_tfind +#define tsearch rk_tsearch +#define twalk rk_twalk + +#endif /* !_rk_SEARCH_H_ */ diff --git a/src/libafscp/afscp_volume.c b/src/libafscp/afscp_volume.c index 7bfb396d9a..9ce7733ea7 100644 --- a/src/libafscp/afscp_volume.c +++ b/src/libafscp/afscp_volume.c @@ -27,7 +27,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifdef HAVE_SEARCH_H #include +#else +#include "afscp_search.h" +#endif #include #include diff --git a/src/venus/Makefile.in b/src/venus/Makefile.in index 2d0c7354d5..1c69672d7f 100644 --- a/src/venus/Makefile.in +++ b/src/venus/Makefile.in @@ -11,11 +11,28 @@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ +KRB5CFLAGS = @KRB5_CPPFLAGS@ +KRB5LIBS = @KRB5_LIBS@ INCLS=${TOP_INCDIR}/afs/afsint.h \ ${TOP_INCDIR}/afs/cmd.h \ ${TOP_INCDIR}/afs/afsutil.h +AFSIO_INCLS=${TOP_INCDIR}/afs/afsint.h \ + ${TOP_INCDIR}/afs/cmd.h \ + ${TOP_INCDIR}/afs/auth.h \ + ${TOP_INCDIR}/afs/vlserver.h \ + ${TOP_INCDIR}/afs/ihandle.h \ + ${TOP_INCDIR}/afs/com_err.h \ + ${TOP_INCDIR}/afs/afscp.h \ + ${TOP_INCDIR}/afs/afsutil.h + +AFSIO_LIBS=${TOP_LIBDIR}/libafscp.a \ + ${TOP_LIBDIR}/libafsauthent.a \ + ${TOP_LIBDIR}/libafsrpc.a \ + ${TOP_LIBDIR}/libcmd.a \ + $(TOP_LIBDIR)/libafsutil.a + FSLIBS=${TOP_LIBDIR}/libsys.a \ ${TOP_LIBDIR}/libvldb.a \ ${TOP_LIBDIR}/libubik.a \ @@ -45,7 +62,7 @@ CMLIBS=${TOP_LIBDIR}/libsys.a \ LIBS = ${FSLIBS} -all: fs up fstrace cmdebug livesys kdump-build cacheout +all: fs up fstrace cmdebug livesys kdump-build cacheout afsio # # Build targets @@ -55,6 +72,9 @@ cacheout: cacheout.o cacheout.o: cacheout.c +PTH_CFLAGS=$(COMMON_CFLAGS) $(MT_CFLAGS) +PTH_LDFLAGS=$(COMMON_LDFLAGS) $(MT_LDFLAGS) +PTH_CCRULE=$(MT_CC) $(PTH_CFLAGS) -o $@ -c up.o: up.c AFS_component_version_number.c @@ -66,10 +86,22 @@ fs.o: fs.c ${INCLS} AFS_component_version_number.c fs: fs.o $(LIBS) ${CC} ${CFLAGS} -o fs fs.o ${TOP_LIBDIR}/libprot.a $(LIBS) ${XLIBS} -afsio.o: afsio.c ${INCLS} AFS_component_version_number.c +afsio.o: afsio.c ${AFSIO_INCLS} AFS_component_version_number.c + ${PTH_CCRULE} afsio.c +vldbint.cs.o: ${srcdir}/../vlserver/vldbint.cs.c + ${PTH_CCRULE} ${srcdir}/../vlserver/vldbint.cs.c +vldbint.xdr.o: ${srcdir}/../vlserver/vldbint.xdr.c + ${PTH_CCRULE} ${srcdir}/../vlserver/vldbint.xdr.c +afscbint.ss.o: ${srcdir}/../fsint/afscbint.ss.c + ${PTH_CCRULE} ${srcdir}/../fsint/afscbint.ss.c -afsio: afsio.o $(LIBS) - ${CC} ${CFLAGS} -o afsio afsio.o ${TOP_LIBDIR}/libprot.a ${TOP_LIBDIR}/libafsint.a $(LIBS) ${XLIBS} +afsio: afsio.o vldbint.cs.o afscbint.ss.o vldbint.xdr.o ${AFSIO_LIBS} + +if test "@BUILD_KRB5@" = "yes"; then \ + $(MT_CC) @KRB5_CPPFLAGS@ $(PTH_LDFLAGS) $(PTH_CFLAGS) -o afsio afsio.o vldbint.cs.o afscbint.ss.o vldbint.xdr.o ${AFSIO_LIBS} \ + ${MT_LIBS} ${XLIBS} ${KRB5LIBS} ; \ + else \ + echo "Skipping afsio (KRB5 build disabled)" ; \ + fi livesys.o: livesys.c ${INCLS} AFS_component_version_number.c @@ -267,7 +299,7 @@ kdump-alpha_linux-@LINUX_VERSION@: kdump-alpha_linux-@LINUX_VERSION@.o # # Install targets # -install: kdump-build fs livesys up fstrace cmdebug +install: kdump-build fs livesys up fstrace cmdebug afsio ${INSTALL} -d ${DESTDIR}${bindir} ${INSTALL} -d ${DESTDIR}${afssrvbindir} ${INSTALL} -d ${DESTDIR}${sbindir} @@ -277,6 +309,9 @@ install: kdump-build fs livesys up fstrace cmdebug ${INSTALL_PROGRAM} up ${DESTDIR}${bindir}/up ${INSTALL_PROGRAM} fstrace ${DESTDIR}${sbindir}/fstrace ${INSTALL_PROGRAM} cmdebug ${DESTDIR}${bindir}/cmdebug + if test "@BUILD_KRB5@" = "yes"; then \ + ${INSTALL_PROGRAM} afsio ${DESTDIR}${bindir}/afsio ; \ + fi -set -x; \ case ${SYS_NAME} in \ sgi_6? ) \ @@ -307,7 +342,7 @@ install: kdump-build fs livesys up fstrace cmdebug ${INSTALL_PROGRAM} kdump64 ${DESTDIR}${sbindir}/kdump; \ fi -dest: kdump-build fs livesys up fstrace cmdebug +dest: kdump-build fs livesys up fstrace cmdebug afsio ${INSTALL} -d ${DEST}/bin ${INSTALL} -d ${DEST}/etc ${INSTALL} -d ${DEST}/root.server/usr/afs/bin @@ -317,6 +352,9 @@ dest: kdump-build fs livesys up fstrace cmdebug ${INSTALL_PROGRAM} up ${DEST}/bin/up ${INSTALL_PROGRAM} fstrace ${DEST}/etc/fstrace ${INSTALL_PROGRAM} cmdebug ${DEST}/bin/cmdebug + if test "@BUILD_KRB5@" = "yes"; then \ + ${INSTALL_PROGRAM} afsio ${DEST}/bin/afsio ; \ + fi -set -x; \ case ${SYS_NAME} in \ sgi_6? ) \ @@ -355,7 +393,7 @@ dest: kdump-build fs livesys up fstrace cmdebug # clean: - $(RM) -f *.o *.a up fs kdump-* kdump kdump64 core cmdebug AFS_component_version_number.c fstrace gcpags livesys dedebug + $(RM) -f *.o *.a up fs kdump-* kdump kdump64 core cmdebug AFS_component_version_number.c fstrace gcpags livesys dedebug afsio test: cd test; $(MAKE) diff --git a/src/venus/afsio.c b/src/venus/afsio.c index 35abfc5677..f7906391f1 100644 --- a/src/venus/afsio.c +++ b/src/venus/afsio.c @@ -24,6 +24,11 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * Revised in 2010 by Chaz Chandler to enhance clientless operations. + * Now utilizes libafscp by Chaskiel Grundman. + * Work funded in part by Sine Nomine Associates (http://www.sinenomine.net/) + */ #include #include @@ -34,6 +39,7 @@ #include #include #include + #ifdef AFS_NT40_ENV #include #include @@ -70,21 +76,10 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include #include +#include #ifdef HAVE_DIRENT_H #include #endif @@ -115,36 +110,38 @@ 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); +static int readFile(struct cmd_syndesc *, void *); +static int writeFile(struct cmd_syndesc *, void *); +static void printDatarate(void); +static void summarizeDatarate(struct timeval *, const char *); +static int CmdProlog(struct cmd_syndesc *, char **, char **, + char **, char **); +static int ScanFid(char *, struct AFSFid *); +static afs_int32 GetVenusFidByFid(char *, char *, int, struct afscp_venusfid **); +static afs_int32 GetVenusFidByPath(char *, char *, struct afscp_venusfid **); +static int BreakUpPath(char *, char *, char *); -char pnp[255]; -int rxInitDone = 0; +static char pnp[AFSPATHMAX]; /* filename of this program when called */ static int verbose = 0; /* Set if -verbose option given */ -static int CBServiceNeeded = 0; +static int cellGiven = 0; /* Set if -cell option given */ +static int force = 0; /* Set if -force option given */ +static int useFid = 0; /* Set if fidwrite/fidread/fidappend invoked */ +static int append = 0; /* Set if append/fidappend invoked */ static struct timeval starttime, opentime, readtime, writetime; -afs_uint64 xfered=0, oldxfered=0; +static afs_uint64 xfered = 0; static struct timeval now; -struct timezone Timezone; -static float seconds, datarate, oldseconds; -extern int rxInitDone; #ifdef AFS_NT40_ENV -static afs_int32 rx_mtu = -1; +static int Timezone; /* Roken gettimeofday ignores the timezone */ +#else +static struct timezone Timezone; #endif -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; +#define BUFFLEN 65536 +#define WRITEBUFLEN (BUFFLEN * 1024) +#define MEGABYTE_F 1048576.0f + +static MD5_CTX md5; +static int md5sum = 0; /* Set if -md5 option given */ struct wbuf { struct wbuf *next; @@ -154,812 +151,463 @@ struct wbuf { char buf[BUFFLEN]; }; -struct connectionLookup { - afs_uint32 host; - u_short port; - struct rx_connection *conn; -}; +/*! + * returns difference in seconds between two times + * + * \param[in] from start time + * \param[in] to end time + * + * \post returns "to" minus "from" in seconds + * + */ +static_inline float +time_elapsed(struct timeval *from, struct timeval *to) +{ + return (float)(to->tv_sec + (to->tv_usec * 0.000001) - from->tv_sec - + (from->tv_usec * 0.000001)); +} /* time_elapsed */ -struct cellLookup { - struct cellLookup *next; - struct afsconf_cell info; - struct rx_securityClass *sc; - 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 +/*! + * prints current average data transfer rate at no less than 30-second intervals + */ +static void printDatarate(void) { - seconds = (float)(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 = %.03f MB/sec.\n", - xfered >> 20, datarate); + static float oldseconds = 0.0; + static afs_uint64 oldxfered = 0; + float seconds; + + gettimeofday(&now, &Timezone); + seconds = time_elapsed(&opentime, &now); + if ((seconds - oldseconds) > 30) { + fprintf(stderr, "%llu MB transferred, present data rate = %.3f MB/sec.\n", xfered >> 20, /* total bytes transferred, in MB */ + (xfered - oldxfered) / (seconds - oldseconds) / MEGABYTE_F); oldxfered = xfered; oldseconds = seconds; } -} +} /* printDatarate */ -void -SetCellFname(char *name) +/*! + * prints overall average data transfer rate and elapsed time + * + * \param[in] tvp current time (to compare with file open time) + * \param[in] xfer_type string identify transfer type ("read" or "write") + */ +static void +summarizeDatarate(struct timeval *tvp, const char *xfer_type) { - struct afsconf_dir *tdir; + float seconds = time_elapsed(&opentime, tvp); - strcpy((char *) &cellFname,"/afs/"); - if (name) - strcat((char *) &cellFname, name); - else { - tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH); - afsconf_GetLocalCell(tdir, &cellFname[5], MAXCELLCHARS); + fprintf(stderr, "Transfer of %llu bytes took %.3f sec.\n", + xfered, seconds); + fprintf(stderr, "Total data rate = %.03f MB/sec. for %s\n", + xfered / seconds / MEGABYTE_F, xfer_type); +} /* summarizeDatarate */ + +/*! + * prints final MD5 sum of all file data transferred + * + * \param[in] fname file name or FID + */ +static void +summarizeMD5(char *fname) +{ + 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); +} /* summarizeMD5 */ -afs_int32 -main (int argc, char **argv) +/*! + * parses all command-line arguments + * + * \param[in] as arguments list + * \param[out] cellp cell name + * \param[out] realmp realm name + * \param[out] fnp filename (either fid or path) + * \param[out] slp "synthesized" (made up) data given + * + * \post returns 0 on success or -1 on error + * + */ +static int +CmdProlog(struct cmd_syndesc *as, char **cellp, char **realmp, + char **fnp, char **slp) { - afs_int32 code; - struct cmd_syndesc *ts; + int i; + struct cmd_parmdesc *pdp; - strcpy(pnp, argv[0]); + if (as == NULL) { + afs_com_err(pnp, EINVAL, "(syndesc is null)"); + return -1; + } + + /* determine which command was requested */ + if (strncmp(as->name, "fid", 3) == 0) /* fidread/fidwrite/fidappend */ + useFid = 1; + if ( (strcmp(as->name, "append") == 0) || + (strcmp(as->name, "fidappend") == 0) ) + append = 1; /* global */ + + /* attempts to ensure loop is bounded: */ + for (pdp = as->parms, i = 0; pdp && (i < as->nParms); i++, pdp++) { + if (pdp->items != NULL) { + if (strcmp(pdp->name, "-verbose") == 0) + verbose = 1; + else if (strcmp(pdp->name, "-md5") == 0) + md5sum = 1; /* global */ + else if (strcmp(pdp->name, "-cell") == 0) { + cellGiven = 1; /* global */ + *cellp = pdp->items->data; + } else if ( (strcmp(pdp->name, "-file") == 0) || + (strcmp(pdp->name, "-fid") == 0) || + (strcmp(pdp->name, "-vnode") == 0) ) + *fnp = pdp->items->data; + else if (strcmp(pdp->name, "-force") == 0) + force = 1; /* global */ + else if (strcmp(pdp->name, "-synthesize") == 0) + *slp = pdp->items->data; + else if (strcmp(pdp->name, "-realm") == 0) + *realmp = pdp->items->data; + } + } + return 0; +} /* CmdProlog */ + +int +main(int argc, char **argv) +{ + afs_int32 code = 0; + struct cmd_syndesc *ts; + char baseName[AFSNAMEMAX]; + + /* try to get only the base name of this executable for use in logs */ + if (BreakUpPath(argv[0], NULL, baseName) > 0) + strlcpy(pnp, baseName, AFSNAMEMAX); + else + strlcpy(pnp, argv[0], AFSPATHMAX); #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, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum"); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); 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, "-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, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum"); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); 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, "-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, "-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"); + cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, + "overwrite existing file"); + cmd_AddParm(ts, "-synthesize", CMD_SINGLE, CMD_OPTIONAL, + "create data pattern of specified length instead reading from stdin"); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); 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, "-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, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum"); + cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, + "overwrite existing file"); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); 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, "-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, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); 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, "-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, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); + + if (afscp_Init(NULL) != 0) + exit(1); code = cmd_Dispatch(argc, argv); - exit (0); -} -AFS_UNUSED -afs_int32 -HandleLocalAuth(struct rx_securityClass **sc, afs_int32 *scIndex) -{ - static struct afsconf_dir *tdir = NULL; - afs_int32 code; + afscp_Finalize(); + exit(0); +} /* main */ - *sc = NULL; - *scIndex = RX_SECIDX_NULL; - - tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH); - if (!tdir) { - fprintf(stderr,"Could not open configuration directory: %s.\n", - AFSDIR_SERVER_ETC_DIRPATH); - return -1; - } - code = afsconf_ClientAuth(tdir, sc, scIndex); - if (code) { - fprintf(stderr,"afsconf_ClientAuth returned %d\n", code); - return -1; - } - 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) -{ - if ( !afs_uuid_equal(&uuid, a_uuid) ) - return(1); - else - return(0); -} - - -afs_int32 -SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr) -{ - return SRXAFSCB_TellMeAboutYourself(a_call, addr, NULL); -} - -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) -{ -#ifdef AFS_NT40_ENV - int code; - int cm_noIPAddr; /* number of client network interfaces */ - int cm_IPAddr[CM_MAXINTERFACE_ADDR]; /* client's IP address in host order */ - int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/ - int cm_NetMtu[CM_MAXINTERFACE_ADDR]; /* client's MTU sizes */ - int cm_NetFlags[CM_MAXINTERFACE_ADDR]; /* network flags */ - int i; - - cm_noIPAddr = CM_MAXINTERFACE_ADDR; - code = syscfg_GetIFInfo(&cm_noIPAddr, - cm_IPAddr, cm_SubnetMask, - cm_NetMtu, cm_NetFlags); - if (code > 0) { - /* return all network interface addresses */ - addr->numberOfInterfaces = cm_noIPAddr; - for ( i=0; i < cm_noIPAddr; i++ ) { - addr->addr_in[i] = cm_IPAddr[i]; - addr->subnetmask[i] = cm_SubnetMask[i]; - addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ? - cm_NetMtu[i] : rx_mtu; - } - } else { - addr->numberOfInterfaces = 0; - } -#else - addr->numberOfInterfaces = 0; -#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 -#endif - - addr->uuid = uuid; - - if (capabilities) { - afs_uint32 *dataBuffP; - afs_int32 dataBytes; - - dataBytes = 1 * sizeof(afs_uint32); - dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes); - dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS; - capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32); - capabilities->Capabilities_val = dataBuffP; - } - return 0; -} - -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; - 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 */ -#if defined AFS_NT40_ENV - srand(_getpid()); - InitialCBPort = RESTOOL_CBPORT + rand() % 1000; -#else /* AFS_NT40_ENV */ - srand(getpid()); - InitialCBPort = RESTOOL_CBPORT + rand() % 1000; -#endif /* AFS_NT40_ENV */ -#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; jVolume = (afs_uint32) f1; + fid->Vnode = (afs_uint32) f2; + fid->Unique = (afs_uint32) f3; + } + if (i != 3) { + fid->Volume = 0; + fid->Vnode = 0; + fid->Unique = 0; + code = EINVAL; + afs_com_err(pnp, code, "(invalid FID triple: %s)", fidString); + } + + return code; +} /* ScanFid */ + +/*! + * look up cell info and verify FID info from user input + * + * \param[in] fidString string containing FID info + * \param[in] cellName cell name string + * \param[in] onlyRW bool: 1 = RW vol only, 0 = any vol type + * \param[out] avfpp pointer to venusfid info + * + * \post *avfpp will contain the VenusFid info found for the FID + * given by the used in the string fidString and zero is + * returned. If not found, an appropriate afs error code + * is returned and *avfpp will be NULL. + * + * \note Any non-NULL avfpp returned should later be freed with + * afscp_FreeFid() when no longer needed. + */ +static afs_int32 +GetVenusFidByFid(char *fidString, char *cellName, int onlyRW, + struct afscp_venusfid **avfpp) +{ + afs_int32 code = 0; + struct stat sbuf; + struct afscp_volume *avolp; + + if (*avfpp == NULL) { + *avfpp = malloc(sizeof(struct afscp_venusfid)); + if ( *avfpp == NULL ) { + code = ENOMEM; + return code; } } - 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); + memset(*avfpp, 0, sizeof(struct afscp_venusfid)); + + if (cellName == NULL) { + (*avfpp)->cell = afscp_DefaultCell(); } 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); - } + (*avfpp)->cell = afscp_CellByName(cellName, NULL); + } + if ((*avfpp)->cell == NULL) { + if (afscp_errno == 0) + code = EINVAL; + else + code = afscp_errno; + return code; + } + + code = ScanFid(fidString, &((*avfpp)->fid)); + if (code != 0) { + code = EINVAL; + return code; + } + + avolp = afscp_VolumeById((*avfpp)->cell, (*avfpp)->fid.Volume); + if (avolp == NULL) { + if (afscp_errno == 0) + code = ENOENT; + else + code = afscp_errno; + afs_com_err(pnp, code, "(finding volume %lu)", + afs_printable_uint32_lu((*avfpp)->fid.Volume)); + return code; + } + + if ( onlyRW && (avolp->voltype != RWVOL) ) { + avolp = afscp_VolumeByName((*avfpp)->cell, avolp->name, RWVOL); + if (avolp == NULL) { + if (afscp_errno == 0) + code = ENOENT; else - afs_com_err(pnp, code, (char *) 0); - } else { - Tmpafs_int32 = (afs_int32 *)buf; - for (j=0;jfid.Volume)); + return code; } - 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 { - Tmpafs_int32 = (afs_int32 *)buf; - Fid->Volume = Tmpafs_int32[1]; - Fid->Vnode = Tmpafs_int32[2]; - Fid->Unique = Tmpafs_int32[3]; + (*avfpp)->fid.Volume = avolp->id; /* is this safe? */ + } + + code = afscp_Stat((*avfpp), &sbuf); + if (code != 0) { + afs_com_err(pnp, code, "(stat failed with code %d)", code); + return code; + } + return 0; +} /* GetVenusFidByFid */ + +/*! + * Split a full path up into dirName and baseName components + * + * \param[in] fullPath can be absolute, relative, or local + * \param[out] dirName pointer to allocated char buffer or NULL + * \param[out] baseName pointer to allocated char buffer or NULL + * + * \post To the fulleset extent possible, the rightmost full path + * component will be copied into baseName and all other + * components into dirName (minus the trailing path separator). + * If either dirName or baseName are NULL, only the non-NULL + * pointer will be filled in (but both can't be null or it would + * be pointless) -- so the caller can retrieve, say, only baseName + * if desired. The return code is the number of strings copied: + * 0 if neither dirName nor baseName could be filled in + * 1 if either dirName or baseName were filled in + * 2 if both dirName and baseName were filled in + */ +static int +BreakUpPath(char *fullPath, char *dirName, char *baseName) +{ + char *lastSlash; + size_t dirNameLen = 0; + int code = 0, useDirName = 1, useBaseName = 1; + + if (fullPath == NULL) { + return code; + } + + if (dirName == NULL) + useDirName = 0; + if (baseName == NULL) + useBaseName = 0; + if (!useBaseName && !useDirName) { + /* would be pointless to continue -- must be error in call */ + return code; + } +#ifdef AFS_NT40_ENV + lastSlash = strrchr(fullPath, '\\'); +#else + lastSlash = strrchr(fullPath, '/'); +#endif + if (lastSlash != NULL) { + /* then lastSlash points to the last path separator in fullPath */ + if (useDirName) { + dirNameLen = strlen(fullPath) - strlen(lastSlash); + strlcpy(dirName, fullPath, dirNameLen + 1); + code++; + } + if (useBaseName) { + lastSlash++; + strlcpy(baseName, lastSlash, strlen(lastSlash) + 1); + code++; + } + } else { + /* there are no path separators in fullPath -- it's just a baseName */ + if (useBaseName) { + strlcpy(baseName, fullPath, strlen(fullPath) + 1); + code++; } } return code; -} +} /* BreakUpPath */ -int -DestroyConnections(void) +/*! + * Get the VenusFid info available for the file at AFS path 'fullPath'. + * Works without pioctls/afsd by using libafscp. Analogous to + * get_file_cell() in the previous iteration of afsio. + * + * \param[in] fullPath the file name + * \param[in] cellName the cell name to look up + * \param[out] avfpp pointer to Venus FID info to be filled in + * + * \post If the path resolves successfully (using afscp_ResolvePath), + * then vfpp will contain the Venus FID info (cell info plus + * AFSFid) of the last path segment in fullPath. + */ +static afs_int32 +GetVenusFidByPath(char *fullPath, char *cellName, + struct afscp_venusfid **avfpp) { - int i; + afs_int32 code = 0; - 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 (fullPath == NULL) { + return -1; } - if (!rxInitDone) - rx_Finalize(); - return 0; -} + if (cellName != NULL) { + code = (afs_int32) afscp_SetDefaultCell(cellName); + if (code != 0) { + return code; + } + } -int -LogErrors (int level, const char *fmt, ...) -{ - va_list ap; + *avfpp = afscp_ResolvePath(fullPath); + if (*avfpp == NULL) { + if (afscp_errno == 0) + code = ENOENT; + else + code = afscp_errno; + } - va_start(ap, fmt); - return vfprintf(stderr, fmt, ap); -} + return code; +} /* GetVenusFidByPath */ -int +static int readFile(struct cmd_syndesc *as, void *unused) { - char *fname; - char *cell = 0; - afs_int32 code; - afs_int32 hosts[AFS_MAXHOSTS]; - AFSFid Fid; - int j; - struct rx_connection *RXConn; - struct cellLookup *cl; - struct rx_call *tcall; - struct AFSVolSync tsync; + char *fname = NULL; + char *cell = NULL; + char *realm = NULL; + afs_int32 code = 0; struct AFSFetchStatus OutStatus; - struct AFSCallBack CallBack; + struct afscp_venusfid *avfp = NULL; afs_int64 Pos; afs_int32 len; - afs_int64 length, Len; - u_char vnode = 0; - u_char first = 1; + afs_int64 length = 0, Len; int bytes; int worstCode = 0; char *buf = 0; + char ipv4_addr[16]; int bufflen = BUFFLEN; #ifdef AFS_NT40_ENV @@ -967,298 +615,265 @@ readFile(struct cmd_syndesc *as, void *unused) _setmode(1, _O_BINARY); #endif - if (as->name[0] == 'f') - vnode = 1; - if (as->parms[2].items) - verbose = 1; - if (as->parms[3].items) { - md5sum = 1; + gettimeofday(&starttime, &Timezone); + + CmdProlog(as, &cell, &realm, &fname, NULL); + afscp_AnonymousAuth(1); + + if (md5sum) MD5_Init(&md5); - } - CBServiceNeeded = 1; - InitializeCBService(); + if (realm != NULL) + code = afscp_SetDefaultRealm(realm); - 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); + if (cell != NULL) + code = afscp_SetDefaultCell(cell); + + if (useFid) + code = GetVenusFidByFid(fname, cell, 0, &avfp); else - code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, 0); - if (code) { - fprintf(stderr,"File not found %s\n", fname); - return code; + code = GetVenusFidByPath(fname, cell, &avfp); + if (code != 0) { + afs_com_err(pnp, code, "(file not found: %s)", 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;jparms[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); - if (!RXConn) { - fprintf(stderr,"rx_NewConnection failed to server 0x%X\n", - useHost); - continue; - } - 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; - } - gettimeofday(&opentime, &Timezone); - if (verbose) { - seconds = (float)(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_int32 tmpPos, tmpLen; - tmpPos = (afs_int32)Pos; tmpLen = (afs_int32)Len; - code = StartAFS_FetchData (tcall, &Fid, tmpPos, tmpLen); - 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 = (afs_int32) 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 = (afs_int32) 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; + if (avfp->fid.Vnode & 1) { + code = ENOENT; + afs_com_err(pnp, code, "(%s is a directory, not a file)", fname); + afscp_FreeFid(avfp); + return code; } + + code = afscp_GetStatus(avfp, &OutStatus); + if (code != 0) { + afs_inet_ntoa_r(avfp->cell->fsservers[0]->addrs[0], ipv4_addr); + afs_com_err(pnp, code, "(failed to get status of file %s from" + "server %s, code = %d)", fname, ipv4_addr, code); + afscp_FreeFid(avfp); + return code; + } + + gettimeofday(&opentime, &Timezone); + if (verbose) + fprintf(stderr, "Startup to find the file took %.3f sec.\n", + time_elapsed(&starttime, &opentime)); + Len = OutStatus.Length_hi; + Len <<= 32; + Len += OutStatus.Length; + ZeroInt64(Pos); + buf = (char *) malloc(bufflen * sizeof(char)); + if (buf == NULL) { + code = ENOMEM; + afs_com_err(pnp, code, "(cannot allocate buffer)"); + afscp_FreeFid(avfp); + return code; + } + memset(buf, 0, bufflen * sizeof(char)); + length = Len; + while (!code && NonZeroInt64(length)) { + if (length > bufflen) + len = bufflen; + else + len = (afs_int32) length; + bytes = afscp_PRead(avfp, buf, len, Pos); + if (bytes != len) + code = -3; /* what error name should we use here? */ + if (md5sum) + MD5_Update(&md5, buf, len); + if (code == 0) { + len = write(1, buf, len); /* to stdout */ + if (len == 0) + code = errno; + } + length -= len; + xfered += len; + if (verbose) + printDatarate(); + Pos += len; + worstCode = code; + } + afscp_FreeFid(avfp); + 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); -#ifdef AFS_NT40_ENV - p = strrchr(fname,'\\'); -#else - p = strrchr(fname,'/'); -#endif - if (p) - p++; - else - p = fname; + if (md5sum) + summarizeMD5(fname); + if (verbose) + summarizeDatarate(&readtime, "read"); + if (buf != NULL) + free(buf); - fprintf(stderr, "%08x%08x%08x%08x %s\n", - htonl(md5int[0]), htonl(md5int[1]), - htonl(md5int[2]), htonl(md5int[3]), p); - } - if(verbose) { - seconds = (float)(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 = %.03f MB/sec. for read\n", - datarate); - } - } - DestroyConnections(); return worstCode; -} +} /* readFile */ -int +static int writeFile(struct cmd_syndesc *as, void *unused) { char *fname = NULL; - char *cell = 0; - afs_int32 code, localcode = 0; - afs_int32 hosts[AFS_MAXHOSTS]; - afs_uint32 useHost; - AFSFid Fid; - struct rx_connection *RXConn; - struct cellLookup *cl; - struct rx_call *tcall; - struct AFSVolSync tsync; + char *cell = NULL; + char *sSynthLen = NULL; + char *realm = NULL; + afs_int32 code = 0; + afs_int32 byteswritten; struct AFSFetchStatus OutStatus; struct AFSStoreStatus InStatus; - struct AFSCallBack CallBack; + struct afscp_venusfid *dirvfp = NULL, *newvfp = NULL; afs_int64 Pos; afs_int64 length, Len, synthlength = 0, offset = 0; - u_char vnode = 0; afs_int64 bytes; int worstCode = 0; - int append = 0; int synthesize = 0; - afs_int32 byteswritten; + int overWrite = 0; struct wbuf *bufchain = 0; struct wbuf *previous, *tbuf; + char dirName[AFSPATHMAX]; + char baseName[AFSNAMEMAX]; + char ipv4_addr[16]; #ifdef AFS_NT40_ENV /* stdin on Windows defaults to _O_TEXT mode */ _setmode(0, _O_BINARY); #endif - 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); + CmdProlog(as, &cell, &realm, &fname, &sSynthLen); + afscp_AnonymousAuth(1); + + if (realm != NULL) + code = afscp_SetDefaultRealm(realm); + + if (cell != NULL) + code = afscp_SetDefaultCell(cell); + + if (sSynthLen) { + code = util_GetInt64(sSynthLen, &synthlength); + if (code != 0) { + afs_com_err(pnp, code, "(invalid value for synthesize length %s)", + sSynthLen); 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) + if (useFid) { + code = GetVenusFidByFid(fname, cell, 1, &newvfp); + if (code != 0) { + afs_com_err(pnp, code, "(GetVenusFidByFid returned code %d)", code); return code; - } else - code = get_file_cell(fname, &cell, hosts, &Fid, &OutStatus, append ? 0 : 1); - if (code) { - fprintf(stderr,"File or directory not found: %s\n", - fname); - return code; + } + } else { + code = GetVenusFidByPath(fname, cell, &newvfp); + if (code == 0) { /* file was found */ + if (force) + overWrite = 1; + else if (!append) { + /* + * file cannot already exist if specified by path and not + * appending to it unless user forces overwrite + */ + code = EEXIST; + afscp_FreeFid(newvfp); + afs_com_err(pnp, code, "(use -force to overwrite)"); + return code; + } + } else { /* file not found */ + if (append) { + code = ENOENT; + afs_com_err(pnp, code, "(cannot append to non-existent file)"); + return code; + } + } + if (!append && !overWrite) { /* must create a new file in this case */ + if ( BreakUpPath(fname, dirName, baseName) != 2 ) { + code = EINVAL; + afs_com_err(pnp, code, "(must provide full AFS path)"); + afscp_FreeFid(newvfp); + return code; + } + + code = GetVenusFidByPath(dirName, cell, &dirvfp); + afscp_FreeFid(newvfp); /* release now-unneeded fid */ + newvfp = NULL; + if (code != 0) { + afs_com_err(pnp, code, "(is dir %s in AFS?)", dirName); + return code; + } + } } - if (Fid.Vnode & 1) { - fprintf(stderr,"%s is a directory, not a file\n", fname); - return ENOENT; + + if ( (newvfp != NULL) && (newvfp->fid.Vnode & 1) ) { + code = EISDIR; + afs_com_err(pnp, code, "(%s is a directory, not a file)", fname); + afscp_FreeFid(newvfp); + afscp_FreeFid(dirvfp); + return code; } - 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); - if (!RXConn) { - fprintf(stderr,"rx_NewConnection failed to server 0x%X\n", - hosts[0]); - return -1; - } - 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); - return -1; - } - if (!append && (OutStatus.Length || OutStatus.Length_hi)) { - fprintf(stderr,"AFS file %s not empty, request aborted.\n", fname); - DestroyConnections(); - return -5; - } - InStatus.Mask = AFS_SETMODE + AFS_FSYNC; + gettimeofday(&starttime, &Timezone); + InStatus.UnixModeBits = 0644; + if (newvfp == NULL) { + code = afscp_CreateFile(dirvfp, baseName, &InStatus, &newvfp); + if (code != 0) { + afs_com_err(pnp, code, + "(could not create file %s in directory %lu.%lu.%lu)", + baseName, afs_printable_uint32_lu(dirvfp->fid.Volume), + afs_printable_uint32_lu(dirvfp->fid.Vnode), + afs_printable_uint32_lu(dirvfp->fid.Unique)); + return code; + } + } + code = afscp_GetStatus(newvfp, &OutStatus); + if (code != 0) { + afs_inet_ntoa_r(newvfp->cell->fsservers[0]->addrs[0], ipv4_addr); + afs_com_err(pnp, code, "(failed to get status of file %s from" + "server %s, code = %d)", fname, ipv4_addr, code); + afscp_FreeFid(newvfp); + afscp_FreeFid(dirvfp); + return code; + } + + if ( !append && !force && + (OutStatus.Length != 0 || OutStatus.Length_hi !=0 ) ) { + /* + * file exists, is of non-zero length, and we're not appending + * to it: user must force overwrite + * (covers fidwrite edge case) + */ + code = EEXIST; + afscp_FreeFid(newvfp); + afscp_FreeFid(dirvfp); + afs_com_err(pnp, code, "(use -force to overwrite)"); + return code; + } + + InStatus.Mask = AFS_SETMODE + AFS_FSYNC; if (append) { Pos = OutStatus.Length_hi; Pos = (Pos << 32) | OutStatus.Length; } else - Pos = 0; + Pos = 0; previous = (struct wbuf *)&bufchain; if (md5sum) MD5_Init(&md5); + /* + * currently, these two while loops (1) read the whole source file in + * before (2) writing any of it out, meaning that afsio can't deal with + * files larger than the maximum amount of memory designated for + * reading a file in (WRITEBUFLEN). + * Consider going to a single loop, like in readFile(), though will + * have implications on timing statistics (such as the "Startup to + * find the file" time, below). + */ Len = 0; - while (Len synthlength) l = synthlength; for (ll = 0; ll < l; ll += 4096) { - sprintf(&tbuf->buf[ll],"Offset (0x%x, 0x%x)\n", + sprintf(&tbuf->buf[ll], "Offset (0x%x, 0x%x)\n", (unsigned int)((offset + ll) >> 32), (unsigned int)((offset + ll) & 0xffffffff)); } offset += l; synthlength -= l; - tbuf->used = (afs_int32)l; + tbuf->used = (afs_int32) l; } else - tbuf->used = read(0, &tbuf->buf, tbuf->buflen); - if (!tbuf->used) { + tbuf->used = read(0, &tbuf->buf, tbuf->buflen); /* from stdin */ + if (tbuf->used == 0) { free(tbuf); break; } @@ -1289,230 +904,78 @@ writeFile(struct cmd_syndesc *as, void *unused) Len += tbuf->used; } gettimeofday(&opentime, &Timezone); - if (verbose) { - seconds = (float) (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); - } + if (verbose) + fprintf(stderr, "Startup to find the file took %.3f sec.\n", + time_elapsed(&starttime, &opentime)); 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 = (afs_int32) Pos; - tmpLen = (afs_int32) 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; + Len = bytes; + length = Len; tbuf = bufchain; if (Len) { - for (tbuf= bufchain; tbuf; tbuf=tbuf->next) { - if (!tbuf->used) + for (tbuf = bufchain; tbuf; tbuf = tbuf->next) { + if (tbuf->used == 0) break; - byteswritten = rx_Write(tcall, tbuf->buf, tbuf->used); - if (byteswritten != tbuf->used) { + byteswritten = afscp_PWrite(newvfp, tbuf->buf, + tbuf->used, Pos + xfered); + 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; + code = -4; break; - } + } xfered += tbuf->used; - gettimeofday(&now, &Timezone); - if (verbose) + 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; + length -= tbuf->used; + } } Pos += Len; bytes = 0; if (!code) { - for (tbuf = bufchain; tbuf; tbuf=tbuf->next) { - tbuf->offset = 0; + for (tbuf = bufchain; tbuf; tbuf = tbuf->next) { + tbuf->offset = 0; if (synthesize) { - afs_int64 ll, l = tbuf->buflen; - if (l > synthlength) + afs_int64 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", + for (ll = 0; ll < l; ll += 4096) { + sprintf(&tbuf->buf[ll], "Offset (0x%x, 0x%x)\n", (unsigned int)((offset + ll) >> 32), (unsigned int)((offset + ll) & 0xffffffff)); - } - offset += l; - synthlength -= l; - tbuf->used = (afs_int32) l; + } + offset += l; + synthlength -= l; + tbuf->used = (afs_int32) l; } else - tbuf->used = read(0, &tbuf->buf, tbuf->buflen); - if (!tbuf->used) - break; + tbuf->used = read(0, &tbuf->buf, tbuf->buflen); /* from stdin */ + if (!tbuf->used) + break; if (md5sum) - MD5_Update(&md5, &tbuf->buf, tbuf->used); - Len += tbuf->used; + MD5_Update(&md5, &tbuf->buf, tbuf->used); + Len += tbuf->used; bytes += tbuf->used; - } - } + } + } } + afscp_FreeFid(newvfp); + afscp_FreeFid(dirvfp); + gettimeofday(&writetime, &Timezone); - if (worstCode) { - fprintf(stderr,"%s failed with code %d\n", as->name, worstCode); - } else if(verbose) { - seconds = (float) (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 = %.03f MB/sec. for write\n", - datarate); + if (code) { + afs_com_err(pnp, code, "(%s failed with code %d)", as->name, + code); + } else if (verbose) { + summarizeDatarate(&writetime, "write"); } while (bufchain) { tbuf = bufchain; bufchain = tbuf->next; free(tbuf); } - DestroyConnections(); - if (md5sum) { - afs_uint32 md5int[4]; - char *p; - MD5_Final((char *) &md5int[0], &md5); -#ifdef AFS_NT40_ENV - p = strrchr(fname,'\\'); -#else - p = strrchr(fname,'/'); -#endif - if (p) - p++; - else - p = fname; - fprintf(stderr, "%08x%08x%08x%08x %s\n", - htonl(md5int[0]), htonl(md5int[1]), - htonl(md5int[2]), htonl(md5int[3]), p); - } + if (md5sum) + summarizeMD5(fname); + return worstCode; -} - -struct cellLookup * -FindCell(char *cellName) -{ - char name[MAXCELLCHARS]; - char *np; - struct cellLookup *p, *p2; - static struct afsconf_dir *tdir; - time_t expires; - 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 - code = afsconf_ClientAuthToken(&p->info, 0, &p->sc, &p->scIndex, &expires); - if (code) { - p->scIndex = RX_SECIDX_NULL; - p->sc = 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; -} +} /* writeFile */