diff --git a/Makefile b/Makefile index 895615e72..b3f945ad1 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ ifeq ($(PANDOC),"") $(warning "pandoc does not appear available: manpage won't be buildable") endif -XATTR_AVAILABLE = $(shell test ! -e /usr/include/attr/xattr.h; echo $$?) +XATTR_AVAILABLE = $(shell test ! -e /usr/include/attr/xattr.h -a ! -e /usr/include/sys/xattr.h; echo $$?) FUSE_AVAILABLE = $(shell ! pkg-config --exists fuse; echo $$?) diff --git a/src/fs.cpp b/src/fs.cpp index 31a2a521e..43c5fb917 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -151,7 +151,7 @@ namespace fs return -1; dev = st.st_dev; - for(int i = 0, ei = srcmounts.size(); i != ei; i++) + for(size_t i = 0, ei = srcmounts.size(); i != ei; i++) { fs::path::make(&srcmounts[i],fusepath,fullpath); @@ -223,7 +223,7 @@ namespace fs const uint64_t minfreespace, string &path) { - fsblkcnt_t mfs; + uint64_t mfs; const string *mfsbasepath; mfs = 0; diff --git a/src/fs_acl.cpp b/src/fs_acl.cpp index 65b40bb25..81f906764 100644 --- a/src/fs_acl.cpp +++ b/src/fs_acl.cpp @@ -30,12 +30,12 @@ namespace fs bool dir_has_defaults(const std::string &fullpath) { - int rv; + ssize_t rv; std::string dirpath = fullpath; fs::path::dirname(dirpath); - rv = fs::lgetxattr(dirpath,POSIX_ACL_DEFAULT_XATTR,NULL,0); + rv = fs::lgetxattr(dirpath,POSIX_ACL_DEFAULT_XATTR,NULL,0,0); return (rv != -1); } diff --git a/src/fs_base_futimesat.cpp b/src/fs_base_futimesat.cpp new file mode 100644 index 000000000..c254f4b93 --- /dev/null +++ b/src/fs_base_futimesat.cpp @@ -0,0 +1,23 @@ +/* + ISC License + + Copyright (c) 2017, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#if __APPLE__ +# include "fs_base_futimesat_osx.icpp" +#else +# include "fs_base_futimesat_generic.icpp" +#endif diff --git a/src/fs_base_futimesat.hpp b/src/fs_base_futimesat.hpp new file mode 100644 index 000000000..20f0938a4 --- /dev/null +++ b/src/fs_base_futimesat.hpp @@ -0,0 +1,30 @@ +/* + ISC License + + Copyright (c) 2017, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef __FS_BASE_FUTIMESAT_HPP__ +#define __FS_BASE_FUTIMESAT_HPP__ + +namespace fs +{ + int + futimesat(const int dirfd, + const char *pathname, + const struct timeval times[2]); +} + +#endif diff --git a/src/fs_base_futimesat_generic.icpp b/src/fs_base_futimesat_generic.icpp new file mode 100644 index 000000000..bfcd5e57e --- /dev/null +++ b/src/fs_base_futimesat_generic.icpp @@ -0,0 +1,31 @@ +/* + ISC License + + Copyright (c) 2017, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include +#include + +namespace fs +{ + int + futimesat(const int dirfd, + const char *pathname, + const struct timeval times[2]) + { + return ::futimesat(dirfd,pathname,times); + } +} diff --git a/src/fs_base_futimesat_osx.icpp b/src/fs_base_futimesat_osx.icpp new file mode 100644 index 000000000..6c781e98a --- /dev/null +++ b/src/fs_base_futimesat_osx.icpp @@ -0,0 +1,83 @@ +/* + ISC License + + Copyright (c) 2017, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static +int +getpath(const int dirfd, + const char *path, + char *fullpath) +{ + int rv; + struct stat st; + + rv = ::fstat(dirfd,&st); + if(rv == -1) + return -1; + + if(!S_ISDIR(st.st_mode)) + return (errno=ENOTDIR,-1); + + rv = ::fcntl(dirfd,F_GETPATH,fullpath); + if(rv == -1) + return -1; + + rv = (int)::strlcat(fullpath,"/",MAXPATHLEN); + if(rv > MAXPATHLEN) + return (errno=ENAMETOOLONG,-1); + + rv = (int)::strlcat(fullpath,path,MAXPATHLEN); + if(rv > MAXPATHLEN) + return (errno=ENAMETOOLONG,-1); + + return 0; +} + +namespace fs +{ + int + futimesat(const int dirfd, + const char *path, + const struct timeval times[2]) + { + int rv; + char fullpath[MAXPATHLEN]; + + if((dirfd == AT_FDCWD) || + ((path != NULL) && (path[0] == '/'))) + return ::utimes(path,times); + + if(dirfd < 0) + return (errno=EBADF,-1); + + rv = getpath(dirfd,path,fullpath); + if(rv == -1) + return -1; + + return ::utimes(fullpath,times); + } +} diff --git a/src/fs_base_getxattr.hpp b/src/fs_base_getxattr.hpp index cc3e26da6..2cc695129 100644 --- a/src/fs_base_getxattr.hpp +++ b/src/fs_base_getxattr.hpp @@ -28,16 +28,19 @@ namespace fs { static inline - int + ssize_t lgetxattr(const std::string &path, const char *attrname, void *value, - const size_t size) + const size_t size, + const u_int32_t position) { -#ifndef WITHOUT_XATTR - return ::lgetxattr(path.c_str(),attrname,value,size); -#else +#if WITHOUT_XATTR return (errno=ENOTSUP,-1); +#elif __APPLE__ + return ::getxattr(path.c_str(),attrname,value,size,position,XATTR_NOFOLLOW); +#else + return ::lgetxattr(path.c_str(),attrname,value,size); #endif } } diff --git a/src/fs_base_ioctl.hpp b/src/fs_base_ioctl.hpp index 9de639837..980378b64 100644 --- a/src/fs_base_ioctl.hpp +++ b/src/fs_base_ioctl.hpp @@ -26,9 +26,9 @@ namespace fs static inline int - ioctl(const int fd, - const int request, - void *data) + ioctl(const int fd, + const unsigned long request, + void *data) { return ::ioctl(fd,request,data); } diff --git a/src/fs_base_listxattr.hpp b/src/fs_base_listxattr.hpp index cbb2bbcec..8de8518a3 100644 --- a/src/fs_base_listxattr.hpp +++ b/src/fs_base_listxattr.hpp @@ -28,15 +28,17 @@ namespace fs { static inline - int + ssize_t llistxattr(const std::string &path, char *list, const size_t size) { -#ifndef WITHOUT_XATTR - return ::llistxattr(path.c_str(),list,size); -#else +#ifdef WITHOUT_XATTR return (errno=ENOTSUP,-1); +#elif __APPLE__ + return ::listxattr(path.c_str(),list,size,XATTR_NOFOLLOW); +#else + return ::llistxattr(path.c_str(),list,size); #endif } } diff --git a/src/fs_base_readlink.hpp b/src/fs_base_readlink.hpp index efe7fa478..b0c6cb92e 100644 --- a/src/fs_base_readlink.hpp +++ b/src/fs_base_readlink.hpp @@ -27,7 +27,7 @@ namespace fs { static inline - int + ssize_t readlink(const std::string &path, char *buf, const size_t bufsiz) diff --git a/src/fs_base_removexattr.hpp b/src/fs_base_removexattr.hpp index 71b9c27a1..1513354d4 100644 --- a/src/fs_base_removexattr.hpp +++ b/src/fs_base_removexattr.hpp @@ -32,10 +32,12 @@ namespace fs lremovexattr(const std::string &path, const char *attrname) { -#ifndef WITHOUT_XATTR - return ::lremovexattr(path.c_str(),attrname); -#else +#if WITHOUT_XATTR return (errno=ENOTSUP,-1); +#elif __APPLE__ + return ::removexattr(path.c_str(),attrname,XATTR_NOFOLLOW); +#else + return ::lremovexattr(path.c_str(),attrname); #endif } } diff --git a/src/fs_base_setxattr.hpp b/src/fs_base_setxattr.hpp index db7851e4e..7a1e2b954 100644 --- a/src/fs_base_setxattr.hpp +++ b/src/fs_base_setxattr.hpp @@ -33,13 +33,16 @@ namespace fs const char *name, const void *value, const size_t size, - const int flags) + const int flags, + const u_int32_t position) { -#ifndef WITHOUT_XATTR - return ::lsetxattr(path.c_str(),name,value,size,flags); -#else + #if WITHOUT_XATTR return (errno=ENOTSUP,-1); -#endif + #elif __APPLE__ + return ::setxattr(path.c_str(),name,value,size,position,flags & XATTR_NOFOLLOW); + #else + return ::lsetxattr(path.c_str(),name,value,size,flags); + #endif } } diff --git a/src/fs_base_stat.hpp b/src/fs_base_stat.hpp index e67d52673..696327392 100644 --- a/src/fs_base_stat.hpp +++ b/src/fs_base_stat.hpp @@ -62,6 +62,56 @@ namespace fs { return ::fstat(fd,&st); } + + static + inline + timespec * + stat_atime(struct stat &st) + { +#if __APPLE__ + return &st.st_atimespec; +#else + return &st.st_atim; +#endif + } + + static + inline + const + timespec * + stat_atime(const struct stat &st) + { +#if __APPLE__ + return &st.st_atimespec; +#else + return &st.st_atim; +#endif + } + + static + inline + timespec * + stat_mtime(struct stat &st) + { +#if __APPLE__ + return &st.st_mtimespec; +#else + return &st.st_mtim; +#endif + } + + static + inline + const + timespec * + stat_mtime(const struct stat &st) + { +#if __APPLE__ + return &st.st_mtimespec; +#else + return &st.st_mtim; +#endif + } } #endif diff --git a/src/fs_base_utime.hpp b/src/fs_base_utime.hpp index ae1b1afee..2def8d5c5 100644 --- a/src/fs_base_utime.hpp +++ b/src/fs_base_utime.hpp @@ -25,6 +25,8 @@ # include "fs_base_utime_generic.hpp" #endif +#include "fs_base_stat.hpp" + namespace fs { static @@ -35,8 +37,8 @@ namespace fs { struct timespec times[2]; - times[0] = st.st_atim; - times[1] = st.st_mtim; + times[0] = *fs::stat_atime(st); + times[1] = *fs::stat_mtime(st); return fs::utime(AT_FDCWD,path,times,0); } @@ -49,8 +51,8 @@ namespace fs { struct timespec times[2]; - times[0] = st.st_atim; - times[1] = st.st_mtim; + times[0] = *fs::stat_atime(st); + times[1] = *fs::stat_mtime(st); return fs::utime(fd,times); } diff --git a/src/fs_base_utime_generic.hpp b/src/fs_base_utime_generic.hpp index eeea26ad9..b8acdca49 100644 --- a/src/fs_base_utime_generic.hpp +++ b/src/fs_base_utime_generic.hpp @@ -25,6 +25,9 @@ #include #include +#include "fs_base_futimesat.hpp" +#include "fs_base_stat.hpp" + #ifndef UTIME_NOW # define UTIME_NOW ((1l << 30) - 1l) #endif @@ -123,6 +126,8 @@ _set_utime_omit_to_current_value(const int dirfd, { int rv; struct stat st; + timespec *atime; + timespec *mtime; if(!_any_timespec_is_utime_omit(ts)) return 0; @@ -131,10 +136,13 @@ _set_utime_omit_to_current_value(const int dirfd, if(rv == -1) return -1; + atime = fs::stat_atime(st); + mtime = fs::stat_mtime(st); + if(ts[0].tv_nsec == UTIME_OMIT) - TIMESPEC_TO_TIMEVAL(&tv[0],&st.st_atim); + TIMESPEC_TO_TIMEVAL(&tv[0],atime); if(ts[1].tv_nsec == UTIME_OMIT) - TIMESPEC_TO_TIMEVAL(&tv[1],&st.st_mtim); + TIMESPEC_TO_TIMEVAL(&tv[1],mtime); return 0; } @@ -148,6 +156,8 @@ _set_utime_omit_to_current_value(const int fd, { int rv; struct stat st; + timespec *atime; + timespec *mtime; if(!_any_timespec_is_utime_omit(ts)) return 0; @@ -156,10 +166,13 @@ _set_utime_omit_to_current_value(const int fd, if(rv == -1) return -1; + atime = fs::stat_atime(st); + mtime = fs::stat_mtime(st); + if(ts[0].tv_nsec == UTIME_OMIT) - TIMESPEC_TO_TIMEVAL(&tv[0],&st.st_atim); + TIMESPEC_TO_TIMEVAL(&tv[0],atime); if(ts[1].tv_nsec == UTIME_OMIT) - TIMESPEC_TO_TIMEVAL(&tv[1],&st.st_mtim); + TIMESPEC_TO_TIMEVAL(&tv[1],mtime); return 0; } @@ -270,7 +283,8 @@ namespace fs return -1; if((flags & AT_SYMLINK_NOFOLLOW) == 0) - return ::futimesat(dirfd,path.c_str(),tvp); + return fs::futimesat(dirfd,path.c_str(),tvp); + if(_can_call_lutimes(dirfd,path,flags)) return ::lutimes(path.c_str(),tvp); diff --git a/src/fs_clonefile.cpp b/src/fs_clonefile.cpp index 826790b96..0def21662 100644 --- a/src/fs_clonefile.cpp +++ b/src/fs_clonefile.cpp @@ -48,13 +48,13 @@ using std::string; using std::vector; -int +ssize_t writen(const int fd, const char *buf, const size_t count) { size_t nleft; - ssize_t nwritten; + ssize_t nwritten = 0; nleft = count; while(nleft > 0) @@ -67,15 +67,15 @@ writen(const int fd, return -1; } - nleft -= nwritten; - buf += nwritten; + nleft -= (size_t)nwritten; + buf += (size_t)nwritten; } - return count; + return nwritten; } static -int +ssize_t copyfile_rw(const int fdin, const int fdout, const size_t count, @@ -83,8 +83,8 @@ copyfile_rw(const int fdin, { ssize_t nr; ssize_t nw; - ssize_t bufsize; - size_t totalwritten; + size_t bufsize; + ssize_t totalwritten; vector buf; bufsize = (blocksize * 16); @@ -93,7 +93,7 @@ copyfile_rw(const int fdin, fs::lseek(fdin,0,SEEK_SET); totalwritten = 0; - while(totalwritten < count) + while(totalwritten < (ssize_t)count) { nr = fs::read(fdin,&buf[0],bufsize); if(nr == -1) @@ -103,29 +103,30 @@ copyfile_rw(const int fdin, return -1; } - nw = writen(fdout,&buf[0],nr); + nw = writen(fdout,&buf[0],(size_t)nr); if(nw == -1) return -1; totalwritten += nw; } - return count; + return totalwritten; } static -int +ssize_t copydata(const int fdin, const int fdout, const size_t count, const size_t blocksize) { - int rv; + ssize_t rv; + off_t scount = (off_t)count; + + fs::fadvise(fdin,0,scount,POSIX_FADV_WILLNEED); + fs::fadvise(fdin,0,scount,POSIX_FADV_SEQUENTIAL); - fs::fadvise(fdin,0,count,POSIX_FADV_WILLNEED); - fs::fadvise(fdin,0,count,POSIX_FADV_SEQUENTIAL); - - fs::fallocate(fdout,0,0,count); + fs::fallocate(fdout,0,0,scount); rv = fs::sendfile(fdin,fdout,count); if((rv == -1) && ((errno == EINVAL) || (errno == ENOSYS))) @@ -153,18 +154,18 @@ ignorable_error(const int err) namespace fs { - int + ssize_t clonefile(const int fdin, const int fdout) { - int rv; + ssize_t rv; struct stat stin; rv = fs::fstat(fdin,stin); if(rv == -1) return -1; - rv = ::copydata(fdin,fdout,stin.st_size,stin.st_blksize); + rv = ::copydata(fdin,fdout,(size_t)stin.st_size,(size_t)stin.st_blksize); if(rv == -1) return -1; @@ -191,11 +192,11 @@ namespace fs return 0; } - int + ssize_t clonefile(const string &in, const string &out) { - int rv; + ssize_t rv; int fdin; int fdout; int error; diff --git a/src/fs_fallocate_osx.icpp b/src/fs_fallocate_osx.icpp index 70894142e..c43a0821f 100644 --- a/src/fs_fallocate_osx.icpp +++ b/src/fs_fallocate_osx.icpp @@ -18,31 +18,32 @@ #include "errno.hpp" #include "fs_fallocate.hpp" +#include "fs_base_ftruncate.hpp" -namespace fs +static +int +_fallocate_core(const int fd, + const off_t offset, + const off_t len) { - static - int - _fallocate_core(const int fd, - const off_t offset, - const off_t len) - { - int rv; - fstore_t store = {F_ALLOCATECONTIG,F_PEOFPOSMODE,offset,len,0}; + int rv; + fstore_t store = {F_ALLOCATECONTIG,F_PEOFPOSMODE,offset,len,0}; - rv = ::fcntl(fd,F_PREALLOCATE,&store); - if(rv == -1) - { - store.fst_flags = F_ALLOCATEALL; - rv = ::fcntl(fd,F_PREALLOCATE,&store); - } + rv = ::fcntl(fd,F_PREALLOCATE,&store); + if(rv == -1) + { + store.fst_flags = F_ALLOCATEALL; + rv = ::fcntl(fd,F_PREALLOCATE,&store); + } - if(rv == -1) - return rv; + if(rv == -1) + return rv; - return ::ftruncate(fd,(offset+len)); - } + return ::ftruncate(fd,(offset+len)); +} +namespace fs +{ int fallocate(const int fd, const int mode, diff --git a/src/fs_inode.hpp b/src/fs_inode.hpp index b217305f4..fac1b814a 100644 --- a/src/fs_inode.hpp +++ b/src/fs_inode.hpp @@ -19,6 +19,7 @@ #ifndef __FS_INODE_HPP__ #define __FS_INODE_HPP__ +#include #include namespace fs @@ -34,7 +35,10 @@ namespace fs void recompute(struct stat &st) { - st.st_ino |= (st.st_dev << 32); + if(sizeof(st.st_ino) == 4) + st.st_ino |= ((uint32_t)st.st_dev << 16); + else + st.st_ino |= ((uint64_t)st.st_dev << 32); } } } diff --git a/src/fs_movefile.cpp b/src/fs_movefile.cpp index 1ca1fa54a..b02715536 100644 --- a/src/fs_movefile.cpp +++ b/src/fs_movefile.cpp @@ -66,7 +66,7 @@ namespace fs return -1; fdin_st.st_size += additional_size; - rv = fs::mfs(basepaths,fdin_st.st_size,fdout_path); + rv = fs::mfs(basepaths,(uint64_t)fdin_st.st_size,fdout_path); if(rv == -1) return -1; diff --git a/src/fs_xattr.cpp b/src/fs_xattr.cpp index acd8fb050..b8dcbcbd9 100644 --- a/src/fs_xattr.cpp +++ b/src/fs_xattr.cpp @@ -36,11 +36,80 @@ using std::vector; using std::map; using std::istringstream; +/* + The Mac version of the get/set APIs includes a position arg to seek around the + resource fork; for all other uses, the value is 0. + + For the other APIs, there are no link-specific variants; rather the standard call + has a flags argument where XATTR_NOFOLLOW is specified to address the link itself. +*/ + +ssize_t +_flistxattr(int fd, char* namebuf, size_t size) +{ +#if __APPLE__ + return ::flistxattr(fd, namebuf, size, 0); +#else + return ::flistxattr(fd, namebuf, size); +#endif +} + +ssize_t +_llistxattr(const char* path, char* namebuf, size_t size) +{ +#if __APPLE__ + return ::listxattr(path, namebuf, size, XATTR_NOFOLLOW); +#else + return ::llistxattr(path, namebuf, size); +#endif +} + +ssize_t +_fgetxattr(int fd, const char* name, char* value, size_t size, u_int32_t position) +{ +#if __APPLE__ + return ::fgetxattr(fd, name, value, size, position, 0); +#else + return ::fgetxattr(fd, name, value, size); +#endif +} + +ssize_t +_lgetxattr(const char* path, const char* name, char* value, size_t size, u_int32_t position) +{ +#if __APPLE__ + return ::getxattr(path, name, value, size, position, XATTR_NOFOLLOW); +#else + return ::lgetxattr(path, name, value, size); +#endif +} + +ssize_t +_fsetxattr(int fd, const char* name, const char* value, size_t size, int flags, u_int32_t position) +{ +#if __APPLE__ + return ::fsetxattr(fd, name, value, size, position, flags); +#else + return ::fsetxattr(fd, name, value, size, flags); +#endif +} + +ssize_t +_lsetxattr(const char* path, const char* name, const char* value, size_t size, int flags, u_int32_t position) +{ +#if __APPLE__ + return ::setxattr(path, name, value, size, position, flags & XATTR_NOFOLLOW); +#else + return ::lsetxattr(path, name, value, size, flags); +#endif +} + + namespace fs { namespace xattr { - int + ssize_t list(const int fd, vector &attrs) { @@ -51,13 +120,13 @@ namespace fs errno = ERANGE; while((rv == -1) && (errno == ERANGE)) { - rv = ::flistxattr(fd,NULL,0); + rv = _flistxattr(fd,NULL,0); if(rv <= 0) return rv; - attrs.resize(rv); + attrs.resize((size_t)rv); - rv = ::flistxattr(fd,&attrs[0],rv); + rv = _flistxattr(fd,&attrs[0],(size_t)rv); } return rv; @@ -66,7 +135,7 @@ namespace fs #endif } - int + ssize_t list(const string &path, vector &attrs) { @@ -77,13 +146,13 @@ namespace fs errno = ERANGE; while((rv == -1) && (errno == ERANGE)) { - rv = ::llistxattr(path.c_str(),NULL,0); + rv = _llistxattr(path.c_str(),NULL,0); if(rv <= 0) return rv; - attrs.resize(rv); + attrs.resize((size_t)rv); - rv = ::llistxattr(path.c_str(),&attrs[0],rv); + rv = _llistxattr(path.c_str(),&attrs[0],(size_t)rv); } return rv; @@ -92,11 +161,11 @@ namespace fs #endif } - int + ssize_t list(const int fd, vector &attrvector) { - int rv; + ssize_t rv; vector attrs; rv = list(fd,attrs); @@ -109,11 +178,11 @@ namespace fs return rv; } - int + ssize_t list(const string &path, vector &attrvector) { - int rv; + ssize_t rv; vector attrs; rv = list(path,attrs); @@ -126,11 +195,11 @@ namespace fs return rv; } - int + ssize_t list(const int fd, string &attrstr) { - int rv; + ssize_t rv; vector attrs; rv = list(fd,attrs); @@ -140,11 +209,11 @@ namespace fs return rv; } - int + ssize_t list(const string &path, string &attrstr) { - int rv; + ssize_t rv; vector attrs; rv = list(path,attrs); @@ -154,7 +223,7 @@ namespace fs return rv; } - int + ssize_t get(const int fd, const string &attr, vector &value) @@ -166,13 +235,14 @@ namespace fs errno = ERANGE; while((rv == -1) && (errno == ERANGE)) { - rv = ::fgetxattr(fd,attr.c_str(),NULL,0); + rv = _fgetxattr(fd,attr.c_str(),NULL,0,0); + if(rv <= 0) return rv; - value.resize(rv); + value.resize((size_t)rv); - rv = ::fgetxattr(fd,attr.c_str(),&value[0],rv); + rv = _fgetxattr(fd,attr.c_str(),&value[0],(size_t)rv, 0); } return rv; @@ -181,7 +251,7 @@ namespace fs #endif } - int + ssize_t get(const string &path, const string &attr, vector &value) @@ -193,13 +263,14 @@ namespace fs errno = ERANGE; while((rv == -1) && (errno == ERANGE)) { - rv = ::lgetxattr(path.c_str(),attr.c_str(),NULL,0); + rv = _lgetxattr(path.c_str(),attr.c_str(),NULL,0, 0); + if(rv <= 0) return rv; - value.resize(rv); + value.resize((size_t)rv); - rv = ::lgetxattr(path.c_str(),attr.c_str(),&value[0],rv); + rv = _lgetxattr(path.c_str(),attr.c_str(),&value[0],(size_t)rv, 0); } return rv; @@ -208,12 +279,12 @@ namespace fs #endif } - int + ssize_t get(const int fd, const string &attr, string &value) { - int rv; + ssize_t rv; vector tmpvalue; rv = get(fd,attr,tmpvalue); @@ -223,12 +294,12 @@ namespace fs return rv; } - int + ssize_t get(const string &path, const string &attr, string &value) { - int rv; + ssize_t rv; vector tmpvalue; rv = get(path,attr,tmpvalue); @@ -238,11 +309,11 @@ namespace fs return rv; } - int + ssize_t get(const int fd, map &attrs) { - int rv; + ssize_t rv; string attrstr; rv = list(fd,attrstr); @@ -266,11 +337,11 @@ namespace fs return 0; } - int + ssize_t get(const string &path, map &attrs) { - int rv; + ssize_t rv; string attrstr; rv = list(path,attrstr); @@ -294,45 +365,45 @@ namespace fs return 0; } - int + ssize_t set(const int fd, const string &key, const string &value, const int flags) { #ifndef WITHOUT_XATTR - return ::fsetxattr(fd, - key.c_str(), - value.data(), - value.size(), - flags); + return _fsetxattr(fd, + key.c_str(), + value.data(), + value.size(), + flags,0); #else return (errno=ENOTSUP,-1); #endif } - int + ssize_t set(const string &path, const string &key, const string &value, const int flags) { #ifndef WITHOUT_XATTR - return ::lsetxattr(path.c_str(), - key.c_str(), - value.data(), - value.size(), - flags); + return _lsetxattr(path.c_str(), + key.c_str(), + value.data(), + value.size(), + flags,0); #else return (errno=ENOTSUP,-1); #endif } - int + ssize_t set(const int fd, const map &attrs) { - int rv; + ssize_t rv; for(map::const_iterator i = attrs.begin(), ei = attrs.end(); i != ei; ++i) @@ -360,11 +431,11 @@ namespace fs return fs::close(fd); } - int + ssize_t copy(const int fdin, const int fdout) { - int rv; + ssize_t rv; map attrs; rv = get(fdin,attrs); @@ -374,11 +445,11 @@ namespace fs return set(fdout,attrs); } - int + ssize_t copy(const string &from, const string &to) { - int rv; + ssize_t rv; map attrs; rv = get(from,attrs); diff --git a/src/getxattr.cpp b/src/getxattr.cpp index 2a4143eab..548ee0370 100644 --- a/src/getxattr.cpp +++ b/src/getxattr.cpp @@ -39,15 +39,16 @@ using std::set; using namespace mergerfs; static -int +ssize_t _lgetxattr(const string &path, const char *attrname, void *value, - const size_t size) + const size_t size, + const u_int32_t position) { - int rv; + ssize_t rv; - rv = fs::lgetxattr(path,attrname,value,size); + rv = fs::lgetxattr(path,attrname,value,size,position); return ((rv == -1) ? -errno : rv); } @@ -153,7 +154,7 @@ _getxattr_pid(string &attrvalue) } static -int +ssize_t _getxattr_controlfile(const Config &config, const char *attrname, char *buf, @@ -198,7 +199,7 @@ _getxattr_controlfile(const Config &config, len = attrvalue.size(); if(count == 0) - return len; + return (ssize_t)len; if(count < len) return -ERANGE; @@ -209,7 +210,7 @@ _getxattr_controlfile(const Config &config, } static -int +ssize_t _getxattr_from_string(char *destbuf, const size_t destbufsize, const string &src) @@ -217,18 +218,18 @@ _getxattr_from_string(char *destbuf, const size_t srcbufsize = src.size(); if(destbufsize == 0) - return srcbufsize; + return (ssize_t)srcbufsize; if(srcbufsize > destbufsize) return -ERANGE; memcpy(destbuf,src.data(),srcbufsize); - return srcbufsize; + return (ssize_t)srcbufsize; } static -int +ssize_t _getxattr_user_mergerfs_allpaths(const vector &srcmounts, const char *fusepath, char *buf, @@ -245,7 +246,7 @@ _getxattr_user_mergerfs_allpaths(const vector &srcmounts, } static -int +ssize_t _getxattr_user_mergerfs(const string &basepath, const char *fusepath, const string &fullpath, @@ -271,16 +272,17 @@ _getxattr_user_mergerfs(const string &basepath, } static -int +ssize_t _getxattr(Policy::Func::Search searchFunc, const vector &srcmounts, const size_t minfreespace, const char *fusepath, const char *attrname, char *buf, - const size_t count) + size_t count, + u_int32_t position) { - int rv; + ssize_t rv; string fullpath; vector basepaths; @@ -293,21 +295,30 @@ _getxattr(Policy::Func::Search searchFunc, if(str::isprefix(attrname,"user.mergerfs.")) rv = _getxattr_user_mergerfs(*basepaths[0],fusepath,fullpath,srcmounts,attrname,buf,count); else - rv = _lgetxattr(fullpath,attrname,buf,count); + rv = _lgetxattr(fullpath,attrname,buf,count,position); return rv; } +/* The FUSE API is different for rthe *xattr APIs on Mac OS; it adds the position parameter. */ + namespace mergerfs { namespace fuse { - int + ssize_t getxattr(const char *fusepath, const char *attrname, char *buf, +#if __APPLE__ + size_t count, + u_int32_t position) + { +#else size_t count) { + u_int32_t position = 0; +#endif const fuse_context *fc = fuse_get_context(); const Config &config = Config::get(fc); @@ -322,11 +333,12 @@ namespace mergerfs return _getxattr(config.getxattr, config.srcmounts, - config.minfreespace, + (size_t)config.minfreespace, fusepath, attrname, buf, - count); + count, + position); } } } diff --git a/src/getxattr.hpp b/src/getxattr.hpp index aefbf37ec..1244b1b41 100644 --- a/src/getxattr.hpp +++ b/src/getxattr.hpp @@ -25,7 +25,12 @@ namespace mergerfs getxattr(const char *fusepath, const char *attrname, char *buf, +#if __APPLE__ + size_t count, + u_int32_t position); +#else size_t count); +#endif } } diff --git a/src/gidcache.cpp b/src/gidcache.cpp index 3bace59a4..995e0d6e7 100644 --- a/src/gidcache.cpp +++ b/src/gidcache.cpp @@ -66,8 +66,8 @@ gid_t_cache::lower_bound(gid_t_rec *begin, gid_t_rec *end, const uid_t uid) { - int step; - int count; + long step; + long count; gid_t_rec *iter; count = std::distance(begin,end); @@ -106,10 +106,22 @@ gid_t_cache::cache(const uid_t uid, rv = ::getpwuid_r(uid,&pwd,buf,sizeof(buf),&pwdrv); if(pwdrv != NULL && rv == 0) { + #if __APPLE__ + // OSX: getgrouplist(const char *name, int basegid, int *groups, int *ngroups) + rec->size = 0; + ::getgrouplist(pwd.pw_name,(int)gid,NULL,&rec->size); + rec->size = std::min(MAXGIDS,rec->size); + + rv = ::getgrouplist(pwd.pw_name,(int)gid,(int*)rec->gids,&rec->size); +#else + // Linux: getgrouplist(const char *name, gid_t group, gid_t *groups int *ngroups) rec->size = 0; ::getgrouplist(pwd.pw_name,gid,NULL,&rec->size); rec->size = std::min(MAXGIDS,rec->size); + rv = ::getgrouplist(pwd.pw_name,gid,rec->gids,&rec->size); +#endif + if(rv == -1) { rec->gids[0] = gid; diff --git a/src/ioctl.cpp b/src/ioctl.cpp index c081bfc9a..c3aa89f12 100644 --- a/src/ioctl.cpp +++ b/src/ioctl.cpp @@ -37,9 +37,9 @@ using namespace mergerfs; static int -_ioctl(const int fd, - const int cmd, - void *data) +_ioctl(const int fd, + const unsigned long cmd, + void *data) { int rv; @@ -60,7 +60,7 @@ _ioctl_dir_base(Policy::Func::Search searchFunc, const vector &srcmounts, const uint64_t minfreespace, const char *fusepath, - const int cmd, + const unsigned long cmd, void *data) { int fd; @@ -88,9 +88,9 @@ _ioctl_dir_base(Policy::Func::Search searchFunc, static int -_ioctl_dir(const char *fusepath, - const int cmd, - void *data) +_ioctl_dir(const char *fusepath, + const unsigned long cmd, + void *data) { const fuse_context *fc = fuse_get_context(); const Config &config = Config::get(fc); @@ -121,13 +121,13 @@ namespace mergerfs #ifdef FUSE_IOCTL_DIR if(flags & FUSE_IOCTL_DIR) return _ioctl_dir(fusepath, - cmd, + (unsigned long)cmd, data); #endif FileInfo *fi = reinterpret_cast(ffi->fh); return _ioctl(fi->fd, - cmd, + (unsigned long)cmd, data); } } diff --git a/src/listxattr.cpp b/src/listxattr.cpp index b84be9efd..1c723f292 100644 --- a/src/listxattr.cpp +++ b/src/listxattr.cpp @@ -36,7 +36,7 @@ using std::vector; using namespace mergerfs; static -int +ssize_t _listxattr_controlfile(char *list, const size_t size) { @@ -59,18 +59,18 @@ _listxattr_controlfile(char *list, xattrs += ("user.mergerfs.func." + (std::string)*FuseFunc::fusefuncs[i] + '\0'); if(size == 0) - return xattrs.size(); + return (ssize_t)xattrs.size(); if(size < xattrs.size()) return -ERANGE; memcpy(list,xattrs.c_str(),xattrs.size()); - return xattrs.size(); + return (ssize_t)xattrs.size(); } static -int +ssize_t _listxattr(Policy::Func::Search searchFunc, const vector &srcmounts, const uint64_t minfreespace, @@ -78,7 +78,7 @@ _listxattr(Policy::Func::Search searchFunc, char *list, const size_t size) { - int rv; + ssize_t rv; string fullpath; vector basepaths; @@ -97,7 +97,7 @@ namespace mergerfs { namespace fuse { - int + ssize_t listxattr(const char *fusepath, char *list, size_t size) diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index 5b65b7329..43aa2e624 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -142,7 +142,7 @@ namespace local { const int prio = -10; - std::srand(time(NULL)); + std::srand((unsigned int)time(NULL)); mergerfs::resources::reset_umask(); mergerfs::resources::maxout_rlimit_nofile(); mergerfs::resources::maxout_rlimit_fsize(); diff --git a/src/num.cpp b/src/num.cpp index 7f6a0ec4d..3e1894ca3 100644 --- a/src/num.cpp +++ b/src/num.cpp @@ -28,7 +28,7 @@ namespace num char *endptr; uint64_t tmp; - tmp = strtoll(str.c_str(),&endptr,10); + tmp = strtoul(str.c_str(),&endptr,10); switch(*endptr) { case 'k': diff --git a/src/read.cpp b/src/read.cpp index 80d08c09b..e3b8ea710 100644 --- a/src/read.cpp +++ b/src/read.cpp @@ -26,32 +26,30 @@ static inline -int +ssize_t _read(const int fd, void *buf, const size_t count, const off_t offset) { - int rv; + ssize_t rv; rv = fs::pread(fd,buf,count,offset); if(rv == -1) return -errno; - if(rv == 0) - return 0; - return count; + return rv; } static inline -int +ssize_t _read_direct_io(const int fd, void *buf, const size_t count, const off_t offset) { - int rv; + ssize_t rv; rv = fs::pread(fd,buf,count,offset); if(rv == -1) @@ -64,7 +62,7 @@ namespace mergerfs { namespace fuse { - int + ssize_t read(const char *fusepath, char *buf, size_t count, @@ -76,7 +74,7 @@ namespace mergerfs return _read(fi->fd,buf,count,offset); } - int + ssize_t read_direct_io(const char *fusepath, char *buf, size_t count, diff --git a/src/readdir.cpp b/src/readdir.cpp index 56d8e054b..c8d5d775e 100644 --- a/src/readdir.cpp +++ b/src/readdir.cpp @@ -50,7 +50,7 @@ _readdir(const vector &srcmounts, void *buf, const fuse_fill_dir_t filler) { - StrSet names; + StrSet names = StrSet(); string basepath; struct stat st = {0}; @@ -69,7 +69,7 @@ _readdir(const vector &srcmounts, dirfd = fs::dirfd(dh); st.st_dev = fs::devid(dirfd); if(st.st_dev == (dev_t)-1) - st.st_dev = i; + st.st_dev = (dev_t)i; rv = 0; for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh)) @@ -79,7 +79,7 @@ _readdir(const vector &srcmounts, continue; st.st_ino = de->d_ino; - st.st_mode = DTTOIF(de->d_type); + st.st_mode = (mode_t)DTTOIF(de->d_type); fs::inode::recompute(st); diff --git a/src/readlink.cpp b/src/readlink.cpp index b484b0524..e5b4f486b 100644 --- a/src/readlink.cpp +++ b/src/readlink.cpp @@ -28,13 +28,13 @@ using std::vector; using mergerfs::Policy; static -int +ssize_t _readlink_core(const string *basepath, const char *fusepath, char *buf, const size_t size) { - int rv; + ssize_t rv; string fullpath; fs::path::make(basepath,fusepath,fullpath); @@ -49,7 +49,7 @@ _readlink_core(const string *basepath, } static -int +ssize_t _readlink(Policy::Func::Search searchFunc, const vector &srcmounts, const uint64_t minfreespace, @@ -57,7 +57,7 @@ _readlink(Policy::Func::Search searchFunc, char *buf, const size_t size) { - int rv; + ssize_t rv; vector basepaths; rv = searchFunc(srcmounts,fusepath,minfreespace,basepaths); @@ -71,7 +71,7 @@ namespace mergerfs { namespace fuse { - int + ssize_t readlink(const char *fusepath, char *buf, size_t size) diff --git a/src/setxattr.cpp b/src/setxattr.cpp index 1b7b8a561..0adc03977 100644 --- a/src/setxattr.cpp +++ b/src/setxattr.cpp @@ -294,6 +294,7 @@ _setxattr_loop_core(const string *basepath, const char *attrval, const size_t attrvalsize, const int flags, + const u_int32_t position, const int error) { int rv; @@ -301,7 +302,7 @@ _setxattr_loop_core(const string *basepath, fs::path::make(basepath,fusepath,fullpath); - rv = fs::lsetxattr(fullpath,attrname,attrval,attrvalsize,flags); + rv = fs::lsetxattr(fullpath,attrname,attrval,attrvalsize,flags,position); return error::calc(rv,error,errno); } @@ -313,6 +314,7 @@ _setxattr_loop(const vector &basepaths, const char *attrname, const char *attrval, const size_t attrvalsize, + const u_int32_t position, const int flags) { int error; @@ -321,7 +323,7 @@ _setxattr_loop(const vector &basepaths, for(size_t i = 0, ei = basepaths.size(); i != ei; i++) { error = _setxattr_loop_core(basepaths[i],fusepath, - attrname,attrval,attrvalsize,flags, + attrname,attrval,attrvalsize,flags,position, error); } @@ -337,6 +339,7 @@ _setxattr(Policy::Func::Action actionFunc, const char *attrname, const char *attrval, const size_t attrvalsize, + const u_int32_t position, const int flags) { int rv; @@ -346,7 +349,7 @@ _setxattr(Policy::Func::Action actionFunc, if(rv == -1) return -errno; - return _setxattr_loop(basepaths,fusepath,attrname,attrval,attrvalsize,flags); + return _setxattr_loop(basepaths,fusepath,attrname,attrval,attrvalsize,position,flags); } namespace mergerfs @@ -358,8 +361,15 @@ namespace mergerfs const char *attrname, const char *attrval, size_t attrvalsize, +#ifdef __APPLE__ + int flags, + u_int32_t position) + { +#else int flags) { + u_int32_t position = 0; +#endif const fuse_context *fc = fuse_get_context(); const Config &config = Config::get(fc); @@ -379,6 +389,7 @@ namespace mergerfs attrname, attrval, attrvalsize, + position, flags); } } diff --git a/src/setxattr.hpp b/src/setxattr.hpp index a05e382a0..ed9b67106 100644 --- a/src/setxattr.hpp +++ b/src/setxattr.hpp @@ -26,7 +26,12 @@ namespace mergerfs const char *attrname, const char *attrval, size_t attrvalsize, +#if __APPLE__ + int flags, + u_int32_t position); +#else int flags); +#endif } } diff --git a/src/ugid_rwlock.hpp b/src/ugid_rwlock.hpp index 0c4dfd234..580a2ec82 100644 --- a/src/ugid_rwlock.hpp +++ b/src/ugid_rwlock.hpp @@ -48,13 +48,13 @@ namespace mergerfs if(currentuid != 0) { - ::seteuid(0); - ::setegid(0); + (void)::seteuid(0); + (void)::setegid(0); } if(newgid) { - ::setegid(newgid); + (void)::setegid(newgid); initgroups(newuid,newgid); } diff --git a/src/write.cpp b/src/write.cpp index 6d722b06a..be1f5deb1 100644 --- a/src/write.cpp +++ b/src/write.cpp @@ -26,7 +26,7 @@ using namespace mergerfs; -typedef int (*WriteFunc)(const int,const void*,const size_t,const off_t); +typedef ssize_t (*WriteFunc)(const int,const void*,const size_t,const off_t); static bool @@ -38,32 +38,30 @@ _out_of_space(const int error) static inline -int +ssize_t _write(const int fd, const void *buf, const size_t count, const off_t offset) { - int rv; + ssize_t rv; rv = fs::pwrite(fd,buf,count,offset); if(rv == -1) return -errno; - if(rv == 0) - return 0; - return count; + return rv; } static inline -int +ssize_t _write_direct_io(const int fd, const void *buf, const size_t count, const off_t offset) { - int rv; + ssize_t rv; rv = fs::pwrite(fd,buf,count,offset); if(rv == -1) @@ -81,7 +79,7 @@ namespace mergerfs { static inline - int + ssize_t write(WriteFunc func, const char *fusepath, const char *buf, @@ -89,11 +87,11 @@ namespace mergerfs const off_t offset, fuse_file_info *ffi) { - int rv; + ssize_t rv; FileInfo* fi = reinterpret_cast(ffi->fh); rv = func(fi->fd,buf,count,offset); - if(_out_of_space(-rv)) + if(_out_of_space((int)-rv)) { const fuse_context *fc = fuse_get_context(); const Config &config = Config::get(fc); @@ -114,7 +112,7 @@ namespace mergerfs return rv; } - int + ssize_t write(const char *fusepath, const char *buf, size_t count, @@ -124,7 +122,7 @@ namespace mergerfs return write(_write,fusepath,buf,count,offset,ffi); } - int + ssize_t write_direct_io(const char *fusepath, const char *buf, size_t count, diff --git a/src/write_buf.cpp b/src/write_buf.cpp index db2624369..44f08dff9 100644 --- a/src/write_buf.cpp +++ b/src/write_buf.cpp @@ -46,7 +46,7 @@ _out_of_space(const int error) } static -int +ssize_t _write_buf(const int fd, fuse_bufvec &src, const off_t offset) @@ -67,17 +67,17 @@ namespace mergerfs { namespace fuse { - int + ssize_t write_buf(const char *fusepath, fuse_bufvec *src, off_t offset, fuse_file_info *ffi) { - int rv; + ssize_t rv; FileInfo *fi = reinterpret_cast(ffi->fh); rv = _write_buf(fi->fd,*src,offset); - if(_out_of_space(-rv)) + if(_out_of_space((int)-rv)) { const fuse_context *fc = fuse_get_context(); const Config &config = Config::get(fc); diff --git a/src/xattr.hpp b/src/xattr.hpp index 181fedf88..dd96ad32c 100644 --- a/src/xattr.hpp +++ b/src/xattr.hpp @@ -18,8 +18,12 @@ #define __XATTR_HPP__ #ifndef WITHOUT_XATTR +#if __APPLE__ +#include +#else #include -#endif +#endif /* __APPLE__ */ +#endif /* WITHOUT_XATTR */ #ifndef XATTR_CREATE # define XATTR_CREATE 0x1 diff --git a/tools/cppfind b/tools/cppfind index bac073eb0..fa9dbad42 100755 --- a/tools/cppfind +++ b/tools/cppfind @@ -2,6 +2,6 @@ FUSE_CFLAGS="$(pkg-config --cflags fuse) -DFUSE_USE_VERSION=29" -echo "#include " | cpp ${FUSE_CFLAGS} | grep "${1}" > /dev/null +echo "#include " | cc -E ${FUSE_CFLAGS} - | grep "${1}" > /dev/null [ "$?" != "0" ]; echo $?