diff --git a/docs/PreReleaseNotes.txt b/docs/PreReleaseNotes.txt index 1d92819a3fc..0caa78357dd 100644 --- a/docs/PreReleaseNotes.txt +++ b/docs/PreReleaseNotes.txt @@ -6,11 +6,14 @@ Prerelease Notes ================ + **New Features** + * [Server] Fixes #345 - add sid to TOD structure (ABI compliant). * [Server] Implement resource selection affinity (primarily for ssi). + **Major bug fixes** + * [Authentication/sss] Fix dynamic id incompatability introduced in 4.0. + **Minor bug fixes** + * [Server] Fixes #344 - squash path before checking for static redirect. * [Server] Free Entity before replacing it from the cache (memleak). + **Miscellaneous** diff --git a/packaging/rhel/xrootd.functions b/packaging/rhel/xrootd.functions index c0a9ec51926..a4639c0bc9b 100644 --- a/packaging/rhel/xrootd.functions +++ b/packaging/rhel/xrootd.functions @@ -139,10 +139,15 @@ function stopDaemon() { echo -n "Shutting down xrootd ($1, $5): " PIDFILE="/var/run/xrootd/$1-$5.pid" - killproc -p $PIDFILE $1 - RETVAL=$? + if [ -e $PIDFILE ]; then + killproc -p $PIDFILE $1 + RETVAL=$? + echo + return $RETVAL + fi + echo -n "$1-$5 not running" echo - return $RETVAL + return 0 } #------------------------------------------------------------------------------- diff --git a/src/XrdCeph/XrdCephPosix.cc b/src/XrdCeph/XrdCephPosix.cc index 644490ca00a..d0fadbeff60 100644 --- a/src/XrdCeph/XrdCephPosix.cc +++ b/src/XrdCeph/XrdCephPosix.cc @@ -42,6 +42,7 @@ #include #include #include "XrdSfs/XrdSfsAio.hh" +#include "XrdSys/XrdSysPthread.hh" #include "XrdCeph/XrdCephPosix.hh" @@ -69,22 +70,79 @@ struct DirIterator { /// small struct for aio API callbacks struct AioArgs { - AioArgs(XrdSfsAio* a, AioCB *b, size_t n) : aiop(a), callback(b), nbBytes(n) {} + AioArgs(XrdSfsAio* a, AioCB *b, size_t n, ceph::bufferlist *_bl=0) : + aiop(a), callback(b), nbBytes(n), bl(_bl) {} XrdSfsAio* aiop; AioCB *callback; size_t nbBytes; + ceph::bufferlist *bl; }; /// global variables holding stripers and ioCtxs for each ceph pool plus the cluster object std::map g_radosStripers; std::map g_ioCtx; librados::Rados* g_cluster = 0; -/// global variable holding a map of file descriptor to file reference -std::map g_fds; +/// mutex protecting the striper and ioctx maps +XrdSysMutex g_striper_mutex; + /// global variable holding a list of files currently opened for write std::multiset g_filesOpenForWrite; +/// global variable holding a map of file descriptor to file reference +std::map g_fds; /// global variable remembering the next available file descriptor unsigned int g_nextCephFd = 0; +/// mutex protecting the map of file descriptors and the openForWrite multiset +XrdSysMutex g_fd_mutex; + +/// check whether a file is open for write +bool isOpenForWrite(std::string& name) { + XrdSysMutexHelper lock(g_fd_mutex); + return g_filesOpenForWrite.find(name) != g_filesOpenForWrite.end(); +} + +/// insert a filename in the list of files opened for write +void insertOpenForWrite(std::string& name) { + XrdSysMutexHelper lock(g_fd_mutex); + g_filesOpenForWrite.insert(name); +} + +/// delete a filename from the list of files opened for write +void deleteOpenForWrite(std::string& name) { + XrdSysMutexHelper lock(g_fd_mutex); + g_filesOpenForWrite.erase(g_filesOpenForWrite.find(name)); +} + +/// look for a FileRef from its file descriptor +CephFileRef* getFileRef(int fd) { + XrdSysMutexHelper lock(g_fd_mutex); + std::map::iterator it = g_fds.find(fd); + if (it != g_fds.end()) { + return &(it->second); + } else { + return 0; + } +} + +/// deletes a FileRef from the global table of file descriptors +void deleteFileRef(int fd) { + XrdSysMutexHelper lock(g_fd_mutex); + std::map::iterator it = g_fds.find(fd); + if (it != g_fds.end()) { + g_fds.erase(it); + } +} + +/** + * inserts a new FileRef into the global table of file descriptors + * and return the associated file descriptor + */ +int insertFileRef(CephFileRef &fr) { + XrdSysMutexHelper lock(g_fd_mutex); + g_fds[g_nextCephFd] = fr; + g_nextCephFd++; + return g_nextCephFd-1; +} + /// global variable containing defaults for CephFiles CephFile g_defaultParams = { "", "default", // default pool @@ -311,7 +369,7 @@ static CephFileRef getCephFileRef(const char *path, XrdOucEnv *env, int flags, return fr; } -static libradosstriper::RadosStriper* getRadosStriper(const CephFile& file) { +static libradosstriper::RadosStriper* getRadosStriperNoLock(const CephFile& file) { std::stringstream ss; ss << file.userId << '@' << file.pool << ',' << file.nbStripes << ',' << file.stripeUnit << ',' << file.objectSize; @@ -420,8 +478,14 @@ static libradosstriper::RadosStriper* getRadosStriper(const CephFile& file) { return it->second; } +static libradosstriper::RadosStriper* getRadosStriper(const CephFile& file) { + XrdSysMutexHelper lock(g_striper_mutex); + return getRadosStriperNoLock(file); +} + static librados::IoCtx* getIoCtx(const CephFile& file) { - libradosstriper::RadosStriper *striper = getRadosStriper(file); + XrdSysMutexHelper lock(g_striper_mutex); + libradosstriper::RadosStriper *striper = getRadosStriperNoLock(file); if (0 == striper) { return 0; } @@ -433,6 +497,7 @@ static librados::IoCtx* getIoCtx(const CephFile& file) { } void ceph_posix_disconnect_all() { + XrdSysMutexHelper lock(g_striper_mutex); for (std::map::iterator it = g_radosStripers.begin(); it != g_radosStripers.end(); @@ -456,12 +521,11 @@ void ceph_posix_set_logfunc(void (*logfunc) (char *, va_list argp)) { static int ceph_posix_internal_truncate(const CephFile &file, unsigned long long size); int ceph_posix_open(XrdOucEnv* env, const char *pathname, int flags, mode_t mode) { - logwrapper((char*)"ceph_open : fd %d associated to %s", g_nextCephFd, pathname); CephFileRef fr = getCephFileRef(pathname, env, flags, mode, 0); - g_fds[g_nextCephFd] = fr; - g_nextCephFd++; + int fd = insertFileRef(fr); + logwrapper((char*)"ceph_open : fd %d associated to %s", fd, pathname); if (flags & (O_WRONLY|O_RDWR)) { - g_filesOpenForWrite.insert(fr.name); + insertOpenForWrite(fr.name); } // in case of O_CREAT and O_EXCL, we should complain if the file exists if ((flags & O_CREAT) && (flags & O_EXCL)) { @@ -480,17 +544,17 @@ int ceph_posix_open(XrdOucEnv* env, const char *pathname, int flags, mode_t mode // fail only if file exists and cannot be truncated if (rc < 0 && rc != -ENOENT) return rc; } - return g_nextCephFd-1; + return fd; } int ceph_posix_close(int fd) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_close: closed fd %d", fd); - if (it->second.flags & (O_WRONLY|O_RDWR)) { - g_filesOpenForWrite.erase(g_filesOpenForWrite.find(it->second.name)); + if (fr->flags & (O_WRONLY|O_RDWR)) { + deleteOpenForWrite(fr->name); } - g_fds.erase(it); + deleteFileRef(fd); return 0; } else { return -EBADF; @@ -512,44 +576,41 @@ static off64_t lseek_compute_offset(CephFileRef &fr, off64_t offset, int whence) } off_t ceph_posix_lseek(int fd, off_t offset, int whence) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_lseek: for fd %d, offset=%lld, whence=%d", fd, offset, whence); - return (off_t)lseek_compute_offset(fr, offset, whence); + return (off_t)lseek_compute_offset(*fr, offset, whence); } else { return -EBADF; } } off64_t ceph_posix_lseek64(int fd, off64_t offset, int whence) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_lseek64: for fd %d, offset=%lld, whence=%d", fd, offset, whence); - return lseek_compute_offset(fr, offset, whence); + return lseek_compute_offset(*fr, offset, whence); } else { return -EBADF; } } ssize_t ceph_posix_write(int fd, const void *buf, size_t count) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_write: for fd %d, count=%d", fd, count); - if ((fr.flags & (O_WRONLY|O_RDWR)) == 0) { + if ((fr->flags & (O_WRONLY|O_RDWR)) == 0) { return -EBADF; } - libradosstriper::RadosStriper *striper = getRadosStriper(fr); + libradosstriper::RadosStriper *striper = getRadosStriper(*fr); if (0 == striper) { return -EINVAL; } ceph::bufferlist bl; bl.append((const char*)buf, count); - int rc = striper->write(fr.name, bl, count, fr.offset); + int rc = striper->write(fr->name, bl, count, fr->offset); if (rc) return rc; - fr.offset += count; + fr->offset += count; return count; } else { return -EBADF; @@ -557,20 +618,19 @@ ssize_t ceph_posix_write(int fd, const void *buf, size_t count) { } ssize_t ceph_posix_pwrite(int fd, const void *buf, size_t count, off64_t offset) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_write: for fd %d, count=%d", fd, count); - if ((fr.flags & (O_WRONLY|O_RDWR)) == 0) { + if ((fr->flags & (O_WRONLY|O_RDWR)) == 0) { return -EBADF; } - libradosstriper::RadosStriper *striper = getRadosStriper(fr); + libradosstriper::RadosStriper *striper = getRadosStriper(*fr); if (0 == striper) { return -EINVAL; } ceph::bufferlist bl; bl.append((const char*)buf, count); - int rc = striper->write(fr.name, bl, count, offset); + int rc = striper->write(fr->name, bl, count, offset); if (rc) return rc; return count; } else { @@ -578,7 +638,7 @@ ssize_t ceph_posix_pwrite(int fd, const void *buf, size_t count, off64_t offset) } } -static void ceph_aio_complete(rados_completion_t c, void *arg) { +static void ceph_aio_write_complete(rados_completion_t c, void *arg) { AioArgs *awa = reinterpret_cast(arg); size_t rc = rados_aio_get_return_value(c); awa->callback(awa->aiop, rc == 0 ? awa->nbBytes : rc); @@ -586,19 +646,18 @@ static void ceph_aio_complete(rados_completion_t c, void *arg) { } ssize_t ceph_aio_write(int fd, XrdSfsAio *aiop, AioCB *cb) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { + CephFileRef* fr = getFileRef(fd); + if (fr) { // get the parameters from the Xroot aio object size_t count = aiop->sfsAio.aio_nbytes; const char *buf = (const char*)aiop->sfsAio.aio_buf; size_t offset = aiop->sfsAio.aio_offset; // get the striper object - CephFileRef &fr = it->second; logwrapper((char*)"ceph_aio_write: for fd %d, count=%d", fd, count); - if ((fr.flags & (O_WRONLY|O_RDWR)) == 0) { + if ((fr->flags & (O_WRONLY|O_RDWR)) == 0) { return -EBADF; } - libradosstriper::RadosStriper *striper = getRadosStriper(fr); + libradosstriper::RadosStriper *striper = getRadosStriper(*fr); if (0 == striper) { return -EINVAL; } @@ -608,32 +667,31 @@ ssize_t ceph_aio_write(int fd, XrdSfsAio *aiop, AioCB *cb) { // prepare a ceph AioCompletion object and do async call AioArgs *args = new AioArgs(aiop, cb, count); librados::AioCompletion *completion = - g_cluster->aio_create_completion(args, ceph_aio_complete, NULL); - int rc = striper->aio_write(fr.name, completion, bl, count, offset); + g_cluster->aio_create_completion(args, ceph_aio_write_complete, NULL); + int rc = striper->aio_write(fr->name, completion, bl, count, offset); completion->release(); return rc; } else { return -EBADF; } -} +} ssize_t ceph_posix_read(int fd, void *buf, size_t count) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_read: for fd %d, count=%d", fd, count); - if ((fr.flags & (O_WRONLY|O_RDWR)) != 0) { + if ((fr->flags & (O_WRONLY|O_RDWR)) != 0) { return -EBADF; } - libradosstriper::RadosStriper *striper = getRadosStriper(fr); + libradosstriper::RadosStriper *striper = getRadosStriper(*fr); if (0 == striper) { return -EINVAL; } ceph::bufferlist bl; - int rc = striper->read(fr.name, &bl, count, fr.offset); + int rc = striper->read(fr->name, &bl, count, fr->offset); if (rc < 0) return rc; bl.copy(0, rc, (char*)buf); - fr.offset += rc; + fr->offset += rc; return rc; } else { return -EBADF; @@ -641,19 +699,18 @@ ssize_t ceph_posix_read(int fd, void *buf, size_t count) { } ssize_t ceph_posix_pread(int fd, void *buf, size_t count, off64_t offset) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_read: for fd %d, count=%d", fd, count); - if ((fr.flags & (O_WRONLY|O_RDWR)) != 0) { + if ((fr->flags & (O_WRONLY|O_RDWR)) != 0) { return -EBADF; } - libradosstriper::RadosStriper *striper = getRadosStriper(fr); + libradosstriper::RadosStriper *striper = getRadosStriper(*fr); if (0 == striper) { return -EINVAL; } ceph::bufferlist bl; - int rc = striper->read(fr.name, &bl, count, offset); + int rc = striper->read(fr->name, &bl, count, offset); if (rc < 0) return rc; bl.copy(0, rc, (char*)buf); return rc; @@ -662,33 +719,43 @@ ssize_t ceph_posix_pread(int fd, void *buf, size_t count, off64_t offset) { } } +static void ceph_aio_read_complete(rados_completion_t c, void *arg) { + AioArgs *awa = reinterpret_cast(arg); + size_t rc = rados_aio_get_return_value(c); + if (awa->bl) { + if (rc > 0) { + awa->bl->copy(0, rc, (char*)awa->aiop->sfsAio.aio_buf); + } + delete awa->bl; + awa->bl = 0; + } + awa->callback(awa->aiop, rc == 0 ? awa->nbBytes : rc); + delete(awa); +} + ssize_t ceph_aio_read(int fd, XrdSfsAio *aiop, AioCB *cb) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { + CephFileRef* fr = getFileRef(fd); + if (fr) { // get the parameters from the Xroot aio object size_t count = aiop->sfsAio.aio_nbytes; - const char *buf = (const char*)aiop->sfsAio.aio_buf; size_t offset = aiop->sfsAio.aio_offset; // get the striper object - CephFileRef &fr = it->second; logwrapper((char*)"ceph_read: for fd %d, count=%d", fd, count); - if ((fr.flags & (O_WRONLY|O_RDWR)) != 0) { + if ((fr->flags & (O_WRONLY|O_RDWR)) != 0) { return -EBADF; } - libradosstriper::RadosStriper *striper = getRadosStriper(fr); + libradosstriper::RadosStriper *striper = getRadosStriper(*fr); if (0 == striper) { return -EINVAL; } // prepare a bufferlist to receive data - ceph::bufferlist bl; + ceph::bufferlist *bl = new ceph::bufferlist(); // prepare a ceph AioCompletion object and do async call - AioArgs *args = new AioArgs(aiop, cb, count); + AioArgs *args = new AioArgs(aiop, cb, count, bl); librados::AioCompletion *completion = - g_cluster->aio_create_completion(args, ceph_aio_complete, NULL); - int rc = striper->aio_read(fr.name, completion, &bl, count, offset); + g_cluster->aio_create_completion(args, ceph_aio_read_complete, NULL); + int rc = striper->aio_read(fr->name, completion, bl, count, offset); completion->release(); - if (rc < 0) return rc; - bl.copy(0, rc, (char*)buf); return rc; } else { return -EBADF; @@ -696,19 +763,18 @@ ssize_t ceph_aio_read(int fd, XrdSfsAio *aiop, AioCB *cb) { } int ceph_posix_fstat(int fd, struct stat *buf) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_stat: fd %d", fd); // minimal stat : only size and times are filled // atime, mtime and ctime are set all to the same value // mode is set arbitrarily to 0666 - libradosstriper::RadosStriper *striper = getRadosStriper(fr); + libradosstriper::RadosStriper *striper = getRadosStriper(*fr); if (0 == striper) { return -EINVAL; } memset(buf, 0, sizeof(*buf)); - int rc = striper->stat(fr.name, (uint64_t*)&(buf->st_size), &(buf->st_atime)); + int rc = striper->stat(fr->name, (uint64_t*)&(buf->st_size), &(buf->st_atime)); if (rc != 0) { return -rc; } @@ -736,7 +802,7 @@ int ceph_posix_stat(XrdOucEnv* env, const char *pathname, struct stat *buf) { if (rc != 0) { // for non existing file. Check that we did not open it for write recently // in that case, we return 0 size and current time - if (-ENOENT == rc && g_filesOpenForWrite.find(file.name) != g_filesOpenForWrite.end()) { + if (-ENOENT == rc && isOpenForWrite(file.name)) { buf->st_size = 0; buf->st_atime = time(NULL); } else { @@ -750,8 +816,8 @@ int ceph_posix_stat(XrdOucEnv* env, const char *pathname, struct stat *buf) { } int ceph_posix_fsync(int fd) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_sync: fd %d", fd); return 0; } else { @@ -760,14 +826,13 @@ int ceph_posix_fsync(int fd) { } int ceph_posix_fcntl(int fd, int cmd, ... /* arg */ ) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_fcntl: fd %d cmd=%d", fd, cmd); // minimal implementation switch (cmd) { case F_GETFL: - return fr.mode; + return fr->mode; default: return -EINVAL; } @@ -799,11 +864,10 @@ ssize_t ceph_posix_getxattr(XrdOucEnv* env, const char* path, ssize_t ceph_posix_fgetxattr(int fd, const char* name, void* value, size_t size) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_fgetxattr: fd %d name=%s", fd, name); - return ceph_posix_internal_getxattr(fr, name, value, size); + return ceph_posix_internal_getxattr(*fr, name, value, size); } else { return -EBADF; } @@ -834,11 +898,10 @@ ssize_t ceph_posix_setxattr(XrdOucEnv* env, const char* path, int ceph_posix_fsetxattr(int fd, const char* name, const void* value, size_t size, int flags) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_fsetxattr: fd %d name=%s value=%s", fd, name, value); - return ceph_posix_internal_setxattr(fr, name, value, size, flags); + return ceph_posix_internal_setxattr(*fr, name, value, size, flags); } else { return -EBADF; } @@ -863,11 +926,10 @@ int ceph_posix_removexattr(XrdOucEnv* env, const char* path, } int ceph_posix_fremovexattr(int fd, const char* name) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_fremovexattr: fd %d name=%s", fd, name); - return ceph_posix_internal_removexattr(fr, name); + return ceph_posix_internal_removexattr(*fr, name); } else { return -EBADF; } @@ -913,11 +975,10 @@ int ceph_posix_listxattrs(XrdOucEnv* env, const char* path, XrdSysXAttr::AList * } int ceph_posix_flistxattrs(int fd, XrdSysXAttr::AList **aPL, int getSz) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_flistxattrs: fd %d", fd); - return ceph_posix_internal_listxattrs(fr, aPL, getSz); + return ceph_posix_internal_listxattrs(*fr, aPL, getSz); } else { return -EBADF; } @@ -952,11 +1013,10 @@ static int ceph_posix_internal_truncate(const CephFile &file, unsigned long long } int ceph_posix_ftruncate(int fd, unsigned long long size) { - std::map::iterator it = g_fds.find(fd); - if (it != g_fds.end()) { - CephFileRef &fr = it->second; + CephFileRef* fr = getFileRef(fd); + if (fr) { logwrapper((char*)"ceph_posix_ftruncate: fd %d, size %d", fd, size); - return ceph_posix_internal_truncate(fr, size); + return ceph_posix_internal_truncate(*fr, size); } else { return -EBADF; } diff --git a/src/XrdCl/XrdClXRootDMsgHandler.cc b/src/XrdCl/XrdClXRootDMsgHandler.cc index d64c9ef1331..060a3dab0e5 100644 --- a/src/XrdCl/XrdClXRootDMsgHandler.cc +++ b/src/XrdCl/XrdClXRootDMsgHandler.cc @@ -445,19 +445,55 @@ namespace XrdCl if( pUrl.GetPassword() != "" && newUrl.GetPassword() == "" ) newUrl.SetPassword( pUrl.GetPassword() ); - pUrl = newUrl; - pRedirectUrl = newUrl.GetURL(); - - URL cgiURL; - if( urlComponents.size() > 1 ) - { - std::ostringstream o; - o << "fake://fake:111//fake?"; - o << urlComponents[1]; - pRedirectUrl += "?"; - pRedirectUrl += urlComponents[1]; - cgiURL = URL( o.str() ); - } + //---------------------------------------------------------------------- + // Forward any "xrd.*" params from the original client request also to + // the new redirection url + //---------------------------------------------------------------------- + std::ostringstream ossXrd; + const URL::ParamsMap &urlParams = pUrl.GetParams(); + + for(URL::ParamsMap::const_iterator it = urlParams.begin(); + it != urlParams.end(); ++it ) + { + if( it->first.compare( 0, 4, "xrd." ) ) + continue; + + ossXrd << it->first << '=' << it->second << '&'; + } + + std::string xrdCgi = ossXrd.str(); + pUrl = newUrl; + pRedirectUrl = newUrl.GetURL(); + + URL cgiURL; + if( urlComponents.size() > 1 ) + { + pRedirectUrl += "?"; + pRedirectUrl += urlComponents[1]; + std::ostringstream o; + o << "fake://fake:111//fake?"; + o << urlComponents[1]; + + if (!xrdCgi.empty()) + { + o << '&' << xrdCgi; + pRedirectUrl += '&'; + pRedirectUrl += xrdCgi; + } + + cgiURL = URL( o.str() ); + } + else { + if (!xrdCgi.empty()) + { + std::ostringstream o; + o << "fake://fake:111//fake?"; + o << xrdCgi; + cgiURL = URL( o.str() ); + pRedirectUrl += '?'; + pRedirectUrl += xrdCgi; + } + } //---------------------------------------------------------------------- // Check if we need to return the URL as a response @@ -1529,14 +1565,50 @@ namespace XrdCl pSidMgr->ReleaseSID( req->header.streamid ); pSidMgr = 0; AnyObject sidMgrObj; - st = pPostMaster->QueryTransport( pUrl, XRootDQuery::SIDManager, - sidMgrObj ); + // Append any "xrd.*" parameters present in newCgi so that any authentication + // requirements are properly enforced + std::string xrdCgi = ""; + std::ostringstream ossXrd; + for(URL::ParamsMap::const_iterator it = newCgi.begin(); + it != newCgi.end(); ++it ) + { + if( it->first.compare( 0, 4, "xrd." ) ) + continue; + + ossXrd << it->first << '=' << it->second << '&'; + } + + xrdCgi = ossXrd.str(); + // Redirection URL containing also any original xrd.* opaque parameters + XrdCl::URL authUrl; + + if (xrdCgi.empty()) + { + authUrl = pUrl; + } + else + { + std::string surl = pUrl.GetURL(); + (surl.find('?') == std::string::npos) ? (surl += '?') : + ((*surl.rbegin() != '&') ? (surl += '&') : (surl += "")); + surl += xrdCgi; + + if (!authUrl.FromString(surl)) + { + log->Error( XRootDMsg, "[%s] Failed to build redirection url from data:" + "%s", surl.c_str()); + return Status(stError, errInvalidRedirectURL); + } + } + + st = pPostMaster->QueryTransport( authUrl, XRootDQuery::SIDManager, + sidMgrObj ); if( !st.IsOK() ) { log->Error( XRootDMsg, "[%s] Impossible to send message %s.", - pUrl.GetHostId().c_str(), - pRequest->GetDescription().c_str() ); + pUrl.GetHostId().c_str(), + pRequest->GetDescription().c_str() ); return st; } @@ -1545,8 +1617,8 @@ namespace XrdCl if( !st.IsOK() ) { log->Error( XRootDMsg, "[%s] Impossible to send message %s.", - pUrl.GetHostId().c_str(), - pRequest->GetDescription().c_str() ); + pUrl.GetHostId().c_str(), + pRequest->GetDescription().c_str() ); return st; } diff --git a/src/XrdDig/XrdDigFS.cc b/src/XrdDig/XrdDigFS.cc index a30009448fe..75bc463053f 100644 --- a/src/XrdDig/XrdDigFS.cc +++ b/src/XrdDig/XrdDigFS.cc @@ -239,21 +239,30 @@ const char *XrdDigDirectory::nextEntry() // Read the next directory entry // +#ifdef __linux__ do{errno = 0; - if ((retc = readdir_r(dh, d_pnt, &rp))) - {if (retc && errno != 0) - XrdDigFS::Emsg(epname,error,retc,"read directory",fname); + rp = readdir(dh); + if (!rp) + {if (!(retc = errno)) {ateof = 1; error.clear();} + else XrdDigFS::Emsg(epname,error,retc,"read directory",fname); + d_pnt->d_name[0] = '\0'; + return (const char *)0; + } +#else +do{if ((retc = readdir_r(dh, d_pnt, &rp))) + {XrdDigFS::Emsg(epname,error,retc,"read directory",fname); d_pnt->d_name[0] = '\0'; return (const char *)0; } // Check if we have reached end of file // - if (retc || !rp || !d_pnt->d_name[0]) + if (!rp || !d_pnt->d_name[0]) {ateof = true; error.clear(); return (const char *)0; } +#endif // If autostat wanted, do so here // @@ -261,11 +270,11 @@ do{errno = 0; { #ifdef HAVE_FSTATAT int sFlags = (isProc ? AT_SYMLINK_NOFOLLOW : 0); - if (fstatat(dirFD, d_pnt->d_name, sBuff, sFlags)) continue; + if (fstatat(dirFD, rp->d_name, sBuff, sFlags)) continue; sBuff->st_mode = (sBuff->st_mode & wMask) | S_IRUSR; #else char dPath[2048]; - snprintf(dPath, sizeof(dPath), "%s%s", fname, d_pnt->d_name); + snprintf(dPath, sizeof(dPath), "%s%s", fname, rp->d_name); if (stat(dPath, sBuff)) continue; sBuff->st_mode = (sBuff->st_mode & wMask) | S_IRUSR; #endif @@ -279,12 +288,12 @@ do{errno = 0; {struct stat Stat, *sP = (sBuff ? sBuff : &Stat); char *dP; int n, rc; - rc = (sBuff ? 0:fstatat(dirFD,d_pnt->d_name,&Stat,AT_SYMLINK_NOFOLLOW)); + rc = (sBuff ? 0:fstatat(dirFD,rp->d_name,&Stat,AT_SYMLINK_NOFOLLOW)); if (!rc && !noTag && S_ISLNK(sP->st_mode)) - {n = strlen(d_pnt->d_name); - dP = d_pnt->d_name + n + 4; + {n = strlen(rp->d_name); + dP = rp->d_name + n + 4; n = sizeof(dirent_full.nbf) - (n + 8); - if ((n = readlinkat(dirFD,d_pnt->d_name,dP,n)) < 0) strcpy(dP,"?"); + if ((n = readlinkat(dirFD,rp->d_name,dP,n)) < 0) strcpy(dP,"?"); else *(dP+n) = 0; strncpy(dP-4, " -> ", 4); } @@ -293,7 +302,7 @@ do{errno = 0; // Return the actual entry // - return (const char *)(d_pnt->d_name); + return (const char *)(rp->d_name); } while(1); return 0; // Keep compiler happy } diff --git a/src/XrdSecsss/XrdSecProtocolsss.cc b/src/XrdSecsss/XrdSecProtocolsss.cc index d903e6676aa..612e2c9d60d 100644 --- a/src/XrdSecsss/XrdSecProtocolsss.cc +++ b/src/XrdSecsss/XrdSecProtocolsss.cc @@ -783,6 +783,7 @@ int XrdSecProtocolsss::getCred(XrdOucErrInfo *einfo, return Fatal(einfo, "getCred", EINVAL, "Invalid id string."); switch(idType) {case XrdSecsssRR_Data::theLgid: lidP = idP; break; + case XrdSecsssRR_Data::theHost: break; case XrdSecsssRR_Data::theRand: break; default: return Fatal(einfo,"getCred",EINVAL,"Invalid id type."); } diff --git a/src/XrdSfs/XrdSfsNative.cc b/src/XrdSfs/XrdSfsNative.cc index 9464219547f..34578af38fc 100644 --- a/src/XrdSfs/XrdSfsNative.cc +++ b/src/XrdSfs/XrdSfsNative.cc @@ -197,17 +197,26 @@ const char *XrdSfsNativeDirectory::nextEntry() // Read the next directory entry // +#ifdef __linux__ errno = 0; + rp = readdir(dh); + if (!rp) + {if (!(retc = errno)) {ateof = 1; error.clear();} + else XrdSfsNative::Emsg(epname,error,retc,"read directory",fname); + d_pnt->d_name[0] = '\0'; + return (const char *)0; + } + return (const char *)(rp->d_name); +#else if ((retc = readdir_r(dh, d_pnt, &rp))) - {if (retc && errno != 0) - XrdSfsNative::Emsg(epname,error,retc,"read directory",fname); + {XrdSfsNative::Emsg(epname,error,retc,"read directory",fname); d_pnt->d_name[0] = '\0'; return (const char *)0; } // Check if we have reached end of file // - if (retc || !rp || !d_pnt->d_name[0]) + if (!rp || !d_pnt->d_name[0]) {ateof = 1; error.clear(); return (const char *)0; @@ -216,6 +225,7 @@ const char *XrdSfsNativeDirectory::nextEntry() // Return the actual entry // return (const char *)(d_pnt->d_name); +#endif } /******************************************************************************/ diff --git a/src/XrdXrootd/XrdXrootdMonData.hh b/src/XrdXrootd/XrdXrootdMonData.hh index cc876e72233..8da90b8d01b 100644 --- a/src/XrdXrootd/XrdXrootdMonData.hh +++ b/src/XrdXrootd/XrdXrootdMonData.hh @@ -161,7 +161,8 @@ enum recFval {forced =0x01, // If recFlag == isClose close due to disconnect hasOPS =0x02, // If recFlag == isClose MonStatXFR + MonStatOPS hasSSQ =0x04, // If recFlag == isClose XFR + OPS + MonStatSSQ hasLFN =0x01, // If recFlag == isOpen the lfn is present - hasRW =0x02 // If recFlag == isOpen file opened r/w + hasRW =0x02, // If recFlag == isOpen file opened r/w + hasSID =0x01 // if recFlag == isTime sID is present (new rec) }; char recType; // RecTval: isClose | isOpen | isTime | isXfr @@ -183,8 +184,10 @@ struct XrdXrootdMonFileTOD XrdXrootdMonFileHdr Hdr; // 8 int tBeg; // time(0) of following record int tEnd; // time(0) when packet was sent +kXR_int64 sID; // Server id in lower 48 bits }; + // The following variable length structure exists in XrdXrootdMonFileOPN if // "lfn" has been specified. It exists only when recFlag & hasLFN is TRUE. // The user's dictid will be zero (missing) if user monitoring is not enabled. diff --git a/src/XrdXrootd/XrdXrootdMonFile.cc b/src/XrdXrootd/XrdXrootdMonFile.cc index a0fe8d59682..a13190c9ec1 100644 --- a/src/XrdXrootd/XrdXrootdMonFile.cc +++ b/src/XrdXrootd/XrdXrootdMonFile.cc @@ -38,6 +38,15 @@ #include "XrdXrootd/XrdXrootdMonFile.hh" #include "XrdXrootd/XrdXrootdFileStats.hh" +/******************************************************************************/ +/* G l o b a l s */ +/******************************************************************************/ + +namespace XrdXrootdMonInfo +{ +extern long long mySID; +} + /******************************************************************************/ /* S t a t i c M e m b e r s */ /******************************************************************************/ @@ -71,7 +80,7 @@ char XrdXrootdMonFile::fsOPS = 0; char XrdXrootdMonFile::fsSSQ = 0; char XrdXrootdMonFile::fsXFR = 0; char XrdXrootdMonFile::crecFlag = 0; - + /******************************************************************************/ /* C l o s e */ /******************************************************************************/ @@ -336,8 +345,9 @@ bool XrdXrootdMonFile::Init(XrdScheduler *sp, XrdSysError *errp, int bfsz) // repTOD = (XrdXrootdMonFileTOD *)(repBuff + sizeof(XrdXrootdMonHeader)); repTOD->Hdr.recType = XrdXrootdMonFileHdr::isTime; - repTOD->Hdr.recFlag = 0; + repTOD->Hdr.recFlag = XrdXrootdMonFileHdr::hasSID; repTOD->Hdr.recSize = htons(sizeof(XrdXrootdMonFileTOD)); + repTOD->sID = static_cast(XrdXrootdMonInfo::mySID); // Establish first real record in the buffer (always fixed) // diff --git a/src/XrdXrootd/XrdXrootdMonitor.cc b/src/XrdXrootd/XrdXrootdMonitor.cc index a12584eab9d..f1fac80b5bd 100644 --- a/src/XrdXrootd/XrdXrootdMonitor.cc +++ b/src/XrdXrootd/XrdXrootdMonitor.cc @@ -88,7 +88,6 @@ int XrdXrootdMonitor::rdrTOD = 0; int XrdXrootdMonitor::rdrWin = 0; int XrdXrootdMonitor::rdrNum = 3; kXR_int32 XrdXrootdMonitor::sizeWindow = 60; -long long XrdXrootdMonitor::mySID = 0; char XrdXrootdMonitor::sidName[16]= {0}; short XrdXrootdMonitor::sidSize = 0; char XrdXrootdMonitor::monINFO = 0; @@ -107,6 +106,13 @@ char XrdXrootdMonitor::monCLOCK = 0; extern XrdOucTrace *XrdXrootdTrace; +namespace XrdXrootdMonInfo +{ +long long mySID = 0; +} + +using namespace XrdXrootdMonInfo; + /******************************************************************************/ /* L o c a l D e f i n e s */ /******************************************************************************/ diff --git a/src/XrdXrootd/XrdXrootdMonitor.hh b/src/XrdXrootd/XrdXrootdMonitor.hh index f1244e9b511..0c9ab44dc47 100644 --- a/src/XrdXrootd/XrdXrootdMonitor.hh +++ b/src/XrdXrootd/XrdXrootdMonitor.hh @@ -256,7 +256,6 @@ static int isEnabled; static int numMonitor; static int monIdent; static int monRlen; -static long long mySID; static char sidName[16]; static short sidSize; static char monIO; diff --git a/src/XrdXrootd/XrdXrootdXeq.cc b/src/XrdXrootd/XrdXrootdXeq.cc index 4034a075a92..feb4d85916c 100644 --- a/src/XrdXrootd/XrdXrootdXeq.cc +++ b/src/XrdXrootd/XrdXrootdXeq.cc @@ -1224,16 +1224,15 @@ int XrdXrootdProtocol::do_Open() // doDig = (digFS && SFS_LCLPATH(fn)); -// Check if static redirection applies -// - if (!doDig && Route[RD_open1].Host[rdType] && (popt = RPList.Validate(fn))) - return Response.Send(kXR_redirect, Route[popt].Port[rdType], - Route[popt].Host[rdType]); - -// Validate the path +// Validate the path and then check if static redirection applies // if (doDig) {popt = XROOTDXP_NOLK; opC = 0;} - else if (!(popt = Squash(fn))) return vpEmsg("Opening", fn); + else {int ropt; + if (!(popt = Squash(fn))) return vpEmsg("Opening", fn); + if (Route[RD_open1].Host[rdType] && (ropt = RPList.Validate(fn))) + return Response.Send(kXR_redirect, Route[ropt].Port[rdType], + Route[ropt].Host[rdType]); + } // Add the multi-write option if this path supports it //