#include "common.h" #include "id.h" #include "fs.h" int direxists(const char *dir) { return fileexists(dir); } int fileexists(const char *file) { struct stat statbuf; if (stat(file, &statbuf) != 0) { if (errno == ENOENT) { return 0; } if (debug) printf("Error (debug): stat() \"%s\": %s\n", file, strerror(errno)); } return 1; } int mkpath(const char *dir, const mode_t mode) { int ret = 1; size_t i = 0, len = 0; char *tmp = NULL; if (!strlen(dir)) { if (debug) printf("Error (debug): mkpath(), no directory given\n"); return 0; } if (direxists(dir)) { if (debug) printf("already exists: %s\n", dir); return 1; } if (!cfg.createdirs) { return 0; } tmp = strdup(dir); if (tmp == NULL) { return 0; } len = strlen(tmp); if (tmp[len - 1] == '/') { tmp[len - 1] = '\0'; } if (tmp[0] == '/') { i++; } for (; i < len; i++) { if (tmp[i] == '/') { tmp[i] = '\0'; if (!direxists(tmp)) { if (mkdir(tmp, mode) != 0) { if (debug) printf("Error (debug): mkdir() \"%s\": %s\n", tmp, strerror(errno)); ret = 0; break; } } tmp[i] = '/'; } } if (ret) { if (mkdir(tmp, mode) != 0) { if (debug) printf("Error (debug): mkdir() \"%s\": %s\n", tmp, strerror(errno)); ret = 0; } else if (debug) { printf("created: %s\n", tmp); } } free(tmp); return ret; } void preparevnstatdir(const char *dir, const char *user, const char *group) { size_t i, len, lastslash = 0; char *path, *base; if (dir == NULL) { return; } len = strlen(dir); if (len < 2) { return; } if (dir[len - 1] == '/') { return; } path = strdup(dir); if (path == NULL) { return; } /* verify that path ends with vnstat or vnstatd */ base = basename(dirname(path)); if (strcmp(base, "vnstat") != 0 && strcmp(base, "vnstatd") != 0) { free(path); return; } free(path); path = strdup(dir); if (path == NULL) { return; } /* extract path */ for (i = 0; i < len; i++) { if (path[i] == '/') { lastslash = i; } } if (lastslash == 0) { free(path); return; } path[lastslash] = '\0'; /* create & chmod if needed */ if (mkpath(path, 0775)) { updatedirowner(path, user, group); } free(path); } void updatedirowner(const char *dir, const char *user, const char *group) { uid_t uid; gid_t gid; if (!cfg.updatefileowner) { return; } if (!hasroot()) { if (debug) printf("user not root, skipping chmod\n"); return; } uid = getuser(user); gid = getgroup(group); updatedirownerid(dir, uid, gid); } void updatedirownerid(const char *dir, const uid_t uid, const gid_t gid) { DIR *d; struct dirent *di; struct stat statbuf; char entryname[512]; int dir_fd, file_fd; if (!cfg.updatefileowner) { return; } if (!hasroot()) { if (debug) printf("user not root, skipping chmod\n"); return; } if ((dir_fd = open(dir, FS_OPEN_RO_FLAGS)) == -1) return; if (fstat(dir_fd, &statbuf) != 0) { close(dir_fd); return; } if (statbuf.st_uid != uid || statbuf.st_gid != gid) { if (fchown(dir_fd, uid, gid) != 0) { if (debug) printf("Error (debug): updatedirowner() chown() \"%s\": %s\n", dir, strerror(errno)); close(dir_fd); return; } else { if (debug) printf("\"%s\" chown completed\n", dir); } } if ((d = fdopendir(dir_fd)) == NULL) { if (debug) printf("Error (debug): updatedirowner() diropen() \"%s\": %s\n", dir, strerror(errno)); close(dir_fd); return; } while ((di = readdir(d))) { if (di->d_type != DT_REG) { continue; } snprintf(entryname, 512, "%s/%s", dir, di->d_name); if ((file_fd = open(entryname, FS_OPEN_RO_FLAGS)) == -1) continue; if (fstat(file_fd, &statbuf) != 0) { close(file_fd); continue; } if (statbuf.st_uid != uid || statbuf.st_gid != gid) { if (fchown(file_fd, uid, gid) != 0) { if (debug) printf("Error (debug): chown() \"%s\": %s\n", entryname, strerror(errno)); } else { if (debug) printf("\"%s\" chown completed\n", entryname); } } close(file_fd); } closedir(d); }