diff --git a/Makefile.in b/Makefile.in index 00bf8811e7..b40d9f89ec 100644 --- a/Makefile.in +++ b/Makefile.in @@ -152,6 +152,13 @@ procmgmt: config util: $(DIR_roken) procmgmt hcrypto lwp_depinstall rx_depinstall +${COMPILE_PART1} util ${COMPILE_PART2} +libafscp: util afs volser vlserver rx auth fsint + +if test "@BUILD_KRB5@" = "yes"; then \ + ${COMPILE_PART1} libafscp ${COMPILE_PART2} ; \ + else \ + echo Skipping libafscp for ${SYS_NAME} ; \ + fi + audit: util rx rxkad fsint +${COMPILE_PART1} audit ${COMPILE_PART2} #TODO @@ -671,7 +678,7 @@ build_tools: config des comerr rxgen finale: project cmd comerr afsd butc tbutc tbudb @ENABLE_KERNEL_MODULE@ libuafs audit kauth log \ ptserver tptserver scout bu_utils ubik uss bozo @VFSCK@ volser tvolser tsalvaged \ - dviced dvolser \ + dviced dvolser libafscp\ venus update xstat afsmonitor rxdebug libafsrpc rfc3961 hcrypto \ libafsauthent shlibafsrpc shlibafsauthent libadmin man-pages \ platform kopenafs authtools $(DIR_roken) @@ -679,7 +686,7 @@ finale: project cmd comerr afsd butc tbutc tbudb @ENABLE_KERNEL_MODULE@ libuafs finale_nolibafs: project cmd comerr afsd butc tbutc tbudb libuafs audit kauth log \ ptserver tptserver scout bu_utils ubik tubik uss bozo @VFSCK@ volser tvolser tsalvaged \ - dviced dvolser \ + dviced dvolser libafscp\ venus update xstat afsmonitor rxdebug libafsrpc rfc3961 hcrypto \ libafsauthent shlibafsrpc shlibafsauthent libadmin man-pages \ platform kopenafs authtools $(DIR_roken) @@ -714,6 +721,7 @@ clean2: -${COMPILE_PART1} config ${COMPILE_CLEAN} -${COMPILE_PART1} procmgmt ${COMPILE_CLEAN} -${COMPILE_PART1} util ${COMPILE_CLEAN} + -${COMPILE_PART1} libafscp ${COMPILE_CLEAN} -${COMPILE_PART1} audit ${COMPILE_CLEAN} -${COMPILE_PART1} comerr ${COMPILE_CLEAN} -${COMPILE_PART1} cmd ${COMPILE_CLEAN} @@ -931,6 +939,7 @@ distclean: clean src/uss/Makefile \ src/util/Makefile \ src/util/test/Makefile \ + src/libafscp/Makefile \ src/venus/Makefile \ src/venus/test/Makefile \ src/vfsck/Makefile \ diff --git a/configure.ac b/configure.ac index ab207c66d9..e93d18f1a8 100644 --- a/configure.ac +++ b/configure.ac @@ -76,7 +76,7 @@ AS_IF([test x"$KRB5_LIBS" != x], [Define to 1 if you have the `krb524_convert_creds_kdc' function.])])])]) AC_CHECK_HEADERS([kerberosIV/krb.h]) AC_CHECK_HEADERS([kerberosV/heim_err.h]) - AC_CHECK_MEMBERS([krb5_creds.keyblock, krb5_creds.session, + AC_CHECK_MEMBERS([krb5_creds.keyblock, krb5_creds.keyblock.enctype, krb5_creds.session, krb5_prompt.type], , , [#include ]) RRA_LIB_KRB5_RESTORE]) AC_SUBST([BUILD_KRB5]) @@ -230,6 +230,7 @@ src/usd/test/Makefile \ src/uss/Makefile \ src/util/Makefile \ src/util/test/Makefile \ +src/libafscp/Makefile \ src/venus/Makefile \ src/venus/test/Makefile \ src/vfsck/Makefile \ diff --git a/src/libafscp/Makefile.in b/src/libafscp/Makefile.in new file mode 100644 index 0000000000..513fc48a0a --- /dev/null +++ b/src/libafscp/Makefile.in @@ -0,0 +1,72 @@ +srcdir=@srcdir@ +include @TOP_OBJDIR@/src/config/Makefile.config +include @TOP_OBJDIR@/src/config/Makefile.pthread +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ + +#for debugging: +#CFLAGS += -DAFSCP_DEBUG +KRB5CFLAGS = @KRB5_CPPFLAGS@ +KRB5LIBS = @KRB5_LIBS@ + +LIBOBJS = \ + afscp_callback.o \ + afscp_server.o \ + afscp_fid.o \ + afscp_volume.o \ + afscp_file.o \ + afscp_dir.o \ + afscp_init.o \ + afscp_util.o \ + afscp_dirops.o \ + afscp_acl.o + +all: \ + ${TOP_LIBDIR}/libafsutil.a \ + ${TOP_LIBDIR}/libafscp.a \ + depinstall + +# +# Build targets +# +${TOP_LIBDIR}/libafscp.a: libafscp.a + ${INSTALL_DATA} $? $@ + +libafscp.a: ${LIBOBJS} AFS_component_version_number.o + $(RM) -f $@ + $(AR) crv $@ ${LIBOBJS} AFS_component_version_number.o + $(RANLIB) $@ + +depinstall: \ + ${TOP_INCDIR}/afs/afscp.h + +${TOP_INCDIR}/afs/afscp.h: afscp.h + ${INSTALL_DATA} $? $@ + +CFLAGS_afscp_util.o = $(KRB5CFLAGS) +CFLAGS_afscp_server.o = $(KRB5CFLAGS) + +# +# Install targets +# +install: all + ${INSTALL} -d ${DESTDIR}${libdir} + ${INSTALL} -d ${DESTDIR}${includedir}/afs + ${INSTALL_DATA} libafscp.a ${DESTDIR}${libdir}/libafscp.a + ${INSTALL_DATA} afscp.h ${DESTDIR}${includedir}/afs/afscp.h + +dest: all + ${INSTALL} -d ${DEST}/lib + ${INSTALL} -d ${DEST}/include/afs + ${INSTALL_DATA} libafscp.a ${DEST}/lib/libafscp.a + ${INSTALL_DATA} afscp.h ${DEST}/include/afs/afscp.h + +# +# Misc targets +# +clean: + $(RM) -f *.o *.a *.gch libafscp* core AFS_component_version_number.c + +include ../config/Makefile.version diff --git a/src/libafscp/afscp.h b/src/libafscp/afscp.h index ae926c74a2..b9cc4284b4 100644 --- a/src/libafscp/afscp.h +++ b/src/libafscp/afscp.h @@ -1,136 +1,180 @@ -#ifndef _AFSCP_H_ -#define _AFSCP_H_ +#ifndef AFS_SRC_LIBAFSCP_AFSCP_H +#define AFS_SRC_LIBAFSCP_AFSCP_H /* AUTORIGHTS */ #include #include -struct afs_server; -struct afs_cell; -struct afs_callback ; +#include +#include +#include +#include -struct afs_volume -{ - struct afs_cell *cell; - afs_uint32 id; - int voltype; - int nservers; - int servers[16]; - char name[256]; - void *statcache; - void *dircache; +struct afscp_server { + afsUUID id; + int index; + int cell; + int naddrs; + afs_uint32 addrs[AFS_MAXHOSTS]; + struct rx_connection *conns[AFS_MAXHOSTS]; }; -struct afs_venusfid -{ - struct afs_cell *cell; - struct AFSFid fid; +struct afscp_cell { + int id; + char name[MAXCELLCHARS + 1]; + struct rx_securityClass *security; + int scindex; + struct ubik_client *vlservers; + int nservers; + int srvsalloced; + struct afscp_server **fsservers; + void *volsbyname; + void *volsbyid; + char *realm; }; -struct afs_dirent -{ - afs_uint32 vnode; - afs_uint32 unique; - char name[16+32*(64-2)]; /* 64 is EPP. */ +struct afscp_volume { + struct afscp_cell *cell; + afs_uint32 id; + int voltype; + int nservers; + int servers[AFS_MAXHOSTS]; + char name[AFSNAMEMAX]; + void *statcache; + void *dircache; }; -typedef struct afs_dirstream afs_DIR; -typedef struct afs_openfile afs_FILE; +struct afscp_venusfid { + struct afscp_cell *cell; + struct AFSFid fid; +}; -extern int afs_errno; -int afscp_init(const char *cellname); -void afscp_finalize(void); +struct afscp_dirent { + afs_uint32 vnode; + afs_uint32 unique; + char name[16 + 32 * (EPP - 2)]; +}; -#ifdef API_COMPAT -#define GetCellByName afs_cellbyname -#define GetCellById afs_cellbyid -#define GetDefaultCell afs_defaultcell -#define SetDefaultCell afs_setdefaultcell -#define GetCellID afs_cellid -#endif -struct afs_cell *afs_defaultcell(void); -struct afs_cell *afs_cellbyname(const char *cellname) ; -int afs_setdefaultcell(const char *cellname); -struct afs_cell *afs_cellbyid(int id); -int afs_cellid(struct afs_cell *cell); +struct afscp_dirstream { + struct afscp_venusfid fid; + int buflen; + char *dirbuffer; + int hashent; + int entry; + int dv; + struct afscp_dirent ret; +}; +struct afscp_dircache { + struct afscp_venusfid me; + int buflen; + char *dirbuffer; + int dv; +}; -#ifdef API_COMPAT -#define GetServerById afs_serverbyid -#define GetServerByAddr afs_serverbyaddr -#define GetAnyServerById afs_anyserverbyaddr -#define GetAnyServerByIndex afs_serverbyindex -#define GetConnection afs_serverconnection -#endif +struct afscp_statent { + struct afscp_venusfid me; + struct AFSFetchStatus status; +}; -struct afs_server *afs_serverbyid(struct afs_cell *thecell, afsUUID *u); -struct afs_server *afs_serverbyaddr(struct afs_cell *thecell, - afs_uint32 addr); -struct afs_server *afs_anyserverbyaddr(afs_uint32 addr) ; -struct afs_server *afs_serverbyindex(int idx) ; -struct rx_connection *afs_serverconnection(const struct afs_server *srv, - int i); +struct afscp_openfile { + struct afscp_venusfid fid; + off_t offset; +}; -int AddCallBack(const struct afs_server *server, const struct AFSFid *fid, - const struct AFSFetchStatus *st, const struct AFSCallBack *cb); -int RemoveCallBack(const struct afs_server *server, const struct afs_venusfid *fid); -int ReturnCallBacks(const struct afs_server *server); -int ReturnAllCallBacks(void); +struct afscp_callback { + int valid; + const struct afscp_server *server; + struct AFSFid fid; + struct AFSCallBack cb; + time_t as_of; +}; +extern int afscp_errno; +int afscp_Init(const char *); +void afscp_Finalize(void); + +int afscp_Insecure(void); +int afscp_AnonymousAuth(int); + +struct afscp_cell *afscp_DefaultCell(void); +struct afscp_cell *afscp_CellByName(const char *, const char *); +int afscp_SetDefaultRealm(const char *); +int afscp_SetDefaultCell(const char *); +struct afscp_cell *afscp_CellById(int); +int afscp_CellId(struct afscp_cell *); +void afscp_FreeAllCells(void); +void afscp_FreeAllServers(void); + +struct afscp_server *afscp_ServerById(struct afscp_cell *, afsUUID *); +struct afscp_server *afscp_ServerByAddr(struct afscp_cell *, afs_uint32); +struct afscp_server *afscp_AnyServerByAddr(afs_uint32); +struct afscp_server *afscp_ServerByIndex(int); +struct rx_connection *afscp_ServerConnection(const struct afscp_server *, + int); + +int afscp_AddCallBack(const struct afscp_server *, + const struct AFSFid *, + const struct AFSFetchStatus *, + const struct AFSCallBack *, const time_t); +int afscp_RemoveCallBack(const struct afscp_server *, + const struct afscp_venusfid *); +int afscp_ReturnCallBacks(const struct afscp_server *); +int afscp_ReturnAllCallBacks(void); /* file metastuff */ /* frees with free() */ -struct afs_venusfid *makefid(struct afs_cell *cell, afs_uint32 volume, - afs_uint32 vnode, afs_uint32 unique); -struct afs_venusfid *dupfid(const struct afs_venusfid *in); +struct afscp_venusfid *afscp_MakeFid(struct afscp_cell *, afs_uint32, + afs_uint32, afs_uint32); +struct afscp_venusfid *afscp_DupFid(const struct afscp_venusfid *); +void afscp_FreeFid(struct afscp_venusfid *); struct stat; -int afs_stat(const struct afs_venusfid *fid, struct stat *s); +int afscp_Stat(const struct afscp_venusfid *, struct stat *); -ssize_t afs_pread(const struct afs_venusfid *fid, void *buffer, size_t count, off_t offset); -ssize_t afs_pwrite(const struct afs_venusfid *fid, const void *buffer, size_t count, off_t offset); -afs_FILE *afs_open(const char *path); -afs_FILE *afs_fidopen(const struct afs_venusfid *fid); -off_t afs_fseek (afs_FILE *f, off_t o, int whence); -ssize_t afs_fread(const afs_FILE *f, void *buffer, size_t count); -ssize_t afs_fwrite(const afs_FILE *f, const void *buffer, size_t count); +ssize_t afscp_PRead(const struct afscp_venusfid *, void *, size_t, off_t); +ssize_t afscp_PWrite(const struct afscp_venusfid *, const void *, + size_t, off_t); +/* + * for future implementation: (?) + * struct afscp_openfile *afscp_FidOpen(const struct afscp_venusfid *); + * off_t afscp_FSeek(struct afscp_openfile *, off_t, int); + * ssize_t afscp_FRead(const struct afscp_openfile *, void *, size_t); + */ /* rpc wrappers */ -int afs_GetStatus(const struct afs_venusfid *fid, struct AFSFetchStatus *s); -int afs_StoreStatus(const struct afs_venusfid *fid, struct AFSStoreStatus *s); -int afs_CreateFile(const struct afs_venusfid *fid, /* const */ char *name, - struct AFSStoreStatus *sst, - struct afs_venusfid **ret); -int afs_MakeDir(const struct afs_venusfid *fid, /* const */ char *name, - struct AFSStoreStatus *sst, - struct afs_venusfid **ret); -int afs_Symlink(const struct afs_venusfid *fid, /* const */ char *name, - /*const*/ char *target, struct AFSStoreStatus *sst); -int afs_RemoveFile(const struct afs_venusfid *dir, char *name); -int afs_RemoveDir(const struct afs_venusfid *dir, char *name); -int afs_FetchACL(const struct afs_venusfid *dir, - struct AFSOpaque *acl); -int afs_StoreACL(const struct afs_venusfid *dir, - struct AFSOpaque *acl); +int afscp_GetStatus(const struct afscp_venusfid *, struct AFSFetchStatus *); +int afscp_StoreStatus(const struct afscp_venusfid *, struct AFSStoreStatus *); +int afscp_CreateFile(const struct afscp_venusfid *, char *, + struct AFSStoreStatus *, struct afscp_venusfid **); +int afscp_MakeDir(const struct afscp_venusfid *, char *, + struct AFSStoreStatus *, struct afscp_venusfid **); +int afscp_Symlink(const struct afscp_venusfid *, char *, + char *, struct AFSStoreStatus *); +int afscp_RemoveFile(const struct afscp_venusfid *, char *); +int afscp_RemoveDir(const struct afscp_venusfid *, char *); +int afscp_FetchACL(const struct afscp_venusfid *, struct AFSOpaque *); +int afscp_StoreACL(const struct afscp_venusfid *, struct AFSOpaque *); + /* directory parsing stuff*/ -struct afs_dirstream *afs_opendir(const struct afs_venusfid *fid); -struct afs_dirent *afs_readdir(struct afs_dirstream *d); -int afs_rewinddir(struct afs_dirstream *d); -int afs_closedir(struct afs_dirstream *d); -struct afs_venusfid *DirLookup(struct afs_dirstream *d, const char *name); -struct afs_venusfid *ResolveName(const struct afs_venusfid *dir, const char *name); -struct afs_venusfid *ResolvePath(const char *path); -struct afs_venusfid *ResolvePath2(const struct afs_volume *start, const char *path); +struct afscp_dirstream *afscp_OpenDir(const struct afscp_venusfid *); +struct afscp_dirent *afscp_ReadDir(struct afscp_dirstream *); +int afscp_RewindDir(struct afscp_dirstream *); +int afscp_CloseDir(struct afscp_dirstream *); +struct afscp_venusfid *afscp_DirLookup(struct afscp_dirstream *, + const char *); +struct afscp_venusfid *afscp_ResolveName(const struct afscp_venusfid *, + const char *); +struct afscp_venusfid *afscp_ResolvePath(const char *); +struct afscp_venusfid *afscp_ResolvePathFromVol(const struct afscp_volume *, + const char *); /* vldb stuff */ -struct afs_volume *afs_volumebyname(struct afs_cell *cell, const char *vname, afs_int32 vtype); -struct afs_volume *afs_volumebyid(struct afs_cell *cell, afs_uint32 id); +struct afscp_volume *afscp_VolumeByName(struct afscp_cell *, + const char *, afs_int32); +struct afscp_volume *afscp_VolumeById(struct afscp_cell *, afs_uint32); -#define DIRMODE_CELL 0 -#define DIRMODE_DYNROOT 1 +#define DIRMODE_CELL 0 +#define DIRMODE_DYNROOT 1 +int afscp_SetDirMode(int); -#define VOLTYPE_RW 0 -#define VOLTYPE_RO 1 -#define VOLTYPE_BK 2 -int SetDirMode(int mode); - -#endif +#endif /* AFS_SRC_LIBAFSCP_AFSCP_H */ diff --git a/src/libafscp/afscp_acl.c b/src/libafscp/afscp_acl.c index 393c6cdbc7..596d0e436d 100644 --- a/src/libafscp/afscp_acl.c +++ b/src/libafscp/afscp_acl.c @@ -24,89 +24,88 @@ 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 #include -#include + +#include + #include #include #include -#include -#include -#include #include "afscp.h" #include "afscp_internal.h" +int +afscp_FetchACL(const struct afscp_venusfid *dir, struct AFSOpaque *acl) +{ + int code, i, j; + struct AFSFid df = dir->fid; + struct afscp_volume *vol; + struct AFSFetchStatus dfst; + struct AFSVolSync vs; + struct afscp_server *server; -int afs_FetchACL(const struct afs_venusfid *dir, - struct AFSOpaque *acl) { - int code, i, j; - struct AFSFid df = dir->fid; - struct afs_volume *vol; - struct AFSFetchStatus dfst; - struct AFSVolSync vs; - struct afs_volume *volume; - struct afs_server *server; - - vol=afs_volumebyid(dir->cell, dir->fid.Volume); - if (!vol) { - afs_errno=ENOENT; - return -1; - } - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(vol->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_FetchACL(server->conns[j], &df, acl, &dfst, &vs); - if (code >= 0) - break; - } + vol = afscp_VolumeById(dir->cell, dir->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; } - if (code >= 0) - break; - } - if (code) { - _StatInvalidate(dir); - afs_errno=code; - return -1; - } - _StatStuff(dir, &dfst); - return 0; + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + code = RXAFS_FetchACL(server->conns[j], &df, acl, &dfst, &vs); + if (code >= 0) + break; + } + } + if (code >= 0) + break; + } + if (code != 0) { + _StatInvalidate(dir); + afscp_errno = code; + return -1; + } + _StatStuff(dir, &dfst); + return 0; } -int afs_StoreACL(const struct afs_venusfid *dir, - struct AFSOpaque *acl) { - int code, i, j; - struct AFSFid df = dir->fid; - struct afs_volume *vol; - struct AFSFetchStatus dfst; - struct AFSVolSync vs; - struct afs_volume *volume; - struct afs_server *server; +int +afscp_StoreACL(const struct afscp_venusfid *dir, struct AFSOpaque *acl) +{ + int code, i, j; + struct AFSFid df = dir->fid; + struct afscp_volume *vol; + struct AFSFetchStatus dfst; + struct AFSVolSync vs; + struct afscp_server *server; - vol=afs_volumebyid(dir->cell, dir->fid.Volume); - if (!vol) { - afs_errno=ENOENT; - return -1; - } - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(vol->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_StoreACL(server->conns[j], &df, acl, &dfst, &vs); - if (code >= 0) - break; - } + vol = afscp_VolumeById(dir->cell, dir->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; } - if (code >= 0) - break; - } - if (code) { - _StatInvalidate(dir); - afs_errno=code; - return -1; - } - _StatStuff(dir, &dfst); - return 0; + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + code = RXAFS_StoreACL(server->conns[j], &df, acl, &dfst, &vs); + if (code >= 0) + break; + } + } + if (code >= 0) + break; + } + if (code != 0) { + _StatInvalidate(dir); + afscp_errno = code; + return -1; + } + _StatStuff(dir, &dfst); + return 0; } diff --git a/src/libafscp/afscp_callback.c b/src/libafscp/afscp_callback.c index f001b3c4f2..dfb5b3bb29 100644 --- a/src/libafscp/afscp_callback.c +++ b/src/libafscp/afscp_callback.c @@ -24,433 +24,704 @@ 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 #include -#include /*Callback interface defs*/ + +#include + #include -#include -#include +#ifdef AFS_NT40_ENV +#include +#include +#endif #include "afscp.h" #include "afscp_internal.h" int afs_cb_inited = 0; struct interfaceAddr afs_cb_interface; -static int afs_maxcallbacks=0, afs_cballoced=0; -struct afs_callback *allcallbacks=NULL; +static int afscp_maxcallbacks = 0, afscp_cballoced = 0; +struct afscp_callback *allcallbacks = NULL; -static int init_afs_cb() { - int count; +/*! + * Initialize the callback interface structure + */ +static int +init_afs_cb(void) +{ + int cm_noIPAddr; /* number of client network interfaces */ +#ifdef AFS_NT40_ENV + /* + * This Windows section was pulled in from changes to src/venus/afsio.c but is + * untested here and may be unnecessary if rx_getAllAddr() can be used on that + * platform. However, there was already an ifdef here surrounding UuidCreate(). + */ + int code; + 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; + UuidCreate((UUID *) & afs_cb_interface.uuid); + 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 */ + afs_cb_interface.numberOfInterfaces = cm_noIPAddr; + for (i = 0; i < cm_noIPAddr; i++) { + afs_cb_interface.addr_in[i] = cm_IPAddr[i]; + afs_cb_interface.subnetmask[i] = cm_SubnetMask[i]; + afs_cb_interface.mtu[i] = (rx_mtu == -1 + || (rx_mtu != -1 + && cm_NetMtu[i] < + rx_mtu)) ? cm_NetMtu[i] : rx_mtu; + } + } else { + afs_cb_interface.numberOfInterfaces = 0; + } +#else afs_uuid_create(&afs_cb_interface.uuid); - count = rx_getAllAddr(&afs_cb_interface.addr_in, AFS_MAX_INTERFACE_ADDR); - if ( count <= 0 ) - afs_cb_interface.numberOfInterfaces = 0; + cm_noIPAddr = + rx_getAllAddr((afs_uint32 *) afs_cb_interface.addr_in, + AFS_MAX_INTERFACE_ADDR); + if (cm_noIPAddr < 0) + afs_cb_interface.numberOfInterfaces = 0; else - afs_cb_interface.numberOfInterfaces = count; + afs_cb_interface.numberOfInterfaces = cm_noIPAddr; +#endif afs_cb_inited = 1; return 0; -} +} /* init_afs_cb */ -int AddCallBack(const struct afs_server *server, const struct AFSFid *fid, - const struct AFSFetchStatus *fst, const struct AFSCallBack *cb) +int +afscp_AddCallBack(const struct afscp_server *server, + const struct AFSFid *fid, + const struct AFSFetchStatus *fst, + const struct AFSCallBack *cb, const time_t as_of) { - int i; - struct afs_callback *use=NULL, *newlist; - struct afs_venusfid f; - time_t now; + int i; + struct afscp_callback *use = NULL, *newlist; + struct afscp_venusfid f; + time_t now; - time(&now); + time(&now); - for (i=0;icell); - memcpy(&f.fid, &allcallbacks[i].fid, sizeof(struct afs_venusfid)); - _StatInvalidate(&f); - } - allcallbacks[i].valid=0; + for (i = 0; i < afscp_maxcallbacks; i++) { + if (allcallbacks[i].cb.ExpirationTime + allcallbacks[i].as_of < now) { + if (allcallbacks[i].valid) { + f.cell = afscp_CellById(allcallbacks[i].server->cell); + memcpy(&f.fid, &allcallbacks[i].fid, sizeof(struct AFSFid)); + _StatInvalidate(&f); + } + allcallbacks[i].valid = 0; - } + } - if (allcallbacks[i].valid == 0) - use=&allcallbacks[i]; - if (allcallbacks[i].server==server && - fid->Volume == allcallbacks[i].fid.Volume && - fid->Vnode == allcallbacks[i].fid.Vnode && - fid->Unique == allcallbacks[i].fid.Unique) { - use=&allcallbacks[i]; + if (allcallbacks[i].valid == 0) + use = &allcallbacks[i]; + if ((allcallbacks[i].server == server) && + (fid->Volume == allcallbacks[i].fid.Volume) && + (fid->Vnode == allcallbacks[i].fid.Vnode) && + (fid->Unique == allcallbacks[i].fid.Unique)) { + use = &allcallbacks[i]; break; - } - } - if (!use) { - if (afs_maxcallbacks >= afs_cballoced) { - if (afs_cballoced) - afs_cballoced = afs_cballoced *2; - else - afs_cballoced = 4; - newlist=realloc(allcallbacks, afs_cballoced * - sizeof(struct afs_callback)); - if (!newlist) - return -1; - allcallbacks=newlist; - } - use=&allcallbacks[afs_maxcallbacks++]; - } - use->valid=1; - use->server=server; - memmove(&use->fid, fid, sizeof(struct AFSFid)); - memmove(&use->cb, cb, sizeof(struct AFSCallBack)); - f.cell=afs_cellbyid(server->cell); - memcpy(&f.fid, fid, sizeof(struct AFSFid)); - _StatStuff(&f, fst); - return 0; -} -int RemoveCallBack(const struct afs_server *server, const struct afs_venusfid *f) + } + } + if (use == NULL) { + if (afscp_maxcallbacks >= afscp_cballoced) { + if (afscp_cballoced != 0) + afscp_cballoced = afscp_cballoced * 2; + else + afscp_cballoced = 4; + newlist = realloc(allcallbacks, afscp_cballoced * + sizeof(struct afscp_callback)); + if (newlist == NULL) { + return -1; + } + allcallbacks = newlist; + } + use = &allcallbacks[afscp_maxcallbacks++]; + } + use->valid = 1; + use->server = server; + memmove(&use->fid, fid, sizeof(struct AFSFid)); + memmove(&use->cb, cb, sizeof(struct AFSCallBack)); + use->as_of = as_of; + f.cell = afscp_CellById(server->cell); + memcpy(&f.fid, fid, sizeof(struct AFSFid)); + _StatStuff(&f, fst); + return 0; +} /* afscp_AddCallBack */ + +int +afscp_RemoveCallBack(const struct afscp_server *server, + const struct afscp_venusfid *f) { - struct afs_callback *cb; - int i; + struct afscp_callback *cb; + int i; - _StatInvalidate(f); - if (!server) - return 0; - for (i=0;iserver == server && - f->fid.Volume == cb->fid.Volume && - f->fid.Vnode == cb->fid.Vnode && - f->fid.Unique == cb->fid.Unique) { - cb->valid = 0; - break; - } - } - return 0; -} + _StatInvalidate(f); + if (server == NULL) { + return 0; + } + for (i = 0; i < afscp_maxcallbacks; i++) { + cb = &allcallbacks[i]; + if ((cb->server == server) && + (f->fid.Volume == cb->fid.Volume) && + (f->fid.Vnode == cb->fid.Vnode) && + (f->fid.Unique == cb->fid.Unique)) { + cb->valid = 0; + break; + } + } + return 0; +} /* afscp_ReturnCallBacks */ -int ReturnCallBacks(const struct afs_server *server) +int +afscp_ReturnCallBacks(const struct afscp_server *server) { - struct AFSCBFids theFids; - struct AFSCBs theCBs; - struct afs_callback *cb; - struct afs_venusfid f; - int inited=0; - int ncallbacks=0; - int i,j; - time_t now; + struct AFSCBFids theFids; + struct AFSCBs theCBs; + struct afscp_callback *cb; + struct afscp_venusfid f; + struct rx_connection *c; + int inited = 0; + int ncallbacks = 0; + int i, j, code; + time_t now; - time(&now); + time(&now); - for (i=0;iserver, cb->cb.ExpirationTime, - cb->valid);*/ - if (cb->server != server) - continue; - if (cb->cb.ExpirationTime < now) { - if (cb->valid) { - f.cell=afs_cellbyid(cb->server->cell); - memcpy(&f.fid, &cb->fid, sizeof(struct afs_venusfid)); - _StatInvalidate(&f); - } - - cb->valid=0; + for (i = 0; i < afscp_maxcallbacks; i++) { + cb = &allcallbacks[i]; + if (cb->server != server) { continue; - } - if (!inited) { - theFids.AFSCBFids_val=malloc(sizeof(struct AFSCallBack) * AFSCBMAX); - if (!theFids.AFSCBFids_val) - return -1; - theCBs.AFSCBs_val=malloc(sizeof(struct AFSFid) * AFSCBMAX); - if (!theCBs.AFSCBs_val) { - free(theFids.AFSCBFids_val); - return -1; - } - } + } + if (cb->cb.ExpirationTime + cb->as_of < now) { + if (cb->valid) { + f.cell = afscp_CellById(cb->server->cell); + memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid)); + _StatInvalidate(&f); + } + cb->valid = 0; + continue; + } + if (!inited) { + theFids.AFSCBFids_val = malloc(sizeof(struct AFSFid) * AFSCBMAX); + if (!theFids.AFSCBFids_val) { + return -1; + } + memset(theFids.AFSCBFids_val, 0, + sizeof(struct AFSFid) * AFSCBMAX); + theCBs.AFSCBs_val = malloc(sizeof(struct AFSCallBack) * AFSCBMAX); + if (!theCBs.AFSCBs_val) { + free(theFids.AFSCBFids_val); + return -1; + } + memset(theCBs.AFSCBs_val, 0, + sizeof(struct AFSCallBack) * AFSCBMAX); + inited = 1; + } - if (ncallbacks == AFSCBMAX) { - theFids.AFSCBFids_len=ncallbacks; - theCBs.AFSCBs_len=ncallbacks; - for (j=0;jnaddrs;j++) { - if (!RXAFS_GiveUpCallBacks(server->conns[j], &theFids, - &theCBs)) - break; - } - ncallbacks=0; - } - memmove(&theFids.AFSCBFids_val[ncallbacks], &cb->fid, - sizeof(struct AFSFid)); - memmove(&theCBs.AFSCBs_val[ncallbacks], &cb->cb, - sizeof(struct AFSCallBack)); + if (ncallbacks == AFSCBMAX) { + theFids.AFSCBFids_len = ncallbacks; + theCBs.AFSCBs_len = ncallbacks; + for (j = 0; j < server->naddrs; j++) { + c = afscp_ServerConnection(server, j); + if (c == NULL) + break; + code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs); + if (code == 0) + break; + } + ncallbacks = 0; + } + memmove(&theFids.AFSCBFids_val[ncallbacks], &cb->fid, + sizeof(struct AFSFid)); + memmove(&theCBs.AFSCBs_val[ncallbacks], &cb->cb, + sizeof(struct AFSCallBack)); - theCBs.AFSCBs_val[ncallbacks].CallBackType = CB_DROPPED; - ncallbacks++; - if (cb->valid) { - f.cell=afs_cellbyid(cb->server->cell); - memcpy(&f.fid, &cb->fid, sizeof(struct afs_callback)); - _StatInvalidate(&f); - } + theCBs.AFSCBs_val[ncallbacks].CallBackType = CB_DROPPED; + ncallbacks++; + if (cb->valid) { + f.cell = afscp_CellById(cb->server->cell); + memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid)); + _StatInvalidate(&f); + } - cb->valid=0; - } - if (ncallbacks) { - theFids.AFSCBFids_len=ncallbacks; - theCBs.AFSCBs_len=ncallbacks; - for (j=0;jnaddrs;j++) { - if (!RXAFS_GiveUpCallBacks(server->conns[j], &theFids, - &theCBs)) - break; - } - free(theFids.AFSCBFids_val); - free(theCBs.AFSCBs_val); - } - return 0; -} + cb->valid = 0; + } + if (ncallbacks > 0) { + theFids.AFSCBFids_len = ncallbacks; + theCBs.AFSCBs_len = ncallbacks; + for (j = 0; j < server->naddrs; j++) { + c = afscp_ServerConnection(server, j); + if (c == NULL) + break; + code = RXAFS_GiveUpCallBacks(c, &theFids, &theCBs); + if (code == 0) + break; + } + free(theFids.AFSCBFids_val); + free(theCBs.AFSCBs_val); + } + return 0; +} /* afscp_ReturnCallBacks */ -int ReturnAllCallBacks(void) +int +afscp_ReturnAllCallBacks(void) { - struct afs_server *s; - int i; + struct afscp_server *s; + int i; - for (i=0;(s=afs_serverbyindex(i));i++) - ReturnCallBacks(s); - return 0; -} + if (allcallbacks == NULL) + return 0; + for (i = 0; (s = afscp_ServerByIndex(i)); i++) { + afscp_ReturnCallBacks(s); + } + free(allcallbacks); + allcallbacks = NULL; + afscp_maxcallbacks = 0; + afscp_cballoced = 0; + return 0; +} /* afscp_ReturnAllCallBacks */ +/*! + * Handle a set of callbacks from the File Server. + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * \param[in] Fids_Array Ptr to the set of Fids. + * \param[in] CallBacks_Array Ptr to the set of callbacks. + * + * \post Returns RXGEN_SUCCESS on success, Error value otherwise. + * + */ +afs_int32 +SRXAFSCB_CallBack(struct rx_call * rxcall, AFSCBFids * Fids_Array, + AFSCBs * CallBack_Array) +{ + struct rx_connection *rxconn = rx_ConnectionOf(rxcall); + struct rx_peer *rxpeer = rx_PeerOf(rxconn); + struct afscp_server *server = afscp_AnyServerByAddr(rxpeer->host); + struct afscp_callback *cb; + struct afscp_venusfid f; + struct AFSFid *fid; + int i, j; + if (server == NULL) { + return 0; + } + for (i = 0; i < afscp_maxcallbacks; i++) { + cb = &allcallbacks[i]; + if (cb->server != server) + continue; + for (j = 0; j < Fids_Array->AFSCBFids_len; j++) { + fid = &Fids_Array->AFSCBFids_val[j]; + if ((fid->Volume == cb->fid.Volume) && + (fid->Vnode == cb->fid.Vnode) && + (fid->Unique == cb->fid.Unique)) + cb->valid = 0; + f.cell = afscp_CellById(cb->server->cell); + memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid)); + _StatInvalidate(&f); + } + } -afs_int32 SRXAFSCB_CallBack(rxcall, Fids_Array, CallBack_Array) - struct rx_call *rxcall; - AFSCBFids *Fids_Array; - AFSCBs *CallBack_Array; + return RXGEN_SUCCESS; +} /*SRXAFSCB_CallBack */ -{ /*SRXAFSCB_CallBack*/ - struct rx_connection *rxconn=rx_ConnectionOf(rxcall); - struct rx_peer *rxpeer=rx_PeerOf(rxconn); - struct afs_server *server=afs_anyserverbyaddr(rxpeer->host); - struct afs_callback *cb; - struct afs_venusfid f; - struct AFSFid *fid; - int i,j; +/*! + * Initialize callback state on this ``Cache Manager''. + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * + * \post Returns RXGEN_SUCCESS on success, Error value otherwise. + * + * \note This will definitely be called by the File Server (exactly once), + * since it will think we are another new ``Cache Manager''. + */ +afs_int32 +SRXAFSCB_InitCallBackState(struct rx_call * rxcall) +{ + struct rx_connection *rxconn = rx_ConnectionOf(rxcall); + struct rx_peer *rxpeer = rx_PeerOf(rxconn); + struct afscp_server *server = afscp_AnyServerByAddr(rxpeer->host); + struct afscp_callback *cb; + struct afscp_venusfid f; + int i; - if (!server) - return 0; - for (i=0;iserver != server) - continue; - for (j=0;jAFSCBFids_len;j++) { - fid=&Fids_Array->AFSCBFids_val[j]; - if (fid->Volume == cb->fid.Volume && - fid->Vnode == cb->fid.Vnode && - fid->Unique == cb->fid.Unique) - cb->valid = 0; - f.cell=afs_cellbyid(cb->server->cell); - memcpy(&f.fid, &cb->fid, sizeof(struct afs_venusfid)); - _StatInvalidate(&f); - } - } + if (server == NULL) { + return 0; + } + for (i = 0; i < afscp_maxcallbacks; i++) { + cb = &allcallbacks[i]; + if (cb->server != server) + continue; + if (cb->valid) { + f.cell = afscp_CellById(cb->server->cell); + memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid)); + _StatInvalidate(&f); + } + cb->valid = 0; + } + return RXGEN_SUCCESS; +} /* SRXAFSCB_InitCallBackState */ - return(0); +/*! + * Respond to a probe from the File Server. + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * + * \post Returns RXGEN_SUCCESS (always) + * + * \note If a File Server doesn't hear from you every so often, it will + * send you a probe to make sure you're there, just like any other + * ``Cache Manager'' it's keeping track of. + * + */ +afs_int32 +SRXAFSCB_Probe(struct rx_call * rxcall) +{ + return RXGEN_SUCCESS; +} /* SRXAFSCB_Probe */ -} /*SRXAFSCB_CallBack*/ +/*! + * Respond minimally to a request for returning the contents of + * a cache lock, since someone out there thinks you're a Cache + * Manager. + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * \param[in] index + * \param[out] lock + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_GetLock(struct rx_call * rxcall, afs_int32 index, AFSDBLock * lock) +{ + return RXGEN_SUCCESS; +} /*SRXAFSCB_GetLock */ -afs_int32 SRXAFSCB_InitCallBackState(rxcall) - struct rx_call *rxcall; +/*! + * Respond minimally to a request for returning the contents of + * a cache entry, since someone out there thinks you're a Cache + * Manager. + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * \param[in] index + * \param[out] ce Ptr to cache entry + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_GetCE(struct rx_call * rxcall, afs_int32 index, AFSDBCacheEntry * ce) +{ + return RXGEN_SUCCESS; +} /* SRXAFSCB_GetCE */ -{ /*SRXAFSCB_InitCallBackState*/ - struct rx_connection *rxconn=rx_ConnectionOf(rxcall); - struct rx_peer *rxpeer=rx_PeerOf(rxconn); - struct afs_server *server=afs_anyserverbyaddr(rxpeer->host); - struct afs_callback *cb; - struct afs_venusfid f; - int i; +/*! + * Respond minimally to a request for returning the contents of + * a cache entry, since someone out there thinks you're a Cache + * Manager. (64-bit version, though same as SRXAFSCB_GetCE()) + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * \param[in] index + * \param[out] ce Ptr to cache entry + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_GetCE64(struct rx_call * rxcall, afs_int32 index, + AFSDBCacheEntry64 * ce) +{ + return RXGEN_SUCCESS; +} /*SRXAFSCB_GetCE */ - if (!server) - return 0; - for (i=0;iserver != server) - continue; - if (cb->valid) { - f.cell=afs_cellbyid(cb->server->cell); - memcpy(&f.fid, &cb->fid, sizeof(struct afs_callback)); - _StatInvalidate(&f); - } - cb->valid = 0; - } - return(0); +/*! + * Respond minimally to a request for fetching the version of + * extended Cache Manager statistics offered, since someone out + * there thinks you're a Cache Manager. + * + * \param[in] rxcall Ptr to the associated Rx call structure + * \param[out] versionNumberP + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_XStatsVersion(struct rx_call * rxcall, afs_int32 * versionNumberP) +{ + return RXGEN_SUCCESS; +} /*SRXAFSCB_XStatsVersion */ -} /*SRXAFSCB_InitCallBackState*/ +/*! + * Respond minimally to a request for returning extended + * statistics for a Cache Manager, since someone out there thinks + * you're a Cache Manager. + * + * \param[in] z_call Ptr to the associated Rx call structure + * \param[in] clientVersionNumber + * \param[in] collectionNumber + * \param[out] srvVersionNumberP + * \param[out] timeP + * \param[out] dataP + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_GetXStats(struct rx_call * z_call, afs_int32 clientVersionNumber, + afs_int32 collectionNumber, afs_int32 * srvVersionNumberP, + afs_int32 * timeP, AFSCB_CollData * dataP) +{ + return RXGEN_SUCCESS; +} /*SRXAFSCB_GetXStats */ -afs_int32 SRXAFSCB_Probe(rxcall) - struct rx_call *rxcall; - -{ /*SRXAFSCB_Probe*/ - return(0); - -} /*SRXAFSCB_Probe*/ - - -afs_int32 SRXAFSCB_GetCE(rxcall) - struct rx_call *rxcall; - -{ /*SRXAFSCB_GetCE*/ - return(0); -} /*SRXAFSCB_GetCE*/ - -afs_int32 SRXAFSCB_GetCE64(rxcall) - struct rx_call *rxcall; - -{ /*SRXAFSCB_GetCE*/ - return(0); -} /*SRXAFSCB_GetCE*/ - - -afs_int32 SRXAFSCB_GetLock(rxcall) - struct rx_call *rxcall; - -{ /*SRXAFSCB_GetLock*/ - return(0); - -} /*SRXAFSCB_GetLock*/ -afs_int32 SRXAFSCB_XStatsVersion(rxcall) - struct rx_call *rxcall; - -{ /*SRXAFSCB_XStatsVersion*/ - return(0); - -} /*SRXAFSCB_XStatsVersion*/ - -afs_int32 SRXAFSCB_GetXStats(rxcall) - struct rx_call *rxcall; - -{ /*SRXAFSCB_GetXStats*/ - return(0); -} /*SRXAFSCB_GetXStats*/ - -int SRXAFSCB_InitCallBackState2(rxcall, addr) -struct rx_call *rxcall; -struct interfaceAddr * addr; +/*! + * This routine was used in the AFS 3.5 beta release, but not anymore. + * It has since been replaced by SRXAFSCB_InitCallBackState3. + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * \param[out] addr Ptr to return the list of interfaces for this client + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_InitCallBackState2(struct rx_call * rxcall, + struct interfaceAddr * addr) { return RXGEN_OPCODE; -} +} /* SRXAFSCB_InitCallBackState2 */ -int SRXAFSCB_WhoAreYou(rxcall, addr) -struct rx_call *rxcall; -struct interfaceAddr *addr; +/*! + * + * \param rxcall Ptr to the associated Rx call structure. + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_TellMeAboutYourself(struct rx_call * a_call, + struct interfaceAddr * addr, + Capabilities * capabilities) { - XDR x; - if ( rxcall && addr ) - { - if (!afs_cb_inited) init_afs_cb(); - *addr = afs_cb_interface; +#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 + if (a_call && addr) { + if (!afs_cb_inited) + init_afs_cb(); + *addr = afs_cb_interface; } -#ifdef STRANGEDEBUG - xdrrx_create(&x, rxcall, XDR_ENCODE); - xdr_interfaceAddr(&x, addr); - rx_Write(rxcall,"",0); - rxi_FlushWrite(rxcall); - rx_EndCall(rxcall, 0); - IOMGR_Sleep(10); - IOMGR_Sleep(600); #endif - return(0); -} + if (capabilities != NULL) { + afs_uint32 *dataBuffP; + afs_int32 dataBytes; -int SRXAFSCB_InitCallBackState3(rxcall, uuidp) -struct rx_call *rxcall; -afsUUID *uuidp; + 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 RXGEN_SUCCESS; +} /* SRXAFSCB_TellMeAboutYourself */ + +/*! + * Routine called by the server-side callback RPC interface to + * obtain a unique identifier for the client. The server uses + * this identifier to figure out whether or not two RX connections + * are from the same client, and to find out which addresses go + * with which clients. + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * \param[out] addr Ptr to return the list of interfaces for this client + * + * \post Returns output of TellMeAboutYourself (which + * should be RXGEN_SUCCESS). + * + */ +afs_int32 +SRXAFSCB_WhoAreYou(struct rx_call * rxcall, struct interfaceAddr * addr) { - struct rx_connection *rxconn=rx_ConnectionOf(rxcall); - struct rx_peer *rxpeer=rx_PeerOf(rxconn); - struct afs_server *server=afs_anyserverbyaddr(rxpeer->host); - struct afs_callback *cb; - struct afs_venusfid f; - int i; + return SRXAFSCB_TellMeAboutYourself(rxcall, addr, NULL); +} /* SRXAFSCB_WhoAreYou */ - if (!server) - return 0; - for (i=0;iserver != server) - continue; - if (cb->valid) { - f.cell=afs_cellbyid(cb->server->cell); - memcpy(&f.fid, &cb->fid, sizeof(struct afs_callback)); - _StatInvalidate(&f); - } - cb->valid = 0; - } - return(0); -} -int SRXAFSCB_ProbeUuid(rxcall, uuidp) -struct rx_call *rxcall; -afsUUID *uuidp; +/*! + * Routine called by the server-side callback RPC interface to + * implement clearing all callbacks from this host. + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * \param[in] serverUuid Ptr to UUID + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_InitCallBackState3(struct rx_call * rxcall, afsUUID * serverUuid) +{ + struct rx_connection *rxconn = rx_ConnectionOf(rxcall); + struct rx_peer *rxpeer = rx_PeerOf(rxconn); + struct afscp_server *server = afscp_AnyServerByAddr(rxpeer->host); + struct afscp_callback *cb; + struct afscp_venusfid f; + int i; + + if (server == NULL) { + return 0; + } + for (i = 0; i < afscp_maxcallbacks; i++) { + cb = &allcallbacks[i]; + if (cb->server != server) + continue; + if (cb->valid) { + f.cell = afscp_CellById(cb->server->cell); + memcpy(&f.fid, &cb->fid, sizeof(struct AFSFid)); + _StatInvalidate(&f); + } + cb->valid = 0; + } + return RXGEN_SUCCESS; +} /* SRXAFSCB_InitCallBackState3 */ + +/*! + * Routine called by the server-side callback RPC interface to + * implement ``probing'' the Cache Manager, just making sure it's + * still there is still the same client it used to be. + * + * \param rxcall Ptr to the associated Rx call structure. + * \param clientUuid Ptr to UUID that must match the client's UUID + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_ProbeUuid(struct rx_call * rxcall, afsUUID * clientUuid) { int code = 0; - if (!afs_cb_inited) init_afs_cb(); - if (!afs_uuid_equal(uuidp, &afs_cb_interface.uuid)) - code = 1; /* failure */ -#ifdef STRANGEDEBUG - rx_EndCall(rxcall,code); - IOMGR_Sleep(600); -#endif + if (!afs_cb_inited) + init_afs_cb(); + if (!afs_uuid_equal(clientUuid, &afs_cb_interface.uuid)) + code = 1; /* failure */ return code; -} -int SRXAFSCB_GetServerPrefs( - struct rx_call *a_call, - afs_int32 a_index, - afs_int32 *a_srvr_addr, - afs_int32 *a_srvr_rank) +} /* SRXAFSCB_ProbeUuid */ + +/*! + * Routine to list server preferences used by this client. + * + * \param[in] a_call Ptr to Rx call on which this request came in. + * \param[in] a_index Input server index + * \param[out] a_srvr_addr Output server address (0xffffffff on last server) + * \param[out] a_srvr_rank Output server rank + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +afs_int32 +SRXAFSCB_GetServerPrefs(struct rx_call * a_call, afs_int32 a_index, + afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank) { *a_srvr_addr = 0xffffffff; *a_srvr_rank = 0xffffffff; - return 0; -} + return RXGEN_SUCCESS; +} /* SRXAFSCB_GetServerPrefs */ -int SRXAFSCB_GetCellServDB( - struct rx_call *a_call, - afs_int32 a_index, - char **a_name, - afs_int32 *a_hosts) -{ - return RXGEN_OPCODE; -} - -int SRXAFSCB_GetLocalCell( - struct rx_call *a_call, - char **a_name) -{ - return RXGEN_OPCODE; -} - -int SRXAFSCB_GetCacheConfig( - struct rx_call *a_call, - afs_uint32 callerVersion, - afs_uint32 *serverVersion, - afs_uint32 *configCount, - cacheConfig *config) -{ - return RXGEN_OPCODE; -} -int SRXAFSCB_GetCellByNum( - struct rx_call *a_call, - afs_int32 a_index, - char **a_name, - afs_int32 *a_hosts) -{ - return RXGEN_OPCODE; -} -#ifdef AFS_64BIT_CLIENT +/*! + * Routine to list cells configured for this client + * + * \param[in] a_call Ptr to Rx call on which this request came in. + * \param[in] a_index Input cell index + * \param[out] a_name Output cell name ("" on last cell) + * \param[out] a_hosts Output cell database servers + * + * \post Returns RXGEN_OPCODE (always) + * + */ afs_int32 -SRXAFSCB_TellMeAboutYourself(struct rx_call * rxcall, - struct interfaceAddr * addr, - Capabilities * capabilities) +SRXAFSCB_GetCellServDB(struct rx_call * a_call, afs_int32 a_index, + char **a_name, afs_int32 * a_hosts) { - if ( rxcall && addr ) - { - if (!afs_cb_inited) init_afs_cb(); - *addr = afs_cb_interface; - } - return(0); -} -#endif + return RXGEN_OPCODE; +} /* SRXAFSCB_GetCellServDB */ + +/*! + * Routine to return name of client's local cell + * + * \param[in] a_call Ptr to Rx call on which this request came in. + * \param[out] a_name Output cell name + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +int +SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name) +{ + return RXGEN_OPCODE; +} /* SRXAFSCB_GetLocalCell */ + +/*! + * Routine to return parameters used to initialize client cache. + * Client may request any format version. Server may not return + * format version greater than version requested by client. + * + * \param[in] a_call Ptr to Rx call on which this request came in. + * \param[in] callerVersion Data format version desired by the client. + * \param[out] serverVersion Data format version of output data. + * \param[out] configCount Number bytes allocated for output data. + * \param[out] config Client cache configuration. + * + * \post Returns RXGEN_SUCCESS (always) + * + */ +int +SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion, + afs_uint32 * serverVersion, afs_uint32 * configCount, + cacheConfig * config) +{ + return RXGEN_OPCODE; +} /* SRXAFSCB_GetCacheConfig */ + +/*! + + * + * \param[in] rxcall Ptr to the associated Rx call structure. + * + * \post Returns RXGEN_OPCODE (always) + * + */ +int +SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_index, + char **a_name, afs_int32 * a_hosts) +{ + return RXGEN_OPCODE; +} /* SRXAFSCB_GetCellByNum */ diff --git a/src/libafscp/afscp_dir.c b/src/libafscp/afscp_dir.c index d761a0ba7d..2dee41c446 100644 --- a/src/libafscp/afscp_dir.c +++ b/src/libafscp/afscp_dir.c @@ -24,647 +24,726 @@ 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 #include -#include + +#include + +#include + #include #include #include -#include -#include -#include -#include #include "afscp.h" #include "afscp_internal.h" -static int dirmode=DIRMODE_CELL; +static int dirmode = DIRMODE_CELL; -int SetDirMode(int mode) { - - if (mode != DIRMODE_CELL && mode != DIRMODE_DYNROOT) { - afs_errno=EINVAL; - return -1; - } - dirmode=mode; - return 0; +int +afscp_SetDirMode(int mode) +{ + if ((mode != DIRMODE_CELL) && (mode != DIRMODE_DYNROOT)) { + afscp_errno = EINVAL; + return -1; + } + dirmode = mode; + return 0; } /* comparison function for tsearch */ -static int dircompare(const void *a, const void *b) +static int +dircompare(const void *a, const void *b) { - const struct afs_dircache *sa=a,*sb=b; - if (sa->me.fid.Vnode < sb->me.fid.Vnode) return -1; - if (sa->me.fid.Vnode > sb->me.fid.Vnode) return 1; - if (sa->me.fid.Unique < sb->me.fid.Unique) return -1; - if (sa->me.fid.Unique > sb->me.fid.Unique) return 1; - return 0; + const struct afscp_dircache *sa = a, *sb = b; + if (sa->me.fid.Vnode < sb->me.fid.Vnode) + return -1; + if (sa->me.fid.Vnode > sb->me.fid.Vnode) + return 1; + if (sa->me.fid.Unique < sb->me.fid.Unique) + return -1; + if (sa->me.fid.Unique > sb->me.fid.Unique) + return 1; + return 0; } /* make sure the dirstream contains the most up to date directory contents */ -static int _DirUpdate (struct afs_dirstream *d) { - struct AFSFetchStatus s; - int code; - struct afs_volume *v; - struct afs_dircache key, *stored; - void **cached; +static int +_DirUpdate(struct afscp_dirstream *d) +{ + struct AFSFetchStatus s; + int code; + struct afscp_volume *v; + struct afscp_dircache key, *stored; + void **cached; - code=afs_GetStatus(&d->fid, &s); - if (code) - return code; + code = afscp_GetStatus(&d->fid, &s); + if (code != 0) { + return code; + } - if (d->dirbuffer && d->dv == s.DataVersion) - return 0; - v=afs_volumebyid(d->fid.cell, d->fid.fid.Volume); - if (!v) { - afs_errno=ENOENT; - return -1; - } + if (d->dirbuffer && d->dv == s.DataVersion) { + return 0; + } + v = afscp_VolumeById(d->fid.cell, d->fid.fid.Volume); + if (v == NULL) { + afscp_errno = ENOENT; + return -1; + } - memcpy(&key.me, &d->fid, sizeof(struct afs_venusfid)); - cached=tfind(&key, &v->dircache, dircompare); - if (cached) { - stored=*(struct afs_dircache **)cached; - if (d->dv == s.DataVersion) { - d->dirbuffer = stored->dirbuffer; - d->buflen = stored->buflen; - d->dv = stored->dv; - return 0; - } - tdelete(&key, &v->dircache, dircompare); - if (d->dirbuffer != stored->dirbuffer) - free(stored->dirbuffer); - free(stored); - } - if (s.Length > BIGMAXPAGES * AFS_PAGESIZE) { - afs_errno=EFBIG; - return -1; - } - if (d->buflen != s.Length) { - char *new; - if (d->dirbuffer) { - new=realloc(d->dirbuffer, s.Length); - } else { - new=malloc(s.Length); - } - if (new) { - d->dirbuffer=new; - } else { - afs_errno=ENOMEM; - return -1; - } - d->buflen=s.Length; - } + memcpy(&key.me, &d->fid, sizeof(struct afscp_venusfid)); + cached = tfind(&key, &v->dircache, dircompare); + if (cached != NULL) { + stored = *(struct afscp_dircache **)cached; + if (d->dv == s.DataVersion) { + d->dirbuffer = stored->dirbuffer; + d->buflen = stored->buflen; + d->dv = stored->dv; + return 0; + } + tdelete(&key, &v->dircache, dircompare); + if (d->dirbuffer != stored->dirbuffer) + free(stored->dirbuffer); + free(stored); + } + if (s.Length > BIGMAXPAGES * AFS_PAGESIZE) { + afscp_errno = EFBIG; + return -1; + } + if (d->buflen != s.Length) { + char *new; + if (d->dirbuffer) { + new = realloc(d->dirbuffer, s.Length); + } else { + new = malloc(s.Length); + } + if (new != NULL) { + d->dirbuffer = new; + } else { + afscp_errno = ENOMEM; + return -1; + } + d->buflen = s.Length; + } - code=afs_pread(&d->fid, d->dirbuffer, s.Length, 0); - if (code < 0) { - return -1; - } - d->dv=s.DataVersion; - cached=tsearch(&key, &v->dircache, dircompare); - if (cached) { - stored=malloc(sizeof(struct afs_dircache)); - if (stored) { - memcpy(&stored->me, &d->fid, sizeof(struct afs_venusfid)); - stored->buflen=d->buflen; - stored->dirbuffer=d->dirbuffer; - stored->dv=d->dv; - *(struct afs_dircache **)cached=stored; - } else { - tdelete(&key, &v->dircache, dircompare); - } - } - return 0; + code = afscp_PRead(&d->fid, d->dirbuffer, s.Length, 0); + if (code < 0) { + return -1; + } + d->dv = s.DataVersion; + cached = tsearch(&key, &v->dircache, dircompare); + if (cached != NULL) { + stored = malloc(sizeof(struct afscp_dircache)); + if (stored != NULL) { + memcpy(&stored->me, &d->fid, sizeof(struct afscp_venusfid)); + stored->buflen = d->buflen; + stored->dirbuffer = d->dirbuffer; + stored->dv = d->dv; + *(struct afscp_dircache **)cached = stored; + } else { + tdelete(&key, &v->dircache, dircompare); + } + } + return 0; } +static struct DirEntry * +dir_get_entry(struct afscp_dirstream *d, int entry) +{ + struct DirHeader *h = (struct DirHeader *)d->dirbuffer; + /* struct PageHeader *p; */ + struct DirEntry *ret; + /* int fr; */ + int pg, off; -static struct DirEntry *dir_get_entry(struct afs_dirstream *d, int entry) { + pg = entry >> LEPP; + off = entry & (EPP - 1); - struct DirHeader *h=(struct DirHeader *)d->dirbuffer; - struct PageHeader *p; - struct DirEntry *ret; - int fr; - int pg, off; - - - pg=entry >> LEPP; - off=entry & (EPP-1); - - if (pg * AFS_PAGESIZE >= d->buflen) { /* beyond end of file */ - return NULL; - } - if (!off || (!pg && off < DHE + 1)) { /* offset refers to metadata */ - return NULL; - } - if (pg < MAXPAGES && h->alloMap[pg] == EPP) { /* page is empty */ - return NULL; - } - p=(struct PageHeader *)&d->dirbuffer[pg * AFS_PAGESIZE]; - fr=p->freebitmap[off >> 8]; -#if 0 - if ((fr & (1<<(off & 7))) == 0 ) { /* entry isn't allocated */ - return NULL; - } -#endif - - ret=(struct DirEntry *)&d->dirbuffer[pg * AFS_PAGESIZE + 32 * off]; - - return ret; + if (pg * AFS_PAGESIZE >= d->buflen) { /* beyond end of file */ + return NULL; + } + if (!off || (!pg && off < DHE + 1)) { /* offset refers to metadata */ + return NULL; + } + if (pg < MAXPAGES && h->alloMap[pg] == EPP) { /* page is empty */ + return NULL; + } + /* p = (struct PageHeader *)&d->dirbuffer[pg * AFS_PAGESIZE]; */ + /* p is set but not referenced later */ + /* fr = p->freebitmap[off >> 8]; */ + /* fr is set but not referenced later */ + ret = (struct DirEntry *)&d->dirbuffer[pg * AFS_PAGESIZE + 32 * off]; + return ret; } -struct afs_dirstream *afs_opendir(const struct afs_venusfid *fid) { - struct afs_dirstream *ret; - struct AFSFetchStatus s; - int code; +struct afscp_dirstream * +afscp_OpenDir(const struct afscp_venusfid *fid) +{ + struct afscp_dirstream *ret; + struct AFSFetchStatus s; + int code; - code=afs_GetStatus(fid, &s); - if (code) { - return NULL; - } + code = afscp_GetStatus(fid, &s); + if (code != 0) { + return NULL; + } - if (s.FileType != Directory) { - afs_errno=ENOTDIR; - return NULL; - } - ret=malloc(sizeof(struct afs_dirstream)); - if (!ret) { - afs_errno=ENOMEM; - return NULL; - } - memset(ret,0,sizeof(struct afs_dirstream)); - memmove(&ret->fid, fid, sizeof(struct afs_venusfid)); - code=_DirUpdate(ret); - if (code < 0) { - afs_closedir(ret); - return NULL; - } - ret->hashent=-1; - ret->entry=0; - return ret; + if (s.FileType != Directory) { + afscp_errno = ENOTDIR; + return NULL; + } + ret = malloc(sizeof(struct afscp_dirstream)); + if (ret == NULL) { + afscp_errno = ENOMEM; + return NULL; + } + memset(ret, 0, sizeof(struct afscp_dirstream)); + memmove(&ret->fid, fid, sizeof(struct afscp_venusfid)); + code = _DirUpdate(ret); + if (code < 0) { + afscp_CloseDir(ret); + return NULL; + } + ret->hashent = -1; + ret->entry = 0; + + return ret; } -struct afs_dirent *afs_readdir(struct afs_dirstream *d) { - struct DirHeader *h=(struct DirHeader *)d->dirbuffer; - struct DirEntry *info; - int ent; +struct afscp_dirent * +afscp_ReadDir(struct afscp_dirstream *d) +{ + struct DirHeader *h = (struct DirHeader *)d->dirbuffer; + struct DirEntry *info; + int ent; - ent=d->entry; - while (ent == 0 && d->hashent < NHASHENT-1) { - d->hashent++; - ent=ntohs(h->hashTable[d->hashent]); - } - if (ent == 0) { - afs_errno=0; - return NULL; - } - info=dir_get_entry(d, ent); - if (!info) { - afs_errno=0; - return NULL; - } - d->ret.vnode=ntohl(info->fid.vnode); - d->ret.unique=ntohl(info->fid.vunique); - strcpy(d->ret.name, info->name); /* guaranteed to be NULL terminated? */ - d->entry=ntohs(info->next); + ent = d->entry; + while (ent == 0 && d->hashent < NHASHENT - 1) { + d->hashent++; + ent = ntohs(h->hashTable[d->hashent]); + } + if (ent == 0) { + afscp_errno = 0; + return NULL; + } + info = dir_get_entry(d, ent); + if (info == NULL) { + afscp_errno = 0; + return NULL; + } + d->ret.vnode = ntohl(info->fid.vnode); + d->ret.unique = ntohl(info->fid.vunique); + strlcpy(d->ret.name, info->name, sizeof(d->ret.name)); /* guaranteed to be NULL terminated? */ + d->entry = ntohs(info->next); - return &d->ret; + return &d->ret; } /* as it calls _DirUpdate, this may corrupt any previously returned dirent's */ -int afs_rewinddir(struct afs_dirstream *d) { - _DirUpdate(d); - d->hashent=-1; - d->entry=0; - return 0; -} -int afs_closedir(struct afs_dirstream *d) { - free(d); - return 0; -} - -static int namehash(const char *name) +int +afscp_RewindDir(struct afscp_dirstream *d) { - int hval, tval; - - hval=0; - while (*name) hval = (hval * 173) + *name++; - tval = hval & (NHASHENT - 1); - return tval ? - (hval < 0 ? NHASHENT - tval : tval) - : 0; + _DirUpdate(d); + d->hashent = -1; + d->entry = 0; + return 0; } - -struct afs_venusfid *DirLookup(struct afs_dirstream *d, const char *name) { - int fid[3]; - int code; - int hval, entry; - struct DirHeader *h=(struct DirHeader *)d->dirbuffer; - struct DirEntry *info; - - code=_DirUpdate(d); - if (code) - return NULL; - hval=namehash(name); - entry=ntohs(h->hashTable[hval]); - - while (entry) { - info=dir_get_entry(d, entry); - if (!info) { - afs_errno=EIO; - return NULL; - } - if (!strcmp(info->name, name)) - break; - entry=ntohs(info->next); - } - if (entry) { - return makefid(d->fid.cell, d->fid.fid.Volume, - ntohl(info->fid.vnode), - ntohl(info->fid.vunique)); - } else { - afs_errno=ENOENT; - return NULL; - } +int +afscp_CloseDir(struct afscp_dirstream *d) +{ + free(d); + return 0; } -struct afs_venusfid *ResolveName(const struct afs_venusfid *dir, const char *name) { - struct afs_venusfid *ret; - struct afs_dirstream *d; +static int +namehash(const char *name) +{ + int hval, tval; - d=afs_opendir(dir); - if (!d) - return NULL; - ret=DirLookup(d, name); - afs_closedir(d); - return ret; + hval = 0; + while (*name != '\0') + hval = (hval * 173) + *name++; + tval = hval & (NHASHENT - 1); + return tval ? (hval < 0 ? NHASHENT - tval : tval) + : 0; } -static int gettoproot(struct afs_cell *cell, char *p, char **q, struct afs_venusfid **root) { - struct afs_volume *rootvol; - char *r; +struct afscp_venusfid * +afscp_DirLookup(struct afscp_dirstream *d, const char *name) +{ + int code; + int hval, entry; + struct DirHeader *h = (struct DirHeader *)d->dirbuffer; + struct DirEntry *info; - if (dirmode == DIRMODE_DYNROOT && !strcmp(p, "/afs")) { - afs_errno=EINVAL; - return 1; - } - if (!strncmp(p,"/afs",4)) { - afscp_dprintf(("gettoproot: path is absolute\n")); - p=&p[5]; - while (*p == '/') p++; - if (dirmode == DIRMODE_DYNROOT) { - int voltype; + code = _DirUpdate(d); + if (code != 0) { + return NULL; + } + hval = namehash(name); + entry = ntohs(h->hashTable[hval]); + + while (entry != 0) { + info = dir_get_entry(d, entry); + if (info == NULL) { + afscp_errno = EIO; + return NULL; + } + if (strcmp(info->name, name) == 0) + break; + entry = ntohs(info->next); + } + if (entry != 0) { + return afscp_MakeFid(d->fid.cell, d->fid.fid.Volume, + ntohl(info->fid.vnode), + ntohl(info->fid.vunique)); + } else { + afscp_errno = ENOENT; + return NULL; + } +} + +struct afscp_venusfid * +afscp_ResolveName(const struct afscp_venusfid *dir, const char *name) +{ + struct afscp_venusfid *ret; + struct afscp_dirstream *d; + + d = afscp_OpenDir(dir); + if (d == NULL) { + return NULL; + } + ret = afscp_DirLookup(d, name); + afscp_CloseDir(d); + return ret; +} + +static int +gettoproot(struct afscp_cell *cell, char *p, char **q, + struct afscp_venusfid **root) +{ + struct afscp_volume *rootvol; + char *r; + + if (dirmode == DIRMODE_DYNROOT && (strcmp(p, "/afs") == 0)) { + afscp_errno = EINVAL; + return 1; + } + if (strncmp(p, "/afs", 4) == 0) { + afs_dprintf(("gettoproot: path is absolute\n")); + p = &p[5]; + while (*p == '/') + p++; + if (dirmode == DIRMODE_DYNROOT) { + int voltype; retry_dot: - voltype = VOLTYPE_RO; - if (*p == '.') { - p++; - voltype=VOLTYPE_RW; - } - if (*p == '/') { - while (*p == '/') p++; - goto retry_dot; - } - if (*p == '.' || *p == 0) { - afs_errno=EINVAL; - return 1; - } - r=p; - while (*r && *r != '/') r++; - if (!*r) { - afs_errno=ENODEV; - return 1; - } - *r++=0; - *q=r; - afscp_dprintf(("gettoproot: dynroot looking up cell %s\n", p)); - cell=afs_cellbyname(p); - if (!cell) { - afscp_dprintf(("gettoproot: no such cell\n")); - afs_errno=ENODEV; - return 1; - } - rootvol=afs_volumebyname(cell, "root.cell", voltype); - if (!rootvol && voltype == VOLTYPE_RO) - rootvol=afs_volumebyname(cell, "root.cell", VOLTYPE_RW); - } else { - *q=p; - rootvol=afs_volumebyname(cell, "root.afs", VOLTYPE_RO); - if (!rootvol) - rootvol=afs_volumebyname(cell, "root.afs", VOLTYPE_RW); - } - if (!rootvol) - afscp_dprintf(("gettoproot: volume not found\n")); - } else { - afscp_dprintf(("gettoproot: path is relative\n")); - if (p[0] == '/') { - afs_errno=EXDEV; - return 1; - } - rootvol=afs_volumebyname(cell, "root.cell", VOLTYPE_RO); - if (!rootvol) - rootvol=afs_volumebyname(cell, "root.cell", VOLTYPE_RW); - *q=p; - } - if (!rootvol) { afs_errno=ENODEV; return 1;} - *root=makefid(cell, rootvol->id, 1, 1); - return 0; + voltype = ROVOL; + if (*p == '.') { + p++; + voltype = RWVOL; + } + if (*p == '/') { + while (*p == '/') + p++; + goto retry_dot; + } + if (*p == '.' || *p == 0) { + afscp_errno = EINVAL; + return 1; + } + r = p; + while (*r && *r != '/') + r++; + if (!*r) { + afscp_errno = ENODEV; + return 1; + } + *r++ = 0; + *q = r; + afs_dprintf(("gettoproot: dynroot looking up cell %s\n", p)); + cell = afscp_CellByName(p, NULL); + if (cell == NULL) { + afs_dprintf(("gettoproot: no such cell\n")); + afscp_errno = ENODEV; + return 1; + } + rootvol = afscp_VolumeByName(cell, "root.cell", voltype); + if (!rootvol && voltype == ROVOL) + rootvol = afscp_VolumeByName(cell, "root.cell", RWVOL); + } else { + *q = p; + rootvol = afscp_VolumeByName(cell, "root.afs", ROVOL); + if (!rootvol) + rootvol = afscp_VolumeByName(cell, "root.afs", RWVOL); + } + if (!rootvol) + afs_dprintf(("gettoproot: volume not found\n")); + } else { + afs_dprintf(("gettoproot: path is relative\n")); + if (p[0] == '/') { + afscp_errno = EXDEV; + return 1; + } + rootvol = afscp_VolumeByName(cell, "root.cell", ROVOL); + if (!rootvol) + rootvol = afscp_VolumeByName(cell, "root.cell", RWVOL); + *q = p; + } + if (rootvol == NULL) { + afscp_errno = ENODEV; + return 1; + } + *root = afscp_MakeFid(cell, rootvol->id, 1, 1); + return 0; } -static int getvolumeroot(struct afs_cell *cell, int voltype, const char *vname, struct afs_venusfid **root) { - struct afs_volume *vol; - vol=afs_volumebyname(cell, vname, voltype); - if (!vol && voltype == VOLTYPE_RO) - vol=afs_volumebyname(cell, vname, VOLTYPE_RW); - if (!vol) { afs_errno=ENODEV; return 1;} - *root=makefid(cell, vol->id, 1, 1); - return 0; -} - -typedef struct fidstack_s +static int +getvolumeroot(struct afscp_cell *cell, int voltype, const char *vname, + struct afscp_venusfid **root) { - int alloc; - int count; - struct afs_venusfid ** entries; + struct afscp_volume *vol; + vol = afscp_VolumeByName(cell, vname, voltype); + if (!vol && voltype == ROVOL) + vol = afscp_VolumeByName(cell, vname, RWVOL); + if (vol == NULL) { + afscp_errno = ENODEV; + return 1; + } + *root = afscp_MakeFid(cell, vol->id, 1, 1); + return 0; +} + +typedef struct fidstack_s { + int alloc; + int count; + struct afscp_venusfid **entries; } *fidstack; -static fidstack fidstack_alloc() { - fidstack ret; +static fidstack +fidstack_alloc(void) +{ + fidstack ret; - ret=malloc(sizeof(struct fidstack_s)); - if (!ret) { - afs_errno=ENOMEM; - return NULL; - } - ret->alloc=10; - ret->count=0; - ret->entries=malloc(ret->alloc * sizeof(struct afs_venusfid *)); - if (!ret->entries) { - free(ret); - afs_errno=ENOMEM; - return NULL; - } - return ret; + ret = malloc(sizeof(struct fidstack_s)); + if (ret == NULL) { + afscp_errno = ENOMEM; + return NULL; + } + ret->alloc = 10; + ret->count = 0; + ret->entries = malloc(ret->alloc * sizeof(struct afscp_venusfid *)); + if (ret->entries == NULL) { + free(ret); + afscp_errno = ENOMEM; + return NULL; + } + return ret; } -static void fidstack_push(fidstack s, struct afs_venusfid *entry) { - struct afs_venusfid **new; - if (s->count >= s->alloc) { - new=realloc(s->entries, (s->alloc + 10) * - sizeof(struct afs_venusfid *)); - if (!new) - return; - s->entries=new; - s->alloc += 10; - } - s->entries[s->count++]=entry; - return; +static void +fidstack_push(fidstack s, struct afscp_venusfid *entry) +{ + struct afscp_venusfid **new; + if (s->count >= s->alloc) { + new = realloc(s->entries, (s->alloc + 10) * + sizeof(struct afscp_venusfid *)); + if (new == NULL) { + return; + } + s->entries = new; + s->alloc += 10; + } + s->entries[s->count++] = entry; + return; } -static struct afs_venusfid *fidstack_pop(fidstack s) { - if (s->count) - return s->entries[-- s->count]; - return NULL; +static struct afscp_venusfid * +fidstack_pop(fidstack s) +{ + if (s->count) + return s->entries[--s->count]; + return NULL; } -static void fidstack_free(fidstack s) { - int i; +static void +fidstack_free(fidstack s) +{ + int i; - for (i=0;icount;i++) - free(s->entries[i]); - free (s->entries); - free(s); + for (i = 0; i < s->count; i++) + free(s->entries[i]); + free(s->entries); + free(s); } -static struct afs_venusfid *_ResolvePath(const struct afs_venusfid *, fidstack, char *, int); +static struct afscp_venusfid *_ResolvePath(const struct afscp_venusfid *, + fidstack, char *, int); -static struct afs_venusfid *HandleLink(struct afs_venusfid *in, const struct afs_venusfid *parent, fidstack fids, int follow, - const struct AFSFetchStatus *s, int terminal) { - char *linkbuf, *linkbufq; - struct afs_cell *cell; - struct afs_volume *v; - struct afs_venusfid *root,*ret; - int voltype; - int code; - if ((s->UnixModeBits & 0111) && - (follow == 0) && - terminal) { /* normal link */ - return in; - } - linkbuf=malloc(s->Length + 1); - code=afs_pread(in, linkbuf, s->Length, 0); - if (code < 0) { - free(linkbuf); - free(in); - return NULL; - } - if (code != s->Length) { - afs_errno=EIO; - free(linkbuf); - free(in); - return NULL; - } - linkbuf[s->Length]=0; - if (s->UnixModeBits & 0111) { /* normal link */ - afscp_dprintf(("Recursing on symlink %s...\n", linkbuf)); - if (linkbuf[0] == '/') { - if (gettoproot(in->cell, linkbuf, &linkbufq, &root)) { - free(linkbuf); - free(in); - return NULL; - } - free(in); - ret=_ResolvePath(root, 0, linkbufq, 0); - free(root); - } else { - free(in); - ret=_ResolvePath(parent, fids, linkbuf, 0); - } - - free(linkbuf); - - } else { /* mountpoint */ - afscp_dprintf(("EvalMountPoint %s...\n", linkbuf)); - linkbufq=strchr(linkbuf, ':'); - cell=in->cell; - v=afs_volumebyid(cell, in->fid.Volume); - free(in); - if (!v) { - free(linkbuf); - afs_errno=ENODEV; - return NULL; - } - voltype=v->voltype; - if (linkbuf[0] == '%') - voltype=VOLTYPE_RW; - if (!linkbufq) { - linkbufq=linkbuf+1; - } else { - *linkbufq++ = 0; - cell=afs_cellbyname(linkbuf+1); - if (linkbuf[0] != '%') - voltype=VOLTYPE_RO; - } - if (!cell) { - free(linkbuf); - afs_errno=ENODEV; - return NULL; - } - if (strlen(linkbufq) < 2) { - free(linkbuf); - afs_errno=ENODEV; - return NULL; - } - linkbufq[strlen(linkbufq)-1]=0; /* eliminate trailer */ - if (getvolumeroot(cell, voltype, linkbufq, &ret)) { - free(linkbuf); - return NULL; - } - free(linkbuf); - } - return ret; +static struct afscp_venusfid * +afscp_HandleLink(struct afscp_venusfid *in, + const struct afscp_venusfid *parent, fidstack fids, + int follow, const struct AFSFetchStatus *s, int terminal) +{ + char *linkbuf, *linkbufq; + struct afscp_cell *cell; + struct afscp_volume *v; + struct afscp_venusfid *root, *ret; + int voltype; + int code; + ssize_t len; + if ((s->UnixModeBits & 0111) && (follow == 0) && terminal) { /* normal link */ + return in; + } + linkbuf = malloc(s->Length + 1); + code = afscp_PRead(in, linkbuf, s->Length, 0); + if (code < 0) { + free(linkbuf); + free(in); + return NULL; + } + if (code != s->Length) { + afscp_errno = EIO; + free(linkbuf); + free(in); + return NULL; + } + linkbuf[s->Length] = 0; + if (s->UnixModeBits & 0111) { /* normal link */ + afs_dprintf(("Recursing on symlink %s...\n", linkbuf)); + if (linkbuf[0] == '/') { + if (gettoproot(in->cell, linkbuf, &linkbufq, &root)) { + free(linkbuf); + free(in); + return NULL; + } + free(in); + ret = _ResolvePath(root, 0, linkbufq, 0); + free(root); + } else { + free(in); + ret = _ResolvePath(parent, fids, linkbuf, 0); + } + free(linkbuf); + } else { /* mountpoint */ + afs_dprintf(("EvalMountPoint %s...\n", linkbuf)); + linkbufq = strchr(linkbuf, ':'); + cell = in->cell; + v = afscp_VolumeById(cell, in->fid.Volume); + free(in); + if (v == NULL) { + free(linkbuf); + afscp_errno = ENODEV; + return NULL; + } + voltype = v->voltype; + if (linkbuf[0] == '%') + voltype = RWVOL; + if (linkbufq == NULL) { + linkbufq = linkbuf + 1; + } else { + *linkbufq++ = 0; + cell = afscp_CellByName(linkbuf + 1, NULL); + if (linkbuf[0] != '%') + voltype = ROVOL; + } + if (cell == NULL) { + free(linkbuf); + afscp_errno = ENODEV; + return NULL; + } + len = strnlen(linkbufq, s->Length + 1); + if (len < 2) { + free(linkbuf); + afscp_errno = ENODEV; + return NULL; + } + len = strnlen(linkbufq, s->Length + 1); + linkbufq[len - 1] = 0; /* eliminate trailer */ + if (getvolumeroot(cell, voltype, linkbufq, &ret)) { + free(linkbuf); + return NULL; + } + free(linkbuf); + } + return ret; } -static struct afs_venusfid *_ResolvePath(const struct afs_venusfid *start, - fidstack infids, char *path, - int follow) { - struct afs_venusfid *ret,*cwd,*parent; - struct AFSFetchStatus s; - char *p,*q; - int code; - int linkcount; - fidstack fids; +static struct afscp_venusfid * +_ResolvePath(const struct afscp_venusfid *start, fidstack infids, + char *path, int follow) +{ + struct afscp_venusfid *ret, *cwd; + struct AFSFetchStatus s; + char *p, *q; + int code; + int linkcount; + fidstack fids; - p=path; - ret=cwd=dupfid(start); - fids=infids; - if (!fids) - fids=fidstack_alloc(); - if (!fids) - return NULL; + p = path; + ret = cwd = afscp_DupFid(start); + fids = infids; + if (fids == NULL) + fids = fidstack_alloc(); + if (fids == NULL) { + return NULL; + } - while (p && *p) { - q=strchr(p, '/'); - if (q) *q++=0; - if (!strcmp(p,".")) { - } else if (!strcmp(p,"..")) { - ret=fidstack_pop(fids); - if (!ret) - ret=cwd; - else - free(cwd); - } else { - ret=ResolveName(cwd, p); - if (!ret) { - afscp_dprintf(("Lookup %s in %lu.%lu.%lu failed\n", p, cwd->fid.Volume, cwd->fid.Vnode, cwd->fid.Unique)); - free(cwd); - if (!infids) - fidstack_free(fids); - return NULL; + while (p && *p) { + q = strchr(p, '/'); + if (q) + *q++ = 0; + if (strcmp(p, ".") == 0) { + /* do nothing */ + } else if (strcmp(p, "..") == 0) { + ret = fidstack_pop(fids); + if (ret == NULL) + ret = cwd; + else + free(cwd); + } else { + ret = afscp_ResolveName(cwd, p); + if (ret == NULL) { + afs_dprintf(("Lookup %s in %lu.%lu.%lu failed\n", p, + cwd->fid.Volume, cwd->fid.Vnode, + cwd->fid.Unique)); + free(cwd); + if (infids == NULL) + fidstack_free(fids); + return NULL; + } + afs_dprintf(("Lookup %s in %lu.%lu.%lu->%lu.%lu.%lu\n", p, + cwd->fid.Volume, cwd->fid.Vnode, cwd->fid.Unique, + ret->fid.Volume, ret->fid.Vnode, ret->fid.Unique)); + linkcount = 0; - } - afscp_dprintf(("Lookup %s in %lu.%lu.%lu->%lu.%lu.%lu\n", p, cwd->fid.Volume, cwd->fid.Vnode, cwd->fid.Unique, ret->fid.Volume, ret->fid.Vnode, ret->fid.Unique)); - linkcount=0; + retry: + if ((ret->fid.Vnode & 1) == 0) { /* not a directory; check for link */ + code = afscp_GetStatus(ret, &s); + if (code != 0) { + if (infids == NULL) + fidstack_free(fids); + free(cwd); + free(ret); + return NULL; + } + if (s.FileType == SymbolicLink) { + if (linkcount++ > 5) { + afscp_errno = ELOOP; + if (infids == NULL) + fidstack_free(fids); + free(cwd); + free(ret); + return NULL; + } + ret = + afscp_HandleLink(ret, cwd, fids, follow, &s, + (q == NULL)); + if (ret == NULL) { + free(cwd); + if (infids == NULL) + fidstack_free(fids); + return NULL; + } + afs_dprintf((" ....-> %lu.%lu.%lu\n", ret->fid.Volume, + ret->fid.Vnode, ret->fid.Unique)); + goto retry; + } else { + if (q != NULL) { + afscp_errno = ENOTDIR; + free(cwd); + free(ret); + if (infids == NULL) + fidstack_free(fids); + return NULL; + } + } + } + fidstack_push(fids, cwd); + } + cwd = ret; - retry: - if ((ret->fid.Vnode & 1) == 0) { /* not a directory; check for link */ - code=afs_GetStatus(ret, &s); - if (code) { - if (!infids) - fidstack_free(fids); - free(cwd); - free(ret); - return NULL; - } - if (s.FileType == SymbolicLink) { - if (linkcount++ > 5) { - afs_errno=ELOOP; - if (!infids) - fidstack_free(fids); - free(cwd); - free(ret); - return NULL; - } - ret=HandleLink(ret, cwd, fids, follow, &s, (q==NULL)); - if (!ret) { - free(cwd); - if (!infids) - fidstack_free(fids); - return NULL; - } - afscp_dprintf((" ....-> %lu.%lu.%lu\n", ret->fid.Volume, ret->fid.Vnode, ret->fid.Unique)); - goto retry; - } else { - if (q) { - afs_errno=ENOTDIR; - free(cwd); - free(ret); - if (!infids) - fidstack_free(fids); - return NULL; - } - } - } - fidstack_push(fids,cwd); - } - cwd=ret; - - if (q) - while (*q == '/') - q++; - p=q; - } - if (!infids) - fidstack_free(fids); - return ret; -} -/* 3 cases: - begins with /afs: start in root.afs of cell or home cell - else begins with /: error - else start in root.cell of cell or home cell -*/ -struct afs_venusfid *ResolvePath(const char *path) { - struct afs_venusfid *root,*ret; - struct afs_cell *cell; - - char *p,*q; - /* so we can modify the string */ - p=strdup(path); - if (!p) { - afs_errno=ENOMEM; - return NULL; - } - cell=afs_defaultcell(); - if (!cell) { afs_errno=EINVAL; return NULL;} - if (gettoproot(cell, p, &q, &root)) { - free(p); - return NULL; - } - if (q && *q) { - ret=_ResolvePath(root, 0, q, 1); - free(root); - } else - ret=root; - free(p); - return ret; + while ((q != NULL) && (*q == '/')) + q++; + p = q; + } + if (infids == NULL) + fidstack_free(fids); + return ret; } -struct afs_venusfid *ResolvePath2(const struct afs_volume *v, const char *path) { - struct afs_venusfid *root,*ret; - - char *p,*q; - /* so we can modify the string */ - p=strdup(path); - if (!p) { - afs_errno=ENOMEM; - return NULL; - } - root=makefid(v->cell, v->id, 1,1); - while (*p == '/') p++; - if (*p) { - ret=_ResolvePath(root, 0, p, 1); - free(root); - } else - ret=root; - free(p); - return ret; +/*! + * Resolve a path to a FID starting from the root volume + * + * \param[in] path full path + * + * \post Returns a venusfid representing the final element of path + * + * \note There are three cases: + * (1) begins with /afs: start in root.afs of cell or home cell + * (2) else begins with /: error + * (3) else start in root.cell of cell or home cell + */ +struct afscp_venusfid * +afscp_ResolvePath(const char *path) +{ + struct afscp_venusfid *root, *ret; + struct afscp_cell *cell; + int code; + char *p, *q; + p = strdup(path); /* so we can modify the string */ + if (p == NULL) { + afscp_errno = ENOMEM; + return NULL; + } + cell = afscp_DefaultCell(); + if (cell == NULL) { + afscp_errno = EINVAL; + return NULL; + } + code = gettoproot(cell, p, &q, &root); + if (code != 0) { + free(p); + return NULL; + } + if (q && *q) { + ret = _ResolvePath(root, 0, q, 1); + free(root); + } else + ret = root; + free(p); + return ret; +} + +/*! + * Resolve a path to a FID starting from the given volume + * + * \param[in] v volume structure containing id and cell info + * \param[in] path path relative to volume v + * + * \post Returns a venusfid representing the final element of path + */ +struct afscp_venusfid * +afscp_ResolvePathFromVol(const struct afscp_volume *v, const char *path) +{ + struct afscp_venusfid *root, *ret; + char *p; + + /* so we can modify the string */ + p = strdup(path); + if (p == NULL) { + afscp_errno = ENOMEM; + return NULL; + } + root = afscp_MakeFid(v->cell, v->id, 1, 1); + while (*p == '/') + p++; + if (*p != '\0') { + ret = _ResolvePath(root, 0, p, 1); + free(root); + } else + ret = root; + free(p); + return ret; } diff --git a/src/libafscp/afscp_dirops.c b/src/libafscp/afscp_dirops.c index b2fa2e782e..3fb08f8cd3 100644 --- a/src/libafscp/afscp_dirops.c +++ b/src/libafscp/afscp_dirops.c @@ -24,220 +24,248 @@ 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 #include -#include + +#include + #include #include #include -#include -#include -#include -#include #include "afscp.h" #include "afscp_internal.h" +int +afscp_CreateFile(const struct afscp_venusfid *dir, char *name, + struct AFSStoreStatus *sst, struct afscp_venusfid **ret) +{ + int code, i, j; + struct AFSFid df = dir->fid; + struct afscp_volume *vol; + struct AFSFetchStatus dfst, fst; + struct AFSVolSync vs; + struct AFSCallBack cb; + struct AFSFid ff; + struct afscp_server *server; + struct rx_connection *c; + time_t now; -int afs_CreateFile(const struct afs_venusfid *dir, char *name, - struct AFSStoreStatus *sst, - struct afs_venusfid **ret) { - int code, i, j; - struct AFSFid df = dir->fid; - struct afs_volume *vol; - struct AFSFetchStatus dfst, fst; - struct AFSVolSync vs; - struct AFSCallBack cb; - struct AFSFid ff; - struct afs_volume *volume; - struct afs_server *server; - struct rx_call *c; - - vol=afs_volumebyid(dir->cell, dir->fid.Volume); - if (!vol) { - afs_errno=ENOENT; - return -1; - } - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(vol->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_CreateFile(server->conns[j], &df, name, sst, &ff, - &fst, &dfst, &cb, &vs); - if (code >= 0) - break; - } + if (dir == NULL || name == NULL || sst == NULL) { + fprintf(stderr, + "afscp_CreateFile called with NULL args, cannot continue\n"); + return -1; } - if (code >= 0) - break; - } - if (code) { - _StatInvalidate(dir); - afs_errno=code; - return -1; - } - _StatStuff(dir, &dfst); - AddCallBack(server, &ff, &fst, &cb); - if (ret) - *ret=makefid(vol->cell, ff.Volume, ff.Vnode, ff.Unique); - return 0; + vol = afscp_VolumeById(dir->cell, dir->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; + } + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + c = afscp_ServerConnection(server, j); + if (c == NULL) { + break; + } + time(&now); + code = RXAFS_CreateFile(c, &df, name, sst, &ff, + &fst, &dfst, &cb, &vs); + if (code >= 0) { + break; + } + } + } + if (code >= 0) { + break; + } + } + if (code != 0) { + _StatInvalidate(dir); + afscp_errno = code; + return -1; + } + _StatStuff(dir, &dfst); + afscp_AddCallBack(server, &ff, &fst, &cb, now); + if (ret != NULL) + *ret = afscp_MakeFid(vol->cell, ff.Volume, ff.Vnode, ff.Unique); + return 0; } -int afs_MakeDir(const struct afs_venusfid *dir, char *name, - struct AFSStoreStatus *sst, - struct afs_venusfid **ret) { - int code, i, j; - struct AFSFid df = dir->fid; - struct afs_volume *vol; - struct AFSFetchStatus dfst, fst; - struct AFSVolSync vs; - struct AFSCallBack cb; - struct AFSFid ff; - struct afs_volume *volume; - struct afs_server *server; +int +afscp_MakeDir(const struct afscp_venusfid *dir, char *name, + struct AFSStoreStatus *sst, struct afscp_venusfid **ret) +{ + int code, i, j; + struct AFSFid df = dir->fid; + struct afscp_volume *vol; + struct AFSFetchStatus dfst, fst; + struct AFSVolSync vs; + struct AFSCallBack cb; + struct AFSFid ff; + struct afscp_server *server; + struct rx_connection *c; + time_t now; - vol=afs_volumebyid(dir->cell, dir->fid.Volume); - if (!vol) { - afs_errno=ENOENT; - return -1; - } - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(vol->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_MakeDir(server->conns[j], &df, name, sst, &ff, - &fst, &dfst, &cb, &vs); - if (code >= 0) - break; - } + vol = afscp_VolumeById(dir->cell, dir->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; } - if (code >= 0) - break; - } - if (code) { - _StatInvalidate(dir); - afs_errno=code; - return -1; - } - _StatStuff(dir, &dfst); - AddCallBack(server, &ff, &fst, &cb); - if (ret) - *ret=makefid(vol->cell, ff.Volume, ff.Vnode, ff.Unique); - return 0; + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + c = afscp_ServerConnection(server, j); + if (c == NULL) + break; + time(&now); + code = RXAFS_MakeDir(c, &df, name, sst, &ff, + &fst, &dfst, &cb, &vs); + if (code >= 0) + break; + } + } + if (code >= 0) + break; + } + if (code != 0) { + _StatInvalidate(dir); + afscp_errno = code; + return -1; + } + _StatStuff(dir, &dfst); + afscp_AddCallBack(server, &ff, &fst, &cb, now); + if (ret != NULL) + *ret = afscp_MakeFid(vol->cell, ff.Volume, ff.Vnode, ff.Unique); + return 0; } -int afs_Symlink(const struct afs_venusfid *dir, char *name, - char *target, - struct AFSStoreStatus *sst) { - int code, i, j; - struct AFSFid df = dir->fid; - struct afs_volume *vol; - struct AFSFetchStatus dfst, fst; - struct AFSVolSync vs; - struct AFSCallBack cb; - struct AFSFid ff; - struct afs_volume *volume; - struct afs_server *server; +int +afscp_Symlink(const struct afscp_venusfid *dir, char *name, + char *target, struct AFSStoreStatus *sst) +{ + int code, i, j; + struct AFSFid df = dir->fid; + struct afscp_volume *vol; + struct AFSFetchStatus dfst, fst; + struct AFSVolSync vs; + struct AFSFid ff; + struct afscp_server *server; + struct rx_connection *c; - vol=afs_volumebyid(dir->cell, dir->fid.Volume); - if (!vol) { - afs_errno=ENOENT; - return -1; - } - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(vol->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_Symlink(server->conns[j], &df, name, target, sst, &ff, - &fst, &dfst, &vs); - if (code >= 0) - break; - } + vol = afscp_VolumeById(dir->cell, dir->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; } - if (code >= 0) - break; - } - if (code) { - _StatInvalidate(dir); - afs_errno=code; - return -1; - } - _StatStuff(dir, &dfst); - return 0; + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + c = afscp_ServerConnection(server, j); + if (c == NULL) + break; + code = RXAFS_Symlink(c, &df, name, target, sst, + &ff, &fst, &dfst, &vs); + if (code >= 0) + break; + } + } + if (code >= 0) + break; + } + if (code != 0) { + _StatInvalidate(dir); + afscp_errno = code; + return -1; + } + _StatStuff(dir, &dfst); + return 0; } -int afs_RemoveFile(const struct afs_venusfid *dir, char *name) { - int code, i, j; - struct AFSFid df = dir->fid; - struct afs_volume *vol; - struct AFSFetchStatus dfst; - struct AFSVolSync vs; - struct AFSCallBack cb; - struct afs_volume *volume; - struct afs_server *server; +int +afscp_RemoveFile(const struct afscp_venusfid *dir, char *name) +{ + int code, i, j; + struct AFSFid df = dir->fid; + struct afscp_volume *vol; + struct AFSFetchStatus dfst; + struct AFSVolSync vs; + struct afscp_server *server; + struct rx_connection *c; - vol=afs_volumebyid(dir->cell, dir->fid.Volume); - if (!vol) { - afs_errno=ENOENT; - return -1; - } - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(vol->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_RemoveFile(server->conns[j], &df, name, &dfst, &vs); - if (code >= 0) - break; - } + vol = afscp_VolumeById(dir->cell, dir->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; } - if (code >= 0) - break; - } - if (code) { - _StatInvalidate(dir); - afs_errno=code; - return -1; - } - _StatStuff(dir, &dfst); - return 0; + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + c = afscp_ServerConnection(server, j); + if (c == NULL) + break; + code = RXAFS_RemoveFile(c, &df, name, &dfst, &vs); + if (code >= 0) + break; + } + } + if (code >= 0) + break; + } + if (code != 0) { + _StatInvalidate(dir); + afscp_errno = code; + return -1; + } + _StatStuff(dir, &dfst); + return 0; } -int afs_RemoveDir(const struct afs_venusfid *dir, char *name) { - int code, i, j; - struct AFSFid df = dir->fid; - struct afs_volume *vol; - struct AFSFetchStatus dfst; - struct AFSVolSync vs; - struct AFSCallBack cb; - struct afs_volume *volume; - struct afs_server *server; +int +afscp_RemoveDir(const struct afscp_venusfid *dir, char *name) +{ + int code, i, j; + struct AFSFid df = dir->fid; + struct afscp_volume *vol; + struct AFSFetchStatus dfst; + struct AFSVolSync vs; + struct afscp_server *server; + struct rx_connection *c; - vol=afs_volumebyid(dir->cell, dir->fid.Volume); - if (!vol) { - afs_errno=ENOENT; - return -1; - } - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(vol->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_RemoveDir(server->conns[j], &df, name, &dfst, &vs); - if (code >= 0) - break; - } + vol = afscp_VolumeById(dir->cell, dir->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; } - if (code >= 0) - break; - } - if (code) { - _StatInvalidate(dir); - afs_errno=code; - return -1; - } - _StatStuff(dir, &dfst); - return 0; + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + c = afscp_ServerConnection(server, j); + if (c == NULL) + break; + code = RXAFS_RemoveDir(c, &df, name, &dfst, &vs); + if (code >= 0) + break; + } + } + if (code >= 0) + break; + } + if (code != 0) { + _StatInvalidate(dir); + afscp_errno = code; + return -1; + } + _StatStuff(dir, &dfst); + return 0; } diff --git a/src/libafscp/afscp_fid.c b/src/libafscp/afscp_fid.c index a85fde2ee5..536f8f1fdc 100644 --- a/src/libafscp/afscp_fid.c +++ b/src/libafscp/afscp_fid.c @@ -24,217 +24,255 @@ 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 #include -#include + +#include + +#include + #include #include -#include -#include -#include -#include -#include -#include #include "afscp.h" #include "afscp_internal.h" -struct afs_venusfid *makefid(struct afs_cell *cell, afs_uint32 volume, - afs_uint32 vnode, afs_uint32 unique) +/* + * Allocate and populate an afscp_venusfid struct from component parts + */ +struct afscp_venusfid * +afscp_MakeFid(struct afscp_cell *cell, afs_uint32 volume, + afs_uint32 vnode, afs_uint32 unique) { - struct afs_venusfid *ret; + struct afscp_venusfid *ret; - if (!cell) - return NULL; - ret=malloc(sizeof(struct afs_venusfid)); - if (!ret) { - afs_errno=errno; - return NULL; - } - ret->cell=cell; - ret->fid.Volume=volume; - ret->fid.Vnode=vnode; - ret->fid.Unique=unique; - return ret; + if (cell == NULL) { + return NULL; + } + ret = malloc(sizeof(struct afscp_venusfid)); + if (ret == NULL) { + afscp_errno = errno; + return NULL; + } + ret->cell = cell; + ret->fid.Volume = volume; + ret->fid.Vnode = vnode; + ret->fid.Unique = unique; + return ret; } -struct afs_venusfid *dupfid(const struct afs_venusfid *in) +/* + * Duplicate an existing afscp_venusfid struct + */ +struct afscp_venusfid * +afscp_DupFid(const struct afscp_venusfid *in) { - struct afs_venusfid *ret; + struct afscp_venusfid *ret; - ret=malloc(sizeof(struct afs_venusfid)); - if (!ret) { - afs_errno=errno; - return NULL; - } - ret->cell=in->cell; - ret->fid.Volume=in->fid.Volume; - ret->fid.Vnode=in->fid.Vnode; - ret->fid.Unique=in->fid.Unique; - return ret; + ret = malloc(sizeof(struct afscp_venusfid)); + if (ret == NULL) { + afscp_errno = errno; + return NULL; + } + ret->cell = in->cell; + ret->fid.Volume = in->fid.Volume; + ret->fid.Vnode = in->fid.Vnode; + ret->fid.Unique = in->fid.Unique; + return ret; } - -static int statcompare(const void *a, const void *b) +void +afscp_FreeFid(struct afscp_venusfid *avfp) { - const struct afs_statent *sa=a,*sb=b; - if (sa->me.fid.Vnode < sb->me.fid.Vnode) return -1; - if (sa->me.fid.Vnode > sb->me.fid.Vnode) return 1; - if (sa->me.fid.Unique < sb->me.fid.Unique) return -1; - if (sa->me.fid.Unique > sb->me.fid.Unique) return 1; - return 0; + if (avfp != NULL) + free(avfp); } - -int afs_GetStatus(const struct afs_venusfid *fid, struct AFSFetchStatus *s) +static int +statcompare(const void *a, const void *b) { - struct afs_volume *v; - struct afs_server *server; - struct AFSCallBack cb; - struct AFSVolSync vs; - struct AFSFid tf = fid->fid; - struct afs_statent *stored,key; - void *cached; - - int code,i,j; - - v=afs_volumebyid(fid->cell, fid->fid.Volume); - if (!v) - return -1; - memset(&key, 0, sizeof(key)); - memcpy(&key.me,fid,sizeof(*fid)); - - cached=tfind(&key, &v->statcache, statcompare); - if (cached) { - stored=*(struct afs_statent **)cached; - memmove(s, &stored->status,sizeof(*s)); - afscp_dprintf(("Stat %u.%lu.%lu.%lu returning cached result\n", - fid->cell->id, fid->fid.Volume, fid->fid.Vnode, fid->fid.Unique)); - return 0; - } - - - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(v->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_FetchStatus(server->conns[j], &tf, s, &cb, &vs); - if (!code) { - AddCallBack(server, &fid->fid, s, &cb); /* calls _StatStuff */ - afscp_dprintf(("Stat %u.%" PRIu32 ".%" PRIu32 ".%" PRIu32 " ok: type %" PRId32 " size %" PRId32 "\n", - fid->cell->id, fid->fid.Volume, fid->fid.Vnode, fid->fid.Unique, s->FileType, s->Length)); - return 0; - } - } - } - } - afs_errno=code; - return -1; + const struct afscp_statent *sa = a, *sb = b; + if (sa->me.fid.Vnode < sb->me.fid.Vnode) + return -1; + if (sa->me.fid.Vnode > sb->me.fid.Vnode) + return 1; + if (sa->me.fid.Unique < sb->me.fid.Unique) + return -1; + if (sa->me.fid.Unique > sb->me.fid.Unique) + return 1; + return 0; } +int +afscp_GetStatus(const struct afscp_venusfid *fid, struct AFSFetchStatus *s) +{ + struct afscp_volume *v; + struct afscp_server *server; + struct AFSCallBack cb; + struct AFSVolSync vs; + struct AFSFid tf = fid->fid; + struct afscp_statent *stored, key; + void *cached; + int code, i, j; + time_t now; + v = afscp_VolumeById(fid->cell, fid->fid.Volume); + if (v == NULL) { + return -1; + } + memset(&key, 0, sizeof(key)); + memcpy(&key.me, fid, sizeof(*fid)); -int afs_stat(const struct afs_venusfid *fid, struct stat *s) + cached = tfind(&key, &v->statcache, statcompare); + if (cached != NULL) { + stored = *(struct afscp_statent **)cached; + memmove(s, &stored->status, sizeof(*s)); + afs_dprintf(("Stat %u.%lu.%lu.%lu returning cached result\n", + fid->cell->id, fid->fid.Volume, fid->fid.Vnode, + fid->fid.Unique)); + return 0; + } + + code = ENOENT; + for (i = 0; i < v->nservers; i++) { + server = afscp_ServerByIndex(v->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + time(&now); + code = RXAFS_FetchStatus(server->conns[j], &tf, s, &cb, &vs); + if (code == 0) { + afscp_AddCallBack(server, &fid->fid, s, &cb, now); /* calls _StatStuff */ + afs_dprintf(("Stat %d.%lu.%lu.%lu" + " ok: type %ld size %ld\n", + fid->cell->id, + afs_printable_uint32_lu(fid->fid.Volume), + afs_printable_uint32_lu(fid->fid.Vnode), + afs_printable_uint32_lu(fid->fid.Unique), + afs_printable_int32_ld(s->FileType), + afs_printable_int32_ld(s->Length))); + return 0; + } + } + } + } + afscp_errno = code; + return -1; +} + +int +afscp_Stat(const struct afscp_venusfid *fid, struct stat *s) { - struct AFSFetchStatus status; - int code; + struct AFSFetchStatus status; + int code; - code=afs_GetStatus(fid, &status); - if (code) - return code; - if (status.FileType==File) - s->st_mode=S_IFREG; - else if (status.FileType==Directory) - s->st_mode=S_IFDIR; - else if (status.FileType==SymbolicLink) - s->st_mode=S_IFLNK; - else { - afs_errno=EINVAL; - return -1; - } - s->st_mode |= (status.UnixModeBits & (~S_IFMT)); - s->st_nlink = status.LinkCount; - s->st_size =status.Length; - s->st_uid =status.Owner; - /*s->st_blksize=status.SegSize;*/ - s->st_atime=s->st_mtime=status.ClientModTime; - s->st_ctime=status.ServerModTime; - s->st_gid = status.Group; - return 0; + if (s == NULL || fid == NULL) { + fprintf(stderr, "NULL args given to afscp_Stat, cannot continue\n"); + return -1; + } + + code = afscp_GetStatus(fid, &status); + if (code != 0) { + return code; + } + + if (status.FileType == File) + s->st_mode = S_IFREG; + else if (status.FileType == Directory) + s->st_mode = S_IFDIR; + else if (status.FileType == SymbolicLink) + s->st_mode = S_IFLNK; + else { + afscp_errno = EINVAL; + return -1; + } + s->st_mode |= (status.UnixModeBits & (~S_IFMT)); + s->st_nlink = status.LinkCount; + s->st_size = status.Length; + s->st_uid = status.Owner; + /*s->st_blksize=status.SegSize; */ + s->st_atime = s->st_mtime = status.ClientModTime; + s->st_ctime = status.ServerModTime; + s->st_gid = status.Group; + return 0; } - -int _StatInvalidate(const struct afs_venusfid *fid) { - struct afs_volume *v; - struct afs_statent key; - void **cached; - - v=afs_volumebyid(fid->cell, fid->fid.Volume); - if (!v) - return -1; - memmove(&key.me,fid,sizeof(*fid)); - - cached=tfind(&key, &v->statcache, statcompare); - if (cached) { - free(*cached); - tdelete(&key, &v->statcache, statcompare); - } - return 0; -} - -int _StatStuff(const struct afs_venusfid *fid, const struct AFSFetchStatus *s) { - struct afs_volume *v; - struct afs_statent key, *stored; - void **cached; - - v=afs_volumebyid(fid->cell, fid->fid.Volume); - if (!v) - return -1; - memmove(&key.me,fid,sizeof(*fid)); - - cached=tsearch(&key, &v->statcache, statcompare); - if (cached) { - stored=malloc(sizeof(struct afs_statent)); - if (stored) { - memmove(&stored->me, fid, sizeof(*fid)); - memmove(&stored->status,s,sizeof(*s)); - *(struct afs_statent **)cached=stored; - } else { - tdelete(&key, &v->statcache, statcompare); - } - } - return 0; -} - -int afs_StoreStatus(const struct afs_venusfid *fid, struct AFSStoreStatus *s) +int +_StatInvalidate(const struct afscp_venusfid *fid) { - struct afs_volume *v; - struct afs_server *server; - struct AFSCallBack cb; - struct AFSVolSync vs; - struct AFSFetchStatus fst; - struct AFSFid tf = fid->fid; - int code,i,j; + struct afscp_volume *v; + struct afscp_statent key; + void **cached; - v=afs_volumebyid(fid->cell, fid->fid.Volume); - if (!v) - return -1; + v = afscp_VolumeById(fid->cell, fid->fid.Volume); + if (v == NULL) { + return -1; + } + memmove(&key.me, fid, sizeof(*fid)); - - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(v->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_StoreStatus(server->conns[j], &tf, s, &fst, &vs); - if (!code) { - _StatStuff(fid, &fst); /* calls _StatStuff */ - return 0; - } - } - } - } - afs_errno=code; - return -1; + cached = tfind(&key, &v->statcache, statcompare); + if (cached != NULL) { + free(*cached); + tdelete(&key, &v->statcache, statcompare); + } + return 0; +} + +int +_StatStuff(const struct afscp_venusfid *fid, const struct AFSFetchStatus *s) +{ + struct afscp_volume *v; + struct afscp_statent key, *stored; + void **cached; + + v = afscp_VolumeById(fid->cell, fid->fid.Volume); + if (v == NULL) { + return -1; + } + memmove(&key.me, fid, sizeof(*fid)); + + cached = tsearch(&key, &v->statcache, statcompare); + if (cached != NULL) { + stored = malloc(sizeof(struct afscp_statent)); + if (stored != NULL) { + memmove(&stored->me, fid, sizeof(*fid)); + memmove(&stored->status, s, sizeof(*s)); + *(struct afscp_statent **)cached = stored; + } else { + tdelete(&key, &v->statcache, statcompare); + } + } + return 0; +} + +int +afscp_StoreStatus(const struct afscp_venusfid *fid, struct AFSStoreStatus *s) +{ + struct afscp_volume *v; + struct afscp_server *server; + struct AFSVolSync vs; + struct AFSFetchStatus fst; + struct AFSFid tf = fid->fid; + int code, i, j; + + v = afscp_VolumeById(fid->cell, fid->fid.Volume); + if (v == NULL) { + return -1; + } + + code = ENOENT; + for (i = 0; i < v->nservers; i++) { + server = afscp_ServerByIndex(v->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + code = RXAFS_StoreStatus(server->conns[j], &tf, s, &fst, &vs); + if (code == 0) { + _StatStuff(fid, &fst); /* calls _StatStuff */ + return 0; + } + } + } + } + afscp_errno = code; + return -1; } diff --git a/src/libafscp/afscp_file.c b/src/libafscp/afscp_file.c index 78d4124871..b4bdc93f39 100644 --- a/src/libafscp/afscp_file.c +++ b/src/libafscp/afscp_file.c @@ -24,159 +24,176 @@ 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 #include -#include + +#include + #include #include -#include -#include -#include #include "afscp.h" #include "afscp_internal.h" -ssize_t afs_pread(const struct afs_venusfid *fid, void *buffer, size_t count, off_t offset) { - struct AFSFetchStatus fst; - struct AFSVolSync vs; - struct AFSCallBack cb; - struct AFSFid tf = fid->fid; - struct afs_volume *vol; - struct afs_server *server; +/* this is not yet 64-bit clean */ +ssize_t +afscp_PRead(const struct afscp_venusfid * fid, void *buffer, + size_t count, off_t offset) +{ + struct AFSFetchStatus fst; + struct AFSVolSync vs; + struct AFSCallBack cb; + struct AFSFid tf = fid->fid; + struct afscp_volume *vol; + struct afscp_server *server; + struct rx_call *c = NULL; + int code, code2 = 0; + int i, j, bytes, totalbytes = 0; + int bytesremaining; + char *p; + time_t now; - struct rx_call *c=NULL; - int code,code2; - int i,j,bytes,totalbytes; - int bytesremaining; - char *p; - - vol=afs_volumebyid(fid->cell, fid->fid.Volume); - if (!vol) { - afs_errno=ENOENT; - return -1; - } - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(vol->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - c=rx_NewCall(server->conns[j]); - if (c) { - p=buffer; - code=StartRXAFS_FetchData(c, &tf, offset, count); - if (code) { - code=rx_EndCall(c,code); - continue; - } - bytes=rx_Read(c,(char *)&bytesremaining,sizeof(afs_int32)); - if (bytes != sizeof(afs_int32)) { - code=rx_EndCall(c,bytes); - continue; - } - bytesremaining=ntohl(bytesremaining); - totalbytes=0; - while (bytesremaining > 0) { - bytes=rx_Read(c, p, bytesremaining); - if (bytes <= 0) - break; - p+=bytes; - totalbytes+=bytes; - bytesremaining-=bytes; - } - if (bytesremaining == 0) { - code2=EndRXAFS_FetchData(c, &fst, &cb, &vs); - if (code2 == 0) - AddCallBack(server, &fid->fid, &fst, &cb); - } - code=rx_EndCall(c, code2); - } - if (code == 0) - return totalbytes; - } - } - } - afs_errno=code; - return -1; + vol = afscp_VolumeById(fid->cell, fid->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; + } + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + c = rx_NewCall(server->conns[j]); + if (c != 0) { + p = buffer; + code = StartRXAFS_FetchData(c, &tf, offset, count); + if (code != 0) { + code = rx_EndCall(c, code); + continue; + } + bytes = + rx_Read(c, (char *)&bytesremaining, + sizeof(afs_int32)); + if (bytes != sizeof(afs_int32)) { + code = rx_EndCall(c, bytes); + continue; + } + bytesremaining = ntohl(bytesremaining); + totalbytes = 0; + while (bytesremaining > 0) { + bytes = rx_Read(c, p, bytesremaining); + if (bytes <= 0) + break; + p += bytes; + totalbytes += bytes; + bytesremaining -= bytes; + } + if (bytesremaining == 0) { + time(&now); + code2 = EndRXAFS_FetchData(c, &fst, &cb, &vs); + if (code2 == 0) + afscp_AddCallBack(server, &fid->fid, &fst, &cb, + now); + } + code = rx_EndCall(c, code2); + } + if (code == 0) { + return totalbytes; + } + } + } + } + afscp_errno = code; + return -1; } +/* this is not yet 64-bit clean */ +ssize_t +afscp_PWrite(const struct afscp_venusfid * fid, const void *buffer, + size_t count, off_t offset) +{ + struct AFSFetchStatus fst; + struct AFSStoreStatus sst; + struct AFSVolSync vs; + struct AFSCallBack cb; + struct AFSFid tf = fid->fid; + struct afscp_volume *vol; + struct afscp_server *server; + struct rx_call *c = NULL; + int code, code2 = 0; + int i, j, bytes, totalbytes = 0; + int bytesremaining; + const char *p; + off_t filesize; + time_t now; + vol = afscp_VolumeById(fid->cell, fid->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; + } + if (vol->voltype != RWVOL) { + afscp_errno = EROFS; + return -1; + } -ssize_t afs_pwrite(const struct afs_venusfid *fid, const void *buffer, size_t count, off_t offset) { - - struct AFSFetchStatus fst; - struct AFSStoreStatus sst; - struct AFSVolSync vs; - struct AFSCallBack cb; - struct AFSFid tf=fid->fid; - struct afs_volume *vol; - struct afs_server *server; - - struct rx_call *c=NULL; - int code,code2; - int i,j,bytes,totalbytes; - int bytesremaining; - const char *p; - size_t filesize; - time_t now; - - - vol=afs_volumebyid(fid->cell, fid->fid.Volume); - if (!vol) { - afs_errno=ENOENT; - return -1; - } - if (vol->voltype != VOLTYPE_RW) { - afs_errno = EROFS; - return -1; - } - - code=ENOENT; - for (i=0;inservers;i++) { - server=afs_serverbyindex(vol->servers[i]); - if (server && server->naddrs > 0) { - for (j=0;j < server->naddrs;j++) { - code=RXAFS_FetchStatus(server->conns[j], &tf, &fst, &cb, &vs); - if (code) - continue; - sst.Mask=AFS_SETMODTIME; - time(&now); - sst.ClientModTime = now; - filesize=fst.Length; - if (offset + count > filesize) - filesize = offset + count; - c=rx_NewCall(server->conns[j]); - if (c) { - p=buffer; - code=StartRXAFS_StoreData(c, &tf, &sst, offset, count, filesize); - if (code) { - code=rx_EndCall(c,code); - continue; - } - bytesremaining=htonl(count); - bytes=rx_Write(c,(char *)&bytesremaining,sizeof(afs_int32)); - if (bytes != sizeof(afs_int32)) { - code=rx_EndCall(c,bytes); - continue; - } - bytesremaining=count; - totalbytes=0; - while (bytesremaining > 0) { - bytes=rx_Write(c, (char *)p, bytesremaining); - if (bytes <= 0) - break; - p+=bytes; - totalbytes+=bytes; - bytesremaining-=bytes; - } - if (bytesremaining == 0) { - code2=EndRXAFS_StoreData(c, &fst, &vs); - } - code=rx_EndCall(c, code2); - } - if (code == 0) - return totalbytes; - } - } - } - afs_errno=code; - return -1; + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + code = + RXAFS_FetchStatus(server->conns[j], &tf, &fst, &cb, &vs); + if (code != 0) + continue; + sst.Mask = AFS_SETMODTIME; + time(&now); + sst.ClientModTime = now; + filesize = fst.Length; + if (offset + count > filesize) + filesize = offset + count; + c = rx_NewCall(server->conns[j]); + if (c != 0) { + p = buffer; + code = + StartRXAFS_StoreData(c, &tf, &sst, offset, count, + filesize); + if (code != 0) { + code = rx_EndCall(c, code); + continue; + } + /* + * seems to write file length to beginning of file -- why? + */ + /* + * bytesremaining = htonl(count); + * bytes = rx_Write(c, (char *)&bytesremaining, + * sizeof(afs_int32)); + * if (bytes != sizeof(afs_int32)) { + * code = rx_EndCall(c, bytes); + * continue; + * } + */ + bytesremaining = count; + totalbytes = 0; + while (bytesremaining > 0) { + bytes = rx_Write(c, (char *)p, bytesremaining); + if (bytes <= 0) + break; + p += bytes; + totalbytes += bytes; + bytesremaining -= bytes; + } + if (bytesremaining == 0) { + code2 = EndRXAFS_StoreData(c, &fst, &vs); + } + code = rx_EndCall(c, code2); + } + if (code == 0) { + return totalbytes; + } + } + } + } + afscp_errno = code; + return -1; } - diff --git a/src/libafscp/afscp_init.c b/src/libafscp/afscp_init.c index c5335335cf..a337f8b805 100644 --- a/src/libafscp/afscp_init.c +++ b/src/libafscp/afscp_init.c @@ -24,24 +24,13 @@ 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - +#include #include -#include + +#include + #include #include - -#include - #include "afscp.h" #include "afscp_internal.h" @@ -50,57 +39,57 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH #endif -static int init=0; -extern int RXAFSCB_ExecuteRequest(); +static int init = 0; static struct rx_securityClass *sc; static struct rx_service *serv; -extern PROCESS rx_listenerPid; -static int start_cb_server() + +static int +start_cb_server(void) { - - sc=rxnull_NewServerSecurityObject(); - serv=rx_NewService(0,1,"afs", &sc, 1, RXAFSCB_ExecuteRequest); - if (!serv) - return 1; - rx_StartServer(0); - return 0; + sc = rxnull_NewServerSecurityObject(); + serv = rx_NewService(0, 1, "afs", &sc, 1, RXAFSCB_ExecuteRequest); + if (serv == NULL) { + return 1; + } + rx_StartServer(0); + return 0; } -int afscp_init(const char *cell) +int +afscp_Init(const char *cell) { - if (init) - return 0; - if (_rx_InitRandomPort()) - return -1; - init=1; - if (start_cb_server()) { - printf("Cannot start callback service\n"); - return -1; - } - init=2; - if (cell) - return afs_setdefaultcell(cell); - return 0; + int code; + if (init != 0) { + return 0; + } + code = rx_Init(0); + if (code != 0) { + return -1; + } + init = 1; + code = start_cb_server(); + if (code != 0) { + printf("Cannot start callback service\n"); + return -1; + } + init = 2; + if (cell != NULL) + code = afscp_SetDefaultCell(cell); + else + code = 0; + return code; } -void afscp_finalize(void) { - if (!init) - return; - - ReturnAllCallBacks(); - IOMGR_Sleep(1); - rx_Finalize(); -#if 0 - LWP_DestroyProcess(rx_listenerPid); - close(serv->socket); - rxi_FreeService(serv); -#endif - IOMGR_Finalize(); - LWP_TerminateProcessSupport(); -#if 1 - close(serv->socket); -#endif +void +afscp_Finalize(void) +{ + if (init == 0) { + return; + } + afscp_ReturnAllCallBacks(); + afscp_FreeAllCells(); + afscp_FreeAllServers(); + rx_Finalize(); + close(serv->socket); } - - diff --git a/src/libafscp/afscp_internal.h b/src/libafscp/afscp_internal.h index c2f887e1f2..e325f08daa 100644 --- a/src/libafscp/afscp_internal.h +++ b/src/libafscp/afscp_internal.h @@ -1,79 +1,24 @@ +#ifndef AFS_SRC_LIBAFSCP_AFSCP_INTERNAL_H +#define AFS_SRC_LIBAFSCP_AFSCP_INTERNAL_H + #include #include #include -#define MAXADDRS 16 + +/* afsint.h conflicts with afscbint.h; provide this here */ +extern int RXAFSCB_ExecuteRequest(struct rx_call *); /* AUTORIGHTS */ -struct afs_server -{ - afsUUID id; - int index; - int cell; - int naddrs; - afs_uint32 addrs[MAXADDRS]; - struct rx_connection *conns[MAXADDRS]; -}; -struct afs_cell -{ - int id; - char name[MAXCELLCHARS]; - struct rx_securityClass *security; - int scindex; - struct ubik_client *vlservers; - int nservers; - int srvsalloced; - struct afs_server **fsservers; - void *volsbyname; - void *volsbyid; -}; +extern int _GetSecurityObject(struct afscp_cell *); +extern int _GetVLservers(struct afscp_cell *); +extern int _StatInvalidate(const struct afscp_venusfid *); +extern int _StatStuff(const struct afscp_venusfid *, + const struct AFSFetchStatus *); -struct afs_callback -{ - int valid; - const struct afs_server *server; - struct AFSFid fid; - struct AFSCallBack cb; -}; - -struct afs_dirstream -{ - struct afs_venusfid fid; - int buflen; - char *dirbuffer; - int hashent; - int entry; - int dv; - struct afs_dirent ret; -}; - -struct afs_dircache -{ - struct afs_venusfid me; - int buflen; - char *dirbuffer; - int dv; -}; - -struct afs_statent -{ - struct afs_venusfid me; - struct AFSFetchStatus status; -}; - -struct afs_openfile -{ - struct afs_venusfid fid; - off_t offset; -}; - -extern int _rx_InitRandomPort(void); -extern int _GetSecurityObject(struct afs_cell *); -extern int _GetVLservers(struct afs_cell *); -extern int _StatInvalidate(const struct afs_venusfid *fid); -extern int _StatStuff(const struct afs_venusfid *fid, const struct AFSFetchStatus *s); - -#ifdef AFSCP_DEBUG -#define afscp_dprintf(x) printf x +#ifndef AFSCP_DEBUG +#define afs_dprintf(x) #else -#define afscp_dprintf(x) +#define afs_dprintf(x) printf x #endif + +#endif /* AFS_SRC_LIBAFSCP_AFSCP_INTERNAL_H */ diff --git a/src/libafscp/afscp_server.c b/src/libafscp/afscp_server.c index 2fb9cd422b..89ac813d64 100644 --- a/src/libafscp/afscp_server.c +++ b/src/libafscp/afscp_server.c @@ -24,8 +24,11 @@ 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 #include -#include + +#include + #include #include #include @@ -34,317 +37,437 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH #endif -#include -#include #include +#include #include "afscp.h" #include "afscp_internal.h" -static int afs_ncells=0,afs_cellsalloced=0; -static struct afs_cell *allcells=NULL; -static int afs_nservers=0,afs_srvsalloced=0; -static struct afs_server **allservers=NULL; -static char *defcell; -int afs_errno=0; +static int afscp_ncells = 0, afscp_cellsalloced = 0; +static struct afscp_cell *allcells = NULL; +static int afscp_nservers = 0, afscp_srvsalloced = 0; +static struct afscp_server **allservers = NULL; +static char *defcell = NULL; +static char *defrealm = NULL; +int afscp_errno = 0; -struct afs_cell *afs_cellbyid(int id) +void +afscp_FreeAllCells(void) { - if (id >= afs_ncells) - return NULL; - return &allcells[id]; + int i; + + if (allcells == NULL) + return; + + for (i = 0; i < afscp_ncells; i++) { + if (allcells[i].realm != NULL) + free(allcells[i].realm); + if (allcells[i].fsservers != NULL) + free(allcells[i].fsservers); + } + + free(allcells); + allcells = NULL; + afscp_ncells = 0; + afscp_cellsalloced = 0; } -struct afs_cell *afs_cellbyname(const char *cellname) +void +afscp_FreeAllServers(void) { - int i; - struct afs_cell *newlist, *thecell; - - for (i=0;i= afs_cellsalloced) { - if (afs_cellsalloced) - afs_cellsalloced = afs_cellsalloced *2; - else - afs_cellsalloced = 4; - newlist=realloc(allcells, afs_cellsalloced * sizeof(struct afs_cell)); - if (!newlist) - return NULL; - allcells=newlist; - } - thecell=&allcells[afs_ncells]; - memset(thecell, 0, sizeof(struct afs_cell)); - strcpy(thecell->name, cellname); - if (_GetSecurityObject(thecell)) - return NULL; - if (_GetVLservers(thecell)) { - RXS_Close(thecell->security); - return NULL; - } - thecell->id=afs_ncells++; - return thecell; -} -struct afs_cell *afs_defaultcell(void) -{ - struct afsconf_dir *dir; - char localcell[MAXCELLCHARS+1]; - int code; - - - if (defcell) { - return afs_cellbyname(defcell); - } - - dir=afsconf_Open(AFSCONF_CLIENTNAME); - if (!dir) { - afs_errno=AFSCONF_NODB; - return NULL; - } - code=afsconf_GetLocalCell(dir, localcell, MAXCELLCHARS); - if (code){ - afs_errno=code; - return NULL; - } - afsconf_Close(dir); - return afs_cellbyname(localcell); + if (allservers == NULL) + return; + free(allservers); + allservers = NULL; + afscp_nservers = 0; + afscp_srvsalloced = 0; } -int afs_setdefaultcell(const char *cellname) { - struct afs_cell *this; - char *newdefcell; - if (!cellname) { - if (defcell) - free(defcell); - defcell=NULL; - return 0; - } +struct afscp_cell * +afscp_CellById(int id) +{ + if (id >= afscp_ncells || id < 0) + return NULL; + return &allcells[id]; +} - this=afs_cellbyname(cellname); - if (!this) - return -1; - newdefcell=strdup(cellname); - if (!newdefcell) +struct afscp_cell * +afscp_CellByName(const char *cellname, const char *realmname) +{ + int i; + struct afscp_cell *newlist, *thecell; + + if (cellname == NULL) { + return NULL; + } + for (i = 0; i < afscp_ncells; i++) { + if (strcmp(allcells[i].name, cellname) == 0) { + return &allcells[i]; + } + } + if (afscp_ncells >= afscp_cellsalloced) { + if (afscp_cellsalloced) + afscp_cellsalloced = afscp_cellsalloced * 2; + else + afscp_cellsalloced = 4; + newlist = + realloc(allcells, afscp_cellsalloced * sizeof(struct afscp_cell)); + if (newlist == NULL) { + return NULL; + } + allcells = newlist; + } + thecell = &allcells[afscp_ncells]; + memset(thecell, 0, sizeof(struct afscp_cell)); + strlcpy(thecell->name, cellname, sizeof(thecell->name)); + if (realmname != NULL) { + thecell->realm = malloc(strlen(realmname) + 1); + memset(thecell->realm, 0, strlen(realmname) + 1); + strlcpy(thecell->realm, realmname, strlen(realmname) + 1); + } else { + thecell->realm = NULL; + } + if (_GetSecurityObject(thecell)) { + return NULL; + } + if (_GetVLservers(thecell)) { + RXS_Close(thecell->security); + return NULL; + } + thecell->id = afscp_ncells++; + return thecell; +} + +struct afscp_cell * +afscp_DefaultCell(void) +{ + struct afsconf_dir *dir; + char localcell[MAXCELLCHARS + 1]; + int code; + + if (defcell) { + return afscp_CellByName(defcell, defrealm); + } + + dir = afsconf_Open(AFSCONF_CLIENTNAME); + if (dir == NULL) { + afscp_errno = AFSCONF_NODB; + return NULL; + } + code = afsconf_GetLocalCell(dir, localcell, MAXCELLCHARS); + if (code != 0) { + afscp_errno = code; + return NULL; + } + afsconf_Close(dir); + return afscp_CellByName(localcell, defrealm); +} + +int +afscp_SetDefaultRealm(const char *realmname) +{ + /* krb5_error_code k5ec; */ + krb5_context k5con; + char *newdefrealm; + int code; + + if (realmname == NULL) { + if (defrealm != NULL) + free(defrealm); + defrealm = NULL; + return 0; + } + + code = krb5_init_context(&k5con); /* see aklog.c main() */ + if (code != 0) { return -1; - if (defcell) - free(defcell); - defcell = newdefcell; - return 0; + } + /* k5ec = */ + krb5_set_default_realm(k5con, realmname); + /* if (k5ec != KRB5KDC_ERR_NONE) { + * com_err("libafscp", k5ec, "k5ec = %d (compared to KRB5KDC_ERR_NONE = %d)", k5ec, KRB5KDC_ERR_NONE); + * return -1; + * } */ + /* krb5_set_default_realm() is returning 0 on success, not KRB5KDC_ERR_NONE */ + newdefrealm = strdup(realmname); + if (newdefrealm == NULL) { + return -1; + } + if (defrealm != NULL) + free(defrealm); + defrealm = newdefrealm; + return 0; } -int afs_cellid(struct afs_cell *cell) { - return cell->id; -} - -static void _xdr_free(bool_t (*fn)(XDR *xdrs, void *obj), void *obj) { - XDR xdrs; - xdrs.x_op=XDR_FREE; - fn(&xdrs, obj); -} -static bool_t _xdr_bulkaddrs(XDR *xdrs, void *objp) { - return xdr_bulkaddrs(xdrs, objp); -} - - -struct afs_server *afs_serverbyid(struct afs_cell *thecell, afsUUID *u) +int +afscp_SetDefaultCell(const char *cellname) { - /* impliment uniquifiers? */ - int i; - struct afs_server **newlist; - struct afs_server **newall; - struct afs_server *ret; - afsUUID tmp; - bulkaddrs addrs; - struct ListAddrByAttributes attrs; - afs_int32 nentries, uniq; + struct afscp_cell *this; + char *newdefcell; + if (cellname == NULL) { + if (defcell != NULL) + free(defcell); + defcell = NULL; + return 0; + } - char s[512]; + this = afscp_CellByName(cellname, defrealm); + if (this == NULL) { + return -1; + } + newdefcell = strdup(cellname); + if (newdefcell == NULL) { + return -1; + } + if (defcell != NULL) + free(defcell); + defcell = newdefcell; + return 0; +} - afsUUID_to_string(u, s, 511); - afscp_dprintf(("GetServerByID %s\n", s)); +int +afscp_CellId(struct afscp_cell *cell) +{ + if (cell == NULL) + return -1; + return cell->id; +} - for (i=0;inservers;i++) { - if (afs_uuid_equal(&thecell->fsservers[i]->id, u)) - return thecell->fsservers[i]; - } +static void +_xdr_free(bool_t(*fn) (XDR * xdrs, void *obj), void *obj) +{ + XDR xdrs; + xdrs.x_op = XDR_FREE; + fn(&xdrs, obj); +} - if (thecell->nservers >= thecell->srvsalloced) { - if (thecell->srvsalloced) - thecell->srvsalloced = thecell->srvsalloced *2; - else - thecell->srvsalloced = 4; - newlist=realloc(thecell->fsservers, - thecell->srvsalloced * sizeof(struct afs_server *)); - if (!newlist) - return NULL; - thecell->fsservers=newlist; - } - ret=malloc(sizeof(struct afs_server)); - if (!ret) - return NULL; - thecell->fsservers[thecell->nservers]=ret; - memmove(&ret->id, u, sizeof(afsUUID)); - ret->cell=thecell->id; - memset(&tmp, 0, sizeof(tmp)); - memset(&addrs, 0, sizeof(addrs)); - memset(&attrs, 0, sizeof(attrs)); - attrs.Mask = VLADDR_UUID; - memmove(&attrs.uuid, u, sizeof(afsUUID)); +static bool_t +_xdr_bulkaddrs(XDR * xdrs, void *objp) +{ + return xdr_bulkaddrs(xdrs, objp); +} - if (ubik_VL_GetAddrsU(thecell->vlservers, 0, &attrs, &tmp, - &uniq, &nentries, &addrs)) - return NULL; - if (nentries > MAXADDRS) { - nentries=MAXADDRS; - /* XXX I don't want to do *that* much dynamic allocation */ - abort(); - } +struct afscp_server * +afscp_ServerById(struct afscp_cell *thecell, afsUUID * u) +{ + /* impliment uniquifiers? */ + int i, code; + struct afscp_server **newlist; + struct afscp_server **newall; + struct afscp_server *ret = NULL; + afsUUID tmp; + bulkaddrs addrs; + struct ListAddrByAttributes attrs; + afs_int32 nentries, uniq; + char s[512]; + afsUUID_to_string(u, s, 511); + afs_dprintf(("GetServerByID %s\n", s)); - ret->naddrs=nentries; - for (i=0; i< nentries;i++) { - ret->addrs[i]=htonl(addrs.bulkaddrs_val[i]); - ret->conns[i]=rx_NewConnection(ret->addrs[i], + for (i = 0; i < thecell->nservers; i++) { + if (afs_uuid_equal(&thecell->fsservers[i]->id, u)) { + return thecell->fsservers[i]; + } + } + + if (thecell->nservers >= thecell->srvsalloced) { + if (thecell->srvsalloced) + thecell->srvsalloced = thecell->srvsalloced * 2; + else + thecell->srvsalloced = 4; + newlist = realloc(thecell->fsservers, + thecell->srvsalloced * + sizeof(struct afscp_server *)); + if (newlist == NULL) { + return NULL; + } + thecell->fsservers = newlist; + } + ret = malloc(sizeof(struct afscp_server)); + if (ret == NULL) { + return NULL; + } + memset(ret, 0, sizeof(struct afscp_server)); + thecell->fsservers[thecell->nservers] = ret; + memmove(&ret->id, u, sizeof(afsUUID)); + ret->cell = thecell->id; + memset(&tmp, 0, sizeof(tmp)); + memset(&addrs, 0, sizeof(addrs)); + memset(&attrs, 0, sizeof(attrs)); + attrs.Mask = VLADDR_UUID; + memmove(&attrs.uuid, u, sizeof(afsUUID)); + + code = ubik_VL_GetAddrsU(thecell->vlservers, 0, &attrs, &tmp, + &uniq, &nentries, &addrs); + if (code != 0) { + return NULL; + } + if (nentries > AFS_MAXHOSTS) { + nentries = AFS_MAXHOSTS; + /* XXX I don't want to do *that* much dynamic allocation */ + abort(); + } + + ret->naddrs = nentries; + for (i = 0; i < nentries; i++) { + ret->addrs[i] = htonl(addrs.bulkaddrs_val[i]); + ret->conns[i] = rx_NewConnection(ret->addrs[i], htons(AFSCONF_FILEPORT), 1, thecell->security, thecell->scindex); - } - _xdr_free(_xdr_bulkaddrs, &addrs); - thecell->nservers++; + } + _xdr_free(_xdr_bulkaddrs, &addrs); + thecell->nservers++; - if (afs_nservers >= afs_srvsalloced) { - if (afs_srvsalloced) - afs_srvsalloced = afs_srvsalloced *2; - else - afs_srvsalloced = 4; - newall=realloc(allservers, - afs_srvsalloced * sizeof(struct afs_server *)); - if (!newall) - return ret; - allservers=newall; - } - ret->index=afs_nservers; - allservers[afs_nservers++]=ret; - return ret; + if (afscp_nservers >= afscp_srvsalloced) { + if (afscp_srvsalloced) + afscp_srvsalloced = afscp_srvsalloced * 2; + else + afscp_srvsalloced = 4; + newall = realloc(allservers, + afscp_srvsalloced * sizeof(struct afscp_server *)); + if (newall == NULL) { + return ret; + } + allservers = newall; + } + ret->index = afscp_nservers; + allservers[afscp_nservers++] = ret; + return ret; } -struct afs_server *afs_serverbyaddr(struct afs_cell *thecell, afs_uint32 addr) +struct afscp_server * +afscp_ServerByAddr(struct afscp_cell *thecell, afs_uint32 addr) { - /* impliment uniquifiers? */ - int i,j; - struct afs_server **newlist; - struct afs_server **newall; - struct afs_server *ret; - afsUUID uuid; - bulkaddrs addrs; - struct ListAddrByAttributes attrs; - afs_int32 nentries, code, uniq; + /* implement uniquifiers? */ + int i, j; + struct afscp_server **newlist; + struct afscp_server **newall; + struct afscp_server *ret = NULL; + afsUUID uuid; + bulkaddrs addrs; + struct ListAddrByAttributes attrs; + afs_int32 nentries, code, uniq; + if (thecell == NULL) + return ret; /* cannot continue without thecell */ - for (i=0;inservers;i++) { - ret=thecell->fsservers[i]; - for (j=0;jnaddrs;j++) - if (ret->addrs[j] == htonl(addr)) - return ret; - } + for (i = 0; i < thecell->nservers; i++) { + ret = thecell->fsservers[i]; + for (j = 0; j < ret->naddrs; j++) + if (ret->addrs[j] == htonl(addr)) { + return ret; + } + } - if (thecell->nservers >= thecell->srvsalloced) { - if (thecell->srvsalloced) - thecell->srvsalloced = thecell->srvsalloced *2; - else - thecell->srvsalloced = 4; - newlist=realloc(thecell->fsservers, - thecell->srvsalloced * sizeof(struct afs_server)); - if (!newlist) - return NULL; - thecell->fsservers=newlist; - } - ret=malloc(sizeof(struct afs_server)); - if (!ret) - return NULL; - thecell->fsservers[thecell->nservers]=ret; - ret->cell=thecell->id; - memset(&uuid, 0, sizeof(uuid)); - memset(&addrs, 0, sizeof(addrs)); - memset(&attrs, 0, sizeof(attrs)); - attrs.Mask = VLADDR_IPADDR; - attrs.ipaddr=addr; + if (thecell->nservers >= thecell->srvsalloced) { + if (thecell->srvsalloced) + thecell->srvsalloced = thecell->srvsalloced * 2; + else + thecell->srvsalloced = 4; + newlist = realloc(thecell->fsservers, + thecell->srvsalloced * sizeof(struct afscp_server)); + if (newlist == NULL) { + return NULL; + } + thecell->fsservers = newlist; + } + ret = malloc(sizeof(struct afscp_server)); + if (ret == NULL) { + return NULL; + } + memset(ret, 0, sizeof(struct afscp_server)); + thecell->fsservers[thecell->nservers] = ret; + ret->cell = thecell->id; + memset(&uuid, 0, sizeof(uuid)); + memset(&addrs, 0, sizeof(addrs)); + memset(&attrs, 0, sizeof(attrs)); + attrs.Mask = VLADDR_IPADDR; + attrs.ipaddr = addr; + code = ubik_VL_GetAddrsU(thecell->vlservers, 0, &attrs, &uuid, + &uniq, &nentries, &addrs); + if (code != 0) { + memset(&ret->id, 0, sizeof(uuid)); + ret->naddrs = 1; + ret->addrs[0] = htonl(addr); + ret->conns[0] = rx_NewConnection(ret->addrs[0], + htons(AFSCONF_FILEPORT), + 1, thecell->security, + thecell->scindex); + } else { + char s[512]; - if ((code=ubik_VL_GetAddrsU(thecell->vlservers, 0, &attrs, &uuid, - &uniq, &nentries, &addrs))) { - memset(&ret->id, 0, sizeof(uuid)); - ret->naddrs=1; - ret->addrs[0]=htonl(addr); - ret->conns[0]=rx_NewConnection(ret->addrs[0], - htons(AFSCONF_FILEPORT), - 1, thecell->security, - thecell->scindex); - } else { - char s[512]; + afsUUID_to_string(&uuid, s, 511); + afs_dprintf(("GetServerByAddr 0x%x -> uuid %s\n", addr, s)); - afsUUID_to_string(&uuid, s, 511); - afscp_dprintf(("GetServerByAddr 0x%x -> uuid %s\n", addr, s)); + if (nentries > AFS_MAXHOSTS) { + nentries = AFS_MAXHOSTS; + /* XXX I don't want to do *that* much dynamic allocation */ + abort(); + } + memmove(&ret->id, &uuid, sizeof(afsUUID)); - if (nentries > MAXADDRS) { - nentries=MAXADDRS; - /* XXX I don't want to do *that* much dynamic allocation */ - abort(); - } - memmove(&ret->id, &uuid, sizeof(afsUUID)); + ret->naddrs = nentries; + for (i = 0; i < nentries; i++) { + ret->addrs[i] = htonl(addrs.bulkaddrs_val[i]); + ret->conns[i] = rx_NewConnection(ret->addrs[i], + htons(AFSCONF_FILEPORT), + 1, thecell->security, + thecell->scindex); + } + _xdr_free(_xdr_bulkaddrs, &addrs); + } - ret->naddrs=nentries; - for (i=0; i< nentries;i++) { - ret->addrs[i]=htonl(addrs.bulkaddrs_val[i]); - ret->conns[i]=rx_NewConnection(ret->addrs[i], - htons(AFSCONF_FILEPORT), - 1, thecell->security, - thecell->scindex); - } - _xdr_free(_xdr_bulkaddrs, &addrs); - } - - thecell->nservers++; - if (afs_nservers >= afs_srvsalloced) { - if (afs_srvsalloced) - afs_srvsalloced = afs_srvsalloced *2; - else - afs_srvsalloced = 4; - newall=realloc(allservers, - afs_srvsalloced * sizeof(struct afs_server *)); - if (!newall) - return ret; - allservers=newall; - } - ret->index=afs_nservers; - allservers[afs_nservers++]=ret; - return ret; + thecell->nservers++; + if (afscp_nservers >= afscp_srvsalloced) { + if (afscp_srvsalloced) + afscp_srvsalloced = afscp_srvsalloced * 2; + else + afscp_srvsalloced = 4; + newall = realloc(allservers, + afscp_srvsalloced * sizeof(struct afscp_server *)); + if (newall == NULL) { + return ret; + } + allservers = newall; + } + ret->index = afscp_nservers; + allservers[afscp_nservers++] = ret; + return ret; } -struct afs_server *afs_anyserverbyaddr(afs_uint32 addr) +struct afscp_server * +afscp_AnyServerByAddr(afs_uint32 addr) { - /* no idea what this means: "impliment uniquifiers?" */ - int i,j; - struct afs_server *ret; + /* implement uniquifiers? */ + int i, j; + struct afscp_server *ret = NULL; - for (i=0;inaddrs;j++) - if (ret->addrs[j] == htonl(addr)) - return ret; - } - return NULL; -} - -struct afs_server *afs_serverbyindex(int i) -{ - - if (i>= afs_nservers) - return NULL; - return allservers[i]; -} - -struct rx_connection *afs_serverconnection(const struct afs_server *srv, int i) { - if (i >= srv->naddrs) + if (allservers == NULL) + return ret; + for (i = 0; i < afscp_nservers; i++) { + ret = allservers[i]; + for (j = 0; j < ret->naddrs; j++) + if (ret->addrs[j] == htonl(addr)) { + return ret; + } + } return NULL; - return srv->conns[i]; +} + +struct afscp_server * +afscp_ServerByIndex(int i) +{ + if (i >= afscp_nservers || i < 0) + return NULL; + return allservers[i]; +} + +struct rx_connection * +afscp_ServerConnection(const struct afscp_server *srv, int i) +{ + if (srv == NULL || srv->conns == NULL) + return NULL; + if (i >= srv->naddrs || i < 0) + return NULL; + return srv->conns[i]; } diff --git a/src/libafscp/afscp_util.c b/src/libafscp/afscp_util.c index 9c58f1424b..2aad521ef6 100644 --- a/src/libafscp/afscp_util.c +++ b/src/libafscp/afscp_util.c @@ -24,32 +24,24 @@ 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 -#include -#include -#include -#include -#include -#include - +#include #include + +#include + +#include #include #ifndef AFSCONF_CLIENTNAME #include #define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH #endif - #include -#include #include - +#include #include - #include "afscp.h" #include "afscp_internal.h" -#define HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE - #ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE #define Z_keydata(keyblock) ((keyblock)->contents) #define Z_keylen(keyblock) ((keyblock)->length) @@ -62,156 +54,180 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define Z_enctype(keyblock) ((keyblock)->keytype) #endif -int _rx_InitRandomPort(void) { - int sock; - unsigned int port; - struct sockaddr_in sin; - - sock=socket(PF_INET, SOCK_DGRAM, 0); - if (sock == -1) - return errno; - sin.sin_family=AF_INET; - sin.sin_addr.s_addr=INADDR_ANY; - sin.sin_port=0; - if (bind(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) - return errno; - - port=sizeof(struct sockaddr_in); - if (getsockname(sock, (struct sockaddr *)&sin, &port) < 0) - return errno; - port=sin.sin_port; - close(sock); - return rx_Init(port); +static int insecure = 0; +static int try_anonymous = 0; +int +afscp_Insecure(void) +{ + insecure = 1; + return 0; } -static int insecure; - -int afscp_Insecure(void) { - insecure=1; - return 0; +int +afscp_AnonymousAuth(int state) +{ + try_anonymous = state; + return 0; } + static struct afsconf_dir *confdir; -static int _GetCellInfo(char *cell, struct afsconf_cell *celldata) { - - if (!confdir) - confdir=afsconf_Open(AFSCONF_CLIENTNAME); - if (!confdir) - return AFSCONF_NODB; - return afsconf_GetCellInfo(confdir, cell, AFSCONF_VLDBSERVICE, celldata); +static int +_GetCellInfo(char *cell, struct afsconf_cell *celldata) +{ + int code; + if (confdir == NULL) + confdir = afsconf_Open(AFSCONF_CLIENTNAME); + if (confdir == NULL) { + return AFSCONF_NODB; + } + code = afsconf_GetCellInfo(confdir, cell, AFSCONF_VLDBSERVICE, celldata); + return code; } -int _GetSecurityObject(struct afs_cell *cell) { - int code; - krb5_context context; - krb5_creds match; - krb5_creds *cred; - krb5_ccache cc; - char **realms,*realm; - struct afsconf_cell celldata; - char localcell[MAXCELLCHARS]; - struct rx_securityClass *sc; - struct ktc_encryptionKey k; - int i; - rxkad_level l; +static int +_GetNullSecurityObject(struct afscp_cell *cell) +{ + cell->security = (struct rx_securityClass *)rxnull_NewClientSecurityObject(); + cell->scindex = RX_SECIDX_NULL; + return 0; +} - code=_GetCellInfo(cell->name, &celldata); - if (code) - return code; - - code=krb5_init_context(&context); - if (code) - return code; - realm=NULL; - code=krb5_get_host_realm(context, celldata.hostName[0], &realms); - if (!code) { - strcpy(localcell,realms[0]); - krb5_free_host_realm(context,realms); - realm=localcell; - } - if (!realm) { - for (i=0; (i < MAXCELLCHARS && cell->name[i]); i++) { - if (isalpha(cell->name[i])) - localcell[i]=toupper(cell->name[i]); - else - localcell[i]=cell->name[i]; +int +_GetSecurityObject(struct afscp_cell *cell) +{ + int code; + krb5_context context; + krb5_creds match; + krb5_creds *cred; + krb5_ccache cc; + char **realms, *realm, *inst; + char name[1024]; + struct afsconf_cell celldata; + char localcell[MAXCELLCHARS + 1]; + struct rx_securityClass *sc; + struct ktc_encryptionKey k; + int i; + rxkad_level l; + code = _GetCellInfo(cell->name, &celldata); + if (code != 0) { + goto try_anon; } - localcell[i]='\0'; - realm=localcell; - } - cc=NULL; - code=krb5_cc_default(context, &cc); - memset(&match, 0, sizeof(match)); - Z_enctype(Z_credskey(&match))=ENCTYPE_DES_CBC_CRC; + code = krb5_init_context(&context); /* see aklog.c main() */ + if (code != 0) { + goto try_anon; + } - if (!code) - code=krb5_cc_get_principal(context, cc, &match.client); - if (!code) - code=krb5_build_principal(context, &match.server, - strlen(realm), realm, - "afs", cell->name, NULL); + if (cell->realm == NULL) { + realm = NULL; + code = krb5_get_host_realm(context, celldata.hostName[0], &realms); - if (code) { + if (code == 0) { + strlcpy(localcell, realms[0], sizeof(localcell)); + krb5_free_host_realm(context, realms); + realm = localcell; + } + } else { + realm = cell->realm; + strlcpy(localcell, realm, MAXCELLCHARS + 1); + } + if (realm) + if (realm == NULL) { + for (i = 0; (i < MAXCELLCHARS && cell->name[i]); i++) { + if (isalpha(cell->name[i])) + localcell[i] = toupper(cell->name[i]); + else + localcell[i] = cell->name[i]; + } + localcell[i] = '\0'; + realm = localcell; + } + cc = NULL; + code = krb5_cc_default(context, &cc); + + memset(&match, 0, sizeof(match)); + Z_enctype(Z_credskey(&match)) = ENCTYPE_DES_CBC_CRC; + + if (code == 0) + code = krb5_cc_get_principal(context, cc, &match.client); + if (code == 0) + code = krb5_build_principal(context, &match.server, + strlen(realm), realm, + "afs", cell->name, NULL); + + if (code != 0) { + krb5_free_cred_contents(context, &match); + if (cc) + krb5_cc_close(context, cc); + krb5_free_context(context); + goto try_anon; + } + + code = krb5_get_credentials(context, 0, cc, &match, &cred); + if (code != 0) { + krb5_free_principal(context, match.server); + match.server = NULL; + + inst = cell->name; + snprintf(name, sizeof(name), "afs/%s", inst); + code = krb5_build_principal(context, &match.server, + strlen(realm), realm, name, (void *)NULL); + if (code == 0) + code = krb5_get_credentials(context, 0, cc, &match, &cred); + if (code != 0) { + krb5_free_cred_contents(context, &match); + if (cc) + krb5_cc_close(context, cc); + krb5_free_context(context); + goto try_anon; + } + } + + if (insecure) + l = rxkad_clear; + else + l = rxkad_crypt; + memcpy(&k.data, Z_keydata(Z_credskey(cred)), 8); + sc = (struct rx_securityClass *)rxkad_NewClientSecurityObject + (l, &k, RXKAD_TKT_TYPE_KERBEROS_V5, + cred->ticket.length, cred->ticket.data); + krb5_free_creds(context, cred); krb5_free_cred_contents(context, &match); if (cc) - krb5_cc_close(context, cc); - krb5_free_context(context); - return code; - } - - code = krb5_get_credentials(context, 0, cc, &match, &cred); - if (code) { - krb5_free_principal(context, match.server); - match.server=NULL; - code=krb5_build_principal(context, &match.server, - strlen(realm), realm, - "afs", NULL); /* afs@cell instead? */ - if (!code) - code = krb5_get_credentials(context, 0, cc, &match, &cred); - if (code) { - krb5_free_cred_contents(context, &match); - if (cc) krb5_cc_close(context, cc); - krb5_free_context(context); - return code; + krb5_free_context(context); + cell->security = sc; + cell->scindex = 2; + return 0; + + try_anon: + if (try_anonymous) + return _GetNullSecurityObject(cell); + else + return code; +} + +int +_GetVLservers(struct afscp_cell *cell) +{ + struct rx_connection *conns[MAXHOSTSPERCELL + 1]; + int i; + int code; + struct afsconf_cell celldata; + + code = _GetCellInfo(cell->name, &celldata); + if (code != 0) { + return code; } - } - if (insecure) - l=rxkad_clear; - else - l=rxkad_crypt; - memcpy(&k.data, Z_keydata(Z_credskey(cred)), 8); - sc = (struct rx_securityClass *)rxkad_NewClientSecurityObject - (l, &k, RXKAD_TKT_TYPE_KERBEROS_V5, - cred->ticket.length, cred->ticket.data); - krb5_free_creds(context, cred); - krb5_free_cred_contents(context, &match); - if (cc) - krb5_cc_close(context, cc); - krb5_free_context(context); - cell->security=sc; - cell->scindex=2; - return 0; -} -int _GetVLservers(struct afs_cell *cell) { - struct rx_connection *conns[MAXHOSTSPERCELL+1]; - int i; - int code; - struct afsconf_cell celldata; - - code=_GetCellInfo(cell->name, &celldata); - if (code) - return code; - - for (i=0; i < celldata.numServers; i++) { - conns[i] = rx_NewConnection(celldata.hostAddr[i].sin_addr.s_addr, - htons(AFSCONF_VLDBPORT), - USER_SERVICE_ID, cell->security, - cell->scindex); - } - conns[i]=0; - return ubik_ClientInit(conns, &cell->vlservers); + for (i = 0; i < celldata.numServers; i++) { + conns[i] = rx_NewConnection(celldata.hostAddr[i].sin_addr.s_addr, + htons(AFSCONF_VLDBPORT), + USER_SERVICE_ID, cell->security, + cell->scindex); + } + conns[i] = 0; + return ubik_ClientInit(conns, &cell->vlservers); } diff --git a/src/libafscp/afscp_volume.c b/src/libafscp/afscp_volume.c index 933705ee06..6a0978d014 100644 --- a/src/libafscp/afscp_volume.c +++ b/src/libafscp/afscp_volume.c @@ -24,294 +24,308 @@ 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 #include + +#include + +#include + #include #include #include -#include -#include -#include -#include -#include -#include #include "afscp.h" #include "afscp_internal.h" -#include -#include - -static int icompare(const void *pa, const void *pb) { - const struct afs_volume *va=pa,*vb=pb; - - if (va->id > vb->id) return 1; - if (va->id < vb->id) return -1; - return 0; -} - - -static int ncompare(const void *pa, const void *pb) { - const struct afs_volume *va=pa,*vb=pb; - - if (va->voltype > vb->voltype) return 1; - if (vb->voltype < va->voltype) return -1; - return strcmp(va->name, vb->name); -} - - -union allvldbentry +static int +icompare(const void *pa, const void *pb) { - struct uvldbentry u; - struct nvldbentry n; - struct vldbentry o; + const struct afscp_volume *va = pa, *vb = pb; + + if (va->id > vb->id) + return 1; + if (va->id < vb->id) + return -1; + return 0; +} + +static int +ncompare(const void *pa, const void *pb) +{ + const struct afscp_volume *va = pa, *vb = pb; + + if (va->voltype > vb->voltype) + return 1; + if (vb->voltype < va->voltype) + return -1; + return strcmp(va->name, vb->name); +} + +union allvldbentry { + struct uvldbentry u; + struct nvldbentry n; + struct vldbentry o; }; -struct afs_volume *afs_volumebyname(struct afs_cell *cell, const char *vname, afs_int32 intype) +struct afscp_volume * +afscp_VolumeByName(struct afscp_cell *cell, const char *vname, + afs_int32 intype) { - union allvldbentry u; - struct afs_volume *ret,key; - struct afs_server *server; - afs_int32 code,vtype,type,srv; - void *s; - struct in_addr i; + union allvldbentry u; + struct afscp_volume *ret, key; + struct afscp_server *server; + afs_int32 code, vtype, type, srv; + void *s; + /* struct in_addr i; */ - if (intype == VOLTYPE_RW) - vtype=VLSF_RWVOL; - else if (intype == VOLTYPE_RO) - vtype=VLSF_ROVOL; - else if (intype == VOLTYPE_BK) - vtype=VLSF_BACKVOL; - else { - afs_errno=EINVAL; - return NULL; - } + if (intype == RWVOL) + vtype = VLSF_RWVOL; + else if (intype == ROVOL) + vtype = VLSF_ROVOL; + else if (intype == BACKVOL) + vtype = VLSF_BACKVOL; + else { + afscp_errno = EINVAL; + return NULL; + } - memset(&key,0, sizeof(key)); - strcpy(key.name,vname); - key.voltype=vtype; - s=tfind(&key, &cell->volsbyname, ncompare); - if (s) { - ret=*(struct afs_volume **)s; - return ret; - } + memset(&key, 0, sizeof(key)); + strlcpy(key.name, vname, sizeof(key.name)); + key.voltype = vtype; + s = tfind(&key, &cell->volsbyname, ncompare); + if (s) { + ret = *(struct afscp_volume **)s; + return ret; + } - type=0; - if ((code=ubik_VL_GetEntryByNameU(cell->vlservers, 0, (char *)vname, &u.u)) - == RXGEN_OPCODE) { - type=1; - if ((code=ubik_VL_GetEntryByNameN(cell->vlservers, 0, (char *)vname, &u.n)) - == RXGEN_OPCODE) { - type=2; - code=ubik_VL_GetEntryByNameO(cell->vlservers, 0, (char *)vname, &u.o); - } - } - if (code) { - afs_errno=code; - return NULL; - } - ret=malloc(sizeof(struct afs_volume)); - if (!ret) { - afs_errno=ENOMEM; - return NULL; - } - memset(ret,0,sizeof(struct afs_volume)); - strcpy(ret->name, u.u.name); - ret->nservers=0; - ret->cell=cell; - switch (type) { - case 0: - ret->id=u.u.volumeId[intype]; - for (srv=0;srv < u.u.nServers;srv++) { - if ((u.u.serverFlags[srv] & vtype) == 0) - continue; - //printf("uvldbentry server %d flags: %x\n",srv, u.u.serverFlags[srv]); + type = 0; + code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, (char *)vname, &u.u); + if (code == RXGEN_OPCODE) { + type = 1; + code = + ubik_VL_GetEntryByNameN(cell->vlservers, 0, (char *)vname, &u.n); + if (code == RXGEN_OPCODE) { + type = 2; + code = ubik_VL_GetEntryByNameO(cell->vlservers, 0, (char *)vname, + &u.o); + } + } + if (code != 0) { + afscp_errno = code; + return NULL; + } + ret = malloc(sizeof(struct afscp_volume)); + if (ret == NULL) { + afscp_errno = ENOMEM; + return NULL; + } + memset(ret, 0, sizeof(struct afscp_volume)); + strlcpy(ret->name, u.u.name, sizeof(ret->name)); + ret->nservers = 0; + ret->cell = cell; + switch (type) { + case 0: + ret->id = u.u.volumeId[intype]; + for (srv = 0; srv < u.u.nServers; srv++) { + if ((u.u.serverFlags[srv] & vtype) == 0) + continue; + afs_dprintf(("uvldbentry server %d flags: %x\n", srv, + u.u.serverFlags[srv])); - if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0) - server=afs_serverbyaddr(cell, u.u.serverNumber[srv].time_low); - else - server=afs_serverbyid(cell, &u.u.serverNumber[srv]); - if (!server) - continue; - ret->servers[ret->nservers++]=server->index; - } - break; - case 1: - ret->id=u.n.volumeId[intype]; - for (srv=0;srv < u.n.nServers;srv++) { - if ((u.n.serverFlags[srv] & vtype) == 0) - continue; - server=afs_serverbyaddr(cell, u.n.serverNumber[srv]); - if (!server) - continue; - ret->servers[ret->nservers++]=server->index; - } - break; - case 2: - ret->id=u.o.volumeId[intype]; - for (srv=0;srv < u.o.nServers;srv++) { - if ((u.o.serverFlags[srv] & vtype) == 0) - continue; - server=afs_serverbyaddr(cell, u.o.serverNumber[srv]); - if (!server) - continue; - ret->servers[ret->nservers++]=server->index; - } - break; - } - if (!ret->nservers || !ret->id) { - free(ret); - return NULL; - } + if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0) + server = + afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low); + else + server = afscp_ServerById(cell, &u.u.serverNumber[srv]); + if (!server) + continue; + ret->servers[ret->nservers++] = server->index; + } + break; + case 1: + ret->id = u.n.volumeId[intype]; + for (srv = 0; srv < u.n.nServers; srv++) { + if ((u.n.serverFlags[srv] & vtype) == 0) + continue; + server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]); + if (!server) + continue; + ret->servers[ret->nservers++] = server->index; + } + break; + case 2: + ret->id = u.o.volumeId[intype]; + for (srv = 0; srv < u.o.nServers; srv++) { + if ((u.o.serverFlags[srv] & vtype) == 0) + continue; + server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]); + if (!server) + continue; + ret->servers[ret->nservers++] = server->index; + } + break; + } + if (!ret->nservers || !ret->id) { + free(ret); + return NULL; + } - ret->voltype=intype; - server=afs_serverbyindex(ret->servers[0]); - if (server) - i.s_addr=server->addrs[0]; - else - i.s_addr=0; - afscp_dprintf(("New volume BYNAME %s (%lu) on %s (%d)\n", ret->name, ret->id, inet_ntoa(i),ret->servers[0])); - s=tsearch(&key, &cell->volsbyname, ncompare); - if (s) - *(struct afs_volume **)s=ret; - key.id=ret->id; - s=tsearch(&key, &cell->volsbyid, icompare); - if (s) - *(struct afs_volume **)s=ret; - return ret; + ret->voltype = intype; + server = afscp_ServerByIndex(ret->servers[0]); + /* if (server != NULL) + * i.s_addr = server->addrs[0]; + * else + * i.s_addr = 0; */ + /* i.s_addr is set but not used later */ + afs_dprintf(("New volume BYNAME %s (%lu) on %s (%d)\n", ret->name, + afs_printable_uint32_lu(ret->id), + inet_ntoa(i), ret->servers[0])); + s = tsearch(&key, &cell->volsbyname, ncompare); + if (s) + *(struct afscp_volume **)s = ret; + key.id = ret->id; + s = tsearch(&key, &cell->volsbyid, icompare); + if (s) + *(struct afscp_volume **)s = ret; + return ret; } -struct afs_volume *afs_volumebyid(struct afs_cell *cell, afs_uint32 id) +struct afscp_volume * +afscp_VolumeById(struct afscp_cell *cell, afs_uint32 id) { - union allvldbentry u; - struct afs_volume *ret,key; - struct afs_server *server; - afs_int32 code,vtype,type,srv; - int voltype; - char idbuffer[16]; - void *s; - struct in_addr i; + union allvldbentry u; + struct afscp_volume *ret, key; + struct afscp_server *server; + afs_int32 code, vtype, type, srv; + int voltype = -1; + char idbuffer[16]; + void *s; + /* struct in_addr i; */ - memset(&key,0, sizeof(key)); - key.id=id; - s=tfind(&key, &cell->volsbyid, icompare); - if (s) { - ret=*(struct afs_volume **)s; - return ret; - } + memset(&key, 0, sizeof(key)); + key.id = id; + s = tfind(&key, &cell->volsbyid, icompare); + if (s) { + ret = *(struct afscp_volume **)s; + return ret; + } - sprintf(idbuffer,"%" PRIu32, id); - type=0; - if ((code=ubik_VL_GetEntryByNameU(cell->vlservers, 0, idbuffer, &u.u)) - == RXGEN_OPCODE) { - type=1; - if ((code=ubik_VL_GetEntryByIDN(cell->vlservers, 0, id, -1, &u.n)) - == RXGEN_OPCODE) { - type=2; - code=ubik_VL_GetEntryByID(cell->vlservers, 0, id, -1, &u.o); - } - } - if (code) { - afs_errno=code; - return NULL; - } - ret=malloc(sizeof(struct afs_volume)); - if (!ret) { - afs_errno=ENOMEM; - return NULL; - } + snprintf(idbuffer, sizeof(idbuffer), "%lu", afs_printable_uint32_lu(id)); + type = 0; + code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, idbuffer, &u.u); + if (code == RXGEN_OPCODE) { + type = 1; + code = ubik_VL_GetEntryByIDN(cell->vlservers, 0, id, -1, &u.n); + if (code == RXGEN_OPCODE) { + type = 2; + code = ubik_VL_GetEntryByID(cell->vlservers, 0, id, -1, &u.o); + } + } + if (code != 0) { + afscp_errno = code; + return NULL; + } + ret = malloc(sizeof(struct afscp_volume)); + if (ret == NULL) { + afscp_errno = ENOMEM; + return NULL; + } + memset(ret, 0, sizeof(struct afscp_volume)); + strlcpy(ret->name, u.u.name, sizeof(ret->name)); + ret->nservers = 0; + ret->cell = cell; - memset(ret,0,sizeof(struct afs_volume)); - strcpy(ret->name, u.u.name); - ret->nservers=0; - ret->cell=cell; - - switch (type) { - case 0: - if (id == u.u.volumeId[RWVOL]) { - vtype=VLSF_RWVOL; - voltype=VOLTYPE_RW; - } else if (id == u.u.volumeId[ROVOL]) { - vtype=VLSF_ROVOL; - voltype=VOLTYPE_RO; - } else if (id == u.u.volumeId[BACKVOL]) { - vtype=VLSF_BACKVOL; - voltype=VOLTYPE_BK; - } else { - vtype=0; - voltype=-1; - } - for (srv=0;srv < u.u.nServers;srv++) { - if ((u.u.serverFlags[srv] & vtype) == 0) - continue; - if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0) - server=afs_serverbyaddr(cell, u.u.serverNumber[srv].time_low); - else - server=afs_serverbyid(cell, &u.u.serverNumber[srv]); - if (!server) - continue; - ret->servers[ret->nservers++]=server->index; - } - break; - case 1: - if (id == u.n.volumeId[RWVOL]) { - vtype=VLSF_RWVOL; - voltype=VOLTYPE_RW; - } else if (id == u.n.volumeId[ROVOL]) { - vtype=VLSF_ROVOL; - voltype=VOLTYPE_RO; - } else if (id == u.n.volumeId[BACKVOL]) { - vtype=VLSF_BACKVOL; - voltype=VOLTYPE_BK; - } else { - vtype=0; - voltype=-1; - } - for (srv=0;srv < u.n.nServers;srv++) { - if ((u.n.serverFlags[srv] & vtype) == 0) - continue; - server=afs_serverbyaddr(cell, u.n.serverNumber[srv]); - if (!server) - continue; - ret->servers[ret->nservers++]=server->index; - } - break; - case 2: - if (id == u.o.volumeId[RWVOL]) { - vtype=VLSF_RWVOL; - voltype=VOLTYPE_RW; - } else if (id == u.o.volumeId[ROVOL]) { - vtype=VLSF_ROVOL; - voltype=VOLTYPE_RO; - } else if (id == u.o.volumeId[BACKVOL]) { - vtype=VLSF_BACKVOL; - voltype=VOLTYPE_BK; - } else { - vtype=0; - voltype=-1; - } - for (srv=0;srv < u.o.nServers;srv++) { - if ((u.o.serverFlags[srv] & vtype) == 0) - continue; - server=afs_serverbyaddr(cell, u.o.serverNumber[srv]); - if (!server) - continue; - ret->servers[ret->nservers++]=server->index; - } - break; - } - ret->voltype=voltype; - server=afs_serverbyindex(ret->servers[0]); - if (server) - i.s_addr=server->addrs[0]; - else - i.s_addr=0; - afscp_dprintf(("New volume BYID %s (%lu) on %s (%d)\n", ret->name, ret->id, inet_ntoa(i), ret->servers[0])); - s=tsearch(&key, &cell->volsbyid, icompare); - if (s) - *(struct afs_volume **)s=ret; - strcpy(key.name, ret->name); - s=tsearch(&key, &cell->volsbyname, ncompare); - if (s) - *(struct afs_volume **)s=ret; - return ret; + switch (type) { + case 0: + if (id == u.u.volumeId[RWVOL]) { + vtype = VLSF_RWVOL; + voltype = RWVOL; + } else if (id == u.u.volumeId[ROVOL]) { + vtype = VLSF_ROVOL; + voltype = ROVOL; + } else if (id == u.u.volumeId[BACKVOL]) { + vtype = VLSF_BACKVOL; + voltype = BACKVOL; + } else { + vtype = 0; + voltype = -1; + } + for (srv = 0; srv < u.u.nServers; srv++) { + if ((u.u.serverFlags[srv] & vtype) == 0) + continue; + if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0) + server = + afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low); + else + server = afscp_ServerById(cell, &u.u.serverNumber[srv]); + if (!server) + continue; + ret->servers[ret->nservers++] = server->index; + } + break; + case 1: + if (id == u.n.volumeId[RWVOL]) { + vtype = VLSF_RWVOL; + voltype = RWVOL; + } else if (id == u.n.volumeId[ROVOL]) { + vtype = VLSF_ROVOL; + voltype = ROVOL; + } else if (id == u.n.volumeId[BACKVOL]) { + vtype = VLSF_BACKVOL; + voltype = BACKVOL; + } else { + vtype = 0; + voltype = -1; + } + for (srv = 0; srv < u.n.nServers; srv++) { + if ((u.n.serverFlags[srv] & vtype) == 0) + continue; + server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]); + if (server == NULL) + continue; + ret->servers[ret->nservers++] = server->index; + } + break; + case 2: + if (id == u.o.volumeId[RWVOL]) { + vtype = VLSF_RWVOL; + voltype = RWVOL; + } else if (id == u.o.volumeId[ROVOL]) { + vtype = VLSF_ROVOL; + voltype = ROVOL; + } else if (id == u.o.volumeId[BACKVOL]) { + vtype = VLSF_BACKVOL; + voltype = BACKVOL; + } else { + vtype = 0; + voltype = -1; + } + for (srv = 0; srv < u.o.nServers; srv++) { + if ((u.o.serverFlags[srv] & vtype) == 0) + continue; + server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]); + if (server == NULL) + continue; + ret->servers[ret->nservers++] = server->index; + } + break; + } + ret->voltype = voltype; + server = afscp_ServerByIndex(ret->servers[0]); + /* if (server) + * i.s_addr = server->addrs[0]; + * else + * i.s_addr = 0; */ + /* i.s_addr is set but not referenced later */ + afs_dprintf(("New volume BYID %s (%lu) on %s (%d)\n", ret->name, + afs_printable_uint32_lu(ret->id), inet_ntoa(i), + ret->servers[0])); + s = tsearch(&key, &cell->volsbyid, icompare); + if (s) + *(struct afscp_volume **)s = ret; + strlcpy(key.name, ret->name, sizeof(key.name)); + s = tsearch(&key, &cell->volsbyname, ncompare); + if (s) + *(struct afscp_volume **)s = ret; + return ret; } -