"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 }