"Fossies" - the Fresh Open Source Software Archive

Member "vnstat-2.9/src/fs.c" (16 Sep 2019, 4053 Bytes) of package /linux/misc/vnstat-2.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fs.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.4_vs_2.5.

    1 #include "common.h"
    2 #include "id.h"
    3 #include "fs.h"
    4 
    5 int direxists(const char *dir)
    6 {
    7     return fileexists(dir);
    8 }
    9 
   10 int fileexists(const char *file)
   11 {
   12     struct stat statbuf;
   13 
   14     if (stat(file, &statbuf) != 0) {
   15         if (errno == ENOENT) {
   16             return 0;
   17         }
   18         if (debug)
   19             printf("Error (debug): stat() \"%s\": %s\n", file, strerror(errno));
   20     }
   21     return 1;
   22 }
   23 
   24 int mkpath(const char *dir, const mode_t mode)
   25 {
   26     int ret = 1;
   27     size_t i = 0, len = 0;
   28     char *tmp = NULL;
   29 
   30     if (!strlen(dir)) {
   31         if (debug)
   32             printf("Error (debug): mkpath(), no directory given\n");
   33         return 0;
   34     }
   35 
   36     if (direxists(dir)) {
   37         if (debug)
   38             printf("already exists: %s\n", dir);
   39         return 1;
   40     }
   41 
   42     if (!cfg.createdirs) {
   43         return 0;
   44     }
   45 
   46     tmp = strdup(dir);
   47     if (tmp == NULL) {
   48         return 0;
   49     }
   50 
   51     len = strlen(tmp);
   52     if (tmp[len - 1] == '/') {
   53         tmp[len - 1] = '\0';
   54     }
   55 
   56     if (tmp[0] == '/') {
   57         i++;
   58     }
   59 
   60     for (; i < len; i++) {
   61         if (tmp[i] == '/') {
   62             tmp[i] = '\0';
   63             if (!direxists(tmp)) {
   64                 if (mkdir(tmp, mode) != 0) {
   65                     if (debug)
   66                         printf("Error (debug): mkdir() \"%s\": %s\n", tmp, strerror(errno));
   67                     ret = 0;
   68                     break;
   69                 }
   70             }
   71             tmp[i] = '/';
   72         }
   73     }
   74     if (ret) {
   75         if (mkdir(tmp, mode) != 0) {
   76             if (debug)
   77                 printf("Error (debug): mkdir() \"%s\": %s\n", tmp, strerror(errno));
   78             ret = 0;
   79         } else if (debug) {
   80             printf("created: %s\n", tmp);
   81         }
   82     }
   83 
   84     free(tmp);
   85     return ret;
   86 }
   87 
   88 void preparevnstatdir(const char *dir, const char *user, const char *group)
   89 {
   90     size_t i, len, lastslash = 0;
   91     char *path, *base;
   92 
   93     if (dir == NULL) {
   94         return;
   95     }
   96 
   97     len = strlen(dir);
   98     if (len < 2) {
   99         return;
  100     }
  101 
  102     if (dir[len - 1] == '/') {
  103         return;
  104     }
  105 
  106     path = strdup(dir);
  107     if (path == NULL) {
  108         return;
  109     }
  110 
  111     /* verify that path ends with vnstat or vnstatd */
  112     base = basename(dirname(path));
  113     if (strcmp(base, "vnstat") != 0 && strcmp(base, "vnstatd") != 0) {
  114         free(path);
  115         return;
  116     }
  117     free(path);
  118 
  119     path = strdup(dir);
  120     if (path == NULL) {
  121         return;
  122     }
  123 
  124     /* extract path */
  125     for (i = 0; i < len; i++) {
  126         if (path[i] == '/') {
  127             lastslash = i;
  128         }
  129     }
  130     if (lastslash == 0) {
  131         free(path);
  132         return;
  133     }
  134     path[lastslash] = '\0';
  135 
  136     /* create & chmod if needed */
  137     if (mkpath(path, 0775)) {
  138         updatedirowner(path, user, group);
  139     }
  140     free(path);
  141 }
  142 
  143 void updatedirowner(const char *dir, const char *user, const char *group)
  144 {
  145     uid_t uid;
  146     gid_t gid;
  147 
  148     if (!cfg.updatefileowner) {
  149         return;
  150     }
  151 
  152     if (!hasroot()) {
  153         if (debug)
  154             printf("user not root, skipping chmod\n");
  155         return;
  156     }
  157 
  158     uid = getuser(user);
  159     gid = getgroup(group);
  160 
  161     updatedirownerid(dir, uid, gid);
  162 }
  163 
  164 void updatedirownerid(const char *dir, const uid_t uid, const gid_t gid)
  165 {
  166     DIR *d;
  167     struct dirent *di;
  168     struct stat statbuf;
  169     char entryname[512];
  170     int dir_fd, file_fd;
  171 
  172     if (!cfg.updatefileowner) {
  173         return;
  174     }
  175 
  176     if (!hasroot()) {
  177         if (debug)
  178             printf("user not root, skipping chmod\n");
  179         return;
  180     }
  181 
  182     if ((dir_fd = open(dir, FS_OPEN_RO_FLAGS)) == -1)
  183         return;
  184     if (fstat(dir_fd, &statbuf) != 0) {
  185         close(dir_fd);
  186         return;
  187     }
  188 
  189     if (statbuf.st_uid != uid || statbuf.st_gid != gid) {
  190         if (fchown(dir_fd, uid, gid) != 0) {
  191             if (debug)
  192                 printf("Error (debug): updatedirowner() chown() \"%s\": %s\n", dir, strerror(errno));
  193             close(dir_fd);
  194             return;
  195         } else {
  196             if (debug)
  197                 printf("\"%s\" chown completed\n", dir);
  198         }
  199     }
  200 
  201     if ((d = fdopendir(dir_fd)) == NULL) {
  202         if (debug)
  203             printf("Error (debug): updatedirowner() diropen() \"%s\": %s\n", dir, strerror(errno));
  204         close(dir_fd);
  205         return;
  206     }
  207 
  208     while ((di = readdir(d))) {
  209         if (di->d_type != DT_REG) {
  210             continue;
  211         }
  212         snprintf(entryname, 512, "%s/%s", dir, di->d_name);
  213         if ((file_fd = open(entryname, FS_OPEN_RO_FLAGS)) == -1)
  214             continue;
  215         if (fstat(file_fd, &statbuf) != 0) {
  216             close(file_fd);
  217             continue;
  218         }
  219         if (statbuf.st_uid != uid || statbuf.st_gid != gid) {
  220             if (fchown(file_fd, uid, gid) != 0) {
  221                 if (debug)
  222                     printf("Error (debug): chown() \"%s\": %s\n", entryname, strerror(errno));
  223             } else {
  224                 if (debug)
  225                     printf("\"%s\" chown completed\n", entryname);
  226             }
  227         }
  228         close(file_fd);
  229     }
  230 
  231     closedir(d);
  232 }