Commit 2a4b491f authored by jan.koester's avatar jan.koester
Browse files

test

parent c1d7ff51
Loading
Loading
Loading
Loading
+36 −1
Changes for src/config.cpp: 36 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sys/stat.h>
#include <unistd.h>

#if __has_include(<sys/uid_r.h>)
#include <sys/uid_r.h>  // systempp: UUID and GUID owners
#define SHAREDD_UID_R 1
#endif

#include <confplus/conf.h>
#include <confplus/exception.h>

@@ -331,6 +336,28 @@ std::string createShareDir(const Share &s, const std::string &lang) {
    uid_t uid = 0;
    gid_t gid = 0;
    mode_t mode = 01777;
#ifdef SHAREDD_UID_R
    // the owner may be a UUID or GUID user or group
    uid_r_t ruid = uid_r_legacy(0), rgid = uid_r_legacy(0);
    if (s.readOnly) {
        mode = 0755;
    } else if (s.users.size() == 1 && s.users[0][0] != '@') {
        if (struct passwd_id_r *pw = getpwnam_id_r(s.users[0].c_str())) {
            ruid = pw->pw_uid;
            rgid = pw->pw_gid;
            mode = 0755;
        }
        endpwent_id_r();
    } else if (s.users.size() == 1) {
        if (struct group_id_r *gr = getgrnam_id_r(s.users[0].c_str() + 1)) {
            rgid = gr->gr_gid;
            mode = 02775;
        }
        endgrent_id_r();
    }
    uid = uid_r_to_legacy(&ruid);
    gid = uid_r_to_legacy(&rgid);
#else
    if (s.readOnly) {
        mode = 0755;
    } else if (s.users.size() == 1 && s.users[0][0] != '@') {
@@ -349,6 +376,7 @@ std::string createShareDir(const Share &s, const std::string &lang) {
        }
        endgrent();
    }
#endif
    // parents first, root's
    for (size_t slash = s.path.find('/', 1); slash != std::string::npos; slash = s.path.find('/', slash + 1)) {
        std::string dir = s.path.substr(0, slash);
@@ -357,7 +385,14 @@ std::string createShareDir(const Share &s, const std::string &lang) {
    }
    if (mkdir(s.path.c_str(), 0700) != 0 && errno != EEXIST)
        return tr(lang, "creating %1 failed: %2", "%1 anlegen fehlgeschlagen: %2", {s.path, strerror(errno)});
    if (chown(s.path.c_str(), uid, gid) != 0 || chmod(s.path.c_str(), mode) != 0)
#ifdef SHAREDD_UID_R
    int owned = chown_r(s.path.c_str(), &ruid, &rgid);
    if (owned != 0 && errno == ENOSYS && uid_r_is_legacy(&ruid) && uid_r_is_legacy(&rgid))
        owned = chown(s.path.c_str(), uid, gid);
#else
    int owned = chown(s.path.c_str(), uid, gid);
#endif
    if (owned != 0 || chmod(s.path.c_str(), mode) != 0)
        return tr(lang, "setting up %1 failed: %2", "%1 einrichten fehlgeschlagen: %2", {s.path, strerror(errno)});
    char m[8];
    snprintf(m, sizeof(m), "%04o", (unsigned)mode);
+39 −5
Changes for src/files.cpp: 39 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -39,6 +39,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sys/stat.h>
#include <unistd.h>

#if __has_include(<sys/uid_r.h>)
#include <sys/uid_r.h>  // systempp: UUID and GUID owners
#define SHAREDD_UID_R 1
#endif

namespace sharedd {

namespace {
@@ -119,6 +124,37 @@ std::string groupName(gid_t gid) {
    return gr ? gr->gr_name : std::to_string(gid);
}

// owner and group names of name in dir (st: its classic stat); a UUID or
// GUID owner (st shows the overflow id for it) by its name or text form
void ownerNames(int dir, const char *name, const struct stat &st, std::string &owner, std::string &group) {
    owner = userName(st.st_uid);
    group = groupName(st.st_gid);
#ifdef SHAREDD_UID_R
    uid_r_t u, g;
    if (fstatat_id_r(dir, name, &u, &g, AT_SYMLINK_NOFOLLOW | (*name ? 0 : AT_EMPTY_PATH)) != 0) return;
    char buf[UID_R_STR_LEN];
    if (!uid_r_is_legacy(&u)) {
        struct passwd_id_r *pw = getpwuid_id_r(&u);
        owner = pw ? pw->pw_name : uid_r_to_str(&u, buf);
    }
    if (!uid_r_is_legacy(&g)) {
        struct group_id_r *gr = getgrgid_id_r(&g);
        group = gr ? gr->gr_name : uid_r_to_str(&g, buf);
    }
#endif
}

// gives fd the owner and group of the directory dir (st: its classic stat),
// a UUID or GUID one too
bool inheritOwner(int fd, int dir, const struct stat &st) {
#ifdef SHAREDD_UID_R
    uid_r_t u, g;
    if (fstatat_id_r(dir, "", &u, &g, AT_EMPTY_PATH) == 0) return fchown_r(fd, &u, &g) == 0;
    if (errno != ENOSYS) return false;
#endif
    return fchown(fd, st.st_uid, st.st_gid) == 0;
}

bool parseId(const std::string &v, bool group, unsigned &out) {
    if (!v.empty() && v.find_first_not_of("0123456789") == std::string::npos) {
        out = (unsigned)std::strtoul(v.c_str(), nullptr, 10);
@@ -216,8 +252,7 @@ std::string listDir(const Share &s, const std::string &rel, std::vector<FileEntr
        self.mtime = own.st_mtime;
        self.uid = own.st_uid;
        self.gid = own.st_gid;
        self.owner = userName(own.st_uid);
        self.group = groupName(own.st_gid);
        ownerNames(dir.fd, "", own, self.owner, self.group);
        self.mode = own.st_mode & 07777;
    }
    DIR *d = fdopendir(dup(dir.fd));
@@ -234,8 +269,7 @@ std::string listDir(const Share &s, const std::string &rel, std::vector<FileEntr
        f.mtime = st.st_mtime;
        f.uid = st.st_uid;
        f.gid = st.st_gid;
        f.owner = userName(st.st_uid);
        f.group = groupName(st.st_gid);
        ownerNames(dir.fd, e->d_name, st, f.owner, f.group);
        f.mode = st.st_mode & 07777;
        out.push_back(f);
    }
@@ -316,7 +350,7 @@ std::string createEntry(const Share &s, const std::string &rel, const std::strin
    if (made.fd < 0) return strerror(errno);
    // the parent's owner and group; folders keep its setgid bit
    unsigned mode = folder ? (0775u | (parent.st_mode & 02000u)) : 0664u;
    if (fchown(made.fd, parent.st_uid, parent.st_gid) != 0 || fchmod(made.fd, mode) != 0)
    if (!inheritOwner(made.fd, dir.fd, parent) || fchmod(made.fd, mode) != 0)
        return tr(lang, "setting up %1 failed: %2", "%1 einrichten fehlgeschlagen: %2", {name, strerror(errno)});
    return "";
}