/src/samba/source3/lib/sysquotas.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | System QUOTA function wrappers |
4 | | Copyright (C) Stefan (metze) Metzmacher 2003 |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 3 of the License, or |
9 | | (at your option) any later version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | | */ |
19 | | |
20 | | |
21 | | #include "includes.h" |
22 | | #include "lib/util/util_file.h" |
23 | | #include "lib/util/smb_strtox.h" |
24 | | |
25 | | #undef DBGC_CLASS |
26 | 0 | #define DBGC_CLASS DBGC_QUOTA |
27 | | |
28 | | #ifdef HAVE_SYS_QUOTAS |
29 | | |
30 | | #if defined(HAVE_QUOTACTL_4A) |
31 | | |
32 | | /*#endif HAVE_QUOTACTL_4A */ |
33 | | #elif defined(HAVE_QUOTACTL_4B) |
34 | | |
35 | | /*#endif HAVE_QUOTACTL_4B */ |
36 | | #elif defined(HAVE_QUOTACTL_3) |
37 | | |
38 | | #error HAVE_QUOTACTL_3 not implemented |
39 | | |
40 | | /* #endif HAVE_QUOTACTL_3 */ |
41 | | #else /* NO_QUOTACTL_USED */ |
42 | | |
43 | | #endif /* NO_QUOTACTL_USED */ |
44 | | |
45 | | #if defined(HAVE_MNTENT) && defined(HAVE_REALPATH) |
46 | | static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs) |
47 | 0 | { |
48 | 0 | int ret = -1; |
49 | 0 | SMB_STRUCT_STAT S; |
50 | 0 | FILE *fp; |
51 | 0 | struct mntent *mnt = NULL; |
52 | 0 | SMB_DEV_T devno; |
53 | 0 | char *stat_mntpath = NULL; |
54 | 0 | char *p; |
55 | | |
56 | | /* find the block device file */ |
57 | 0 | (*mntpath) = NULL; |
58 | 0 | (*bdev) = NULL; |
59 | 0 | (*fs) = NULL; |
60 | |
|
61 | 0 | if (sys_stat(path, &S, false) != 0) { |
62 | 0 | return -1; |
63 | 0 | } |
64 | | |
65 | 0 | devno = S.st_ex_dev ; |
66 | |
|
67 | 0 | stat_mntpath = sys_realpath(path); |
68 | 0 | if (stat_mntpath == NULL) { |
69 | 0 | DBG_WARNING("realpath(%s) failed - %s\n", path, |
70 | 0 | strerror(errno)); |
71 | 0 | goto out; |
72 | 0 | } |
73 | | |
74 | 0 | if (sys_stat(stat_mntpath, &S, false) != 0) { |
75 | 0 | DBG_WARNING("cannot stat real path %s - %s\n", stat_mntpath, |
76 | 0 | strerror(errno)); |
77 | 0 | goto out; |
78 | 0 | } |
79 | | |
80 | 0 | if (S.st_ex_dev != devno) { |
81 | 0 | DBG_WARNING("device on real path has changed\n"); |
82 | 0 | goto out; |
83 | 0 | } |
84 | | |
85 | 0 | while (true) { |
86 | 0 | char save_ch; |
87 | |
|
88 | 0 | p = strrchr(stat_mntpath, '/'); |
89 | 0 | if (p == NULL) { |
90 | 0 | DBG_ERR("realpath for %s does not begin with a '/'\n", |
91 | 0 | path); |
92 | 0 | goto out; |
93 | 0 | } |
94 | | |
95 | 0 | if (p == stat_mntpath) { |
96 | 0 | ++p; |
97 | 0 | } |
98 | |
|
99 | 0 | save_ch = *p; |
100 | 0 | *p = 0; |
101 | 0 | if (sys_stat(stat_mntpath, &S, false) != 0) { |
102 | 0 | DBG_WARNING("cannot stat real path component %s - %s\n", |
103 | 0 | stat_mntpath, strerror(errno)); |
104 | 0 | goto out; |
105 | 0 | } |
106 | 0 | if (S.st_ex_dev != devno) { |
107 | 0 | *p = save_ch; |
108 | 0 | break; |
109 | 0 | } |
110 | | |
111 | 0 | if (p <= stat_mntpath + 1) { |
112 | 0 | break; |
113 | 0 | } |
114 | 0 | } |
115 | | |
116 | 0 | fp = setmntent(MOUNTED,"r"); |
117 | 0 | if (fp == NULL) { |
118 | 0 | goto out; |
119 | 0 | } |
120 | | |
121 | 0 | while ((mnt = getmntent(fp))) { |
122 | 0 | if (!strequal(mnt->mnt_dir, stat_mntpath)) { |
123 | 0 | continue; |
124 | 0 | } |
125 | | |
126 | 0 | if ( sys_stat(mnt->mnt_dir, &S, false) == -1 ) |
127 | 0 | continue ; |
128 | | |
129 | 0 | if (S.st_ex_dev == devno) { |
130 | 0 | (*mntpath) = SMB_STRDUP(mnt->mnt_dir); |
131 | 0 | (*bdev) = SMB_STRDUP(mnt->mnt_fsname); |
132 | 0 | (*fs) = SMB_STRDUP(mnt->mnt_type); |
133 | 0 | if ((*mntpath)&&(*bdev)&&(*fs)) { |
134 | 0 | ret = 0; |
135 | 0 | } else { |
136 | 0 | SAFE_FREE(*mntpath); |
137 | 0 | SAFE_FREE(*bdev); |
138 | 0 | SAFE_FREE(*fs); |
139 | 0 | ret = -1; |
140 | 0 | } |
141 | |
|
142 | 0 | break; |
143 | 0 | } |
144 | 0 | } |
145 | |
|
146 | 0 | endmntent(fp) ; |
147 | |
|
148 | 0 | out: |
149 | 0 | SAFE_FREE(stat_mntpath); |
150 | 0 | return ret; |
151 | 0 | } |
152 | | /* #endif HAVE_MNTENT */ |
153 | | #elif defined(HAVE_DEVNM) |
154 | | |
155 | | /* we have this on HPUX, ... */ |
156 | | static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs) |
157 | | { |
158 | | int ret = -1; |
159 | | char dev_disk[256]; |
160 | | SMB_STRUCT_STAT S; |
161 | | |
162 | | if (!path||!mntpath||!bdev||!fs) |
163 | | smb_panic("sys_path_to_bdev: called with NULL pointer"); |
164 | | |
165 | | (*mntpath) = NULL; |
166 | | (*bdev) = NULL; |
167 | | (*fs) = NULL; |
168 | | |
169 | | /* find the block device file */ |
170 | | |
171 | | if ((ret=sys_stat(path, &S, false))!=0) { |
172 | | return ret; |
173 | | } |
174 | | |
175 | | if ((ret=devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 1))!=0) { |
176 | | return ret; |
177 | | } |
178 | | |
179 | | /* we should get the mntpath right... |
180 | | * but I don't know how |
181 | | * --metze |
182 | | */ |
183 | | (*mntpath) = SMB_STRDUP(path); |
184 | | (*bdev) = SMB_STRDUP(dev_disk); |
185 | | if ((*mntpath)&&(*bdev)) { |
186 | | ret = 0; |
187 | | } else { |
188 | | SAFE_FREE(*mntpath); |
189 | | SAFE_FREE(*bdev); |
190 | | ret = -1; |
191 | | } |
192 | | |
193 | | |
194 | | return ret; |
195 | | } |
196 | | |
197 | | /* #endif HAVE_DEVNM */ |
198 | | #else |
199 | | /* we should fake this up...*/ |
200 | | static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs) |
201 | | { |
202 | | int ret = -1; |
203 | | |
204 | | if (!path||!mntpath||!bdev||!fs) |
205 | | smb_panic("sys_path_to_bdev: called with NULL pointer"); |
206 | | |
207 | | (*mntpath) = NULL; |
208 | | (*bdev) = NULL; |
209 | | (*fs) = NULL; |
210 | | |
211 | | (*mntpath) = SMB_STRDUP(path); |
212 | | if (*mntpath) { |
213 | | ret = 0; |
214 | | } else { |
215 | | SAFE_FREE(*mntpath); |
216 | | ret = -1; |
217 | | } |
218 | | |
219 | | return ret; |
220 | | } |
221 | | #endif |
222 | | |
223 | | /********************************************************************* |
224 | | Now the list of all filesystem specific quota systems we have found |
225 | | **********************************************************************/ |
226 | | static struct { |
227 | | const char *name; |
228 | | int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp); |
229 | | int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp); |
230 | | } sys_quota_backends[] = { |
231 | | #ifdef HAVE_JFS_QUOTA_H |
232 | | {"jfs2", sys_get_jfs2_quota, sys_set_jfs2_quota}, |
233 | | #endif |
234 | | #if defined HAVE_XFS_QUOTAS |
235 | | {"xfs", sys_get_xfs_quota, sys_set_xfs_quota}, |
236 | | {"gfs", sys_get_xfs_quota, sys_set_xfs_quota}, |
237 | | {"gfs2", sys_get_xfs_quota, sys_set_xfs_quota}, |
238 | | #endif /* HAVE_XFS_QUOTAS */ |
239 | | #ifdef HAVE_NFS_QUOTAS |
240 | | {"nfs", sys_get_nfs_quota, sys_set_nfs_quota}, |
241 | | {"nfs4", sys_get_nfs_quota, sys_set_nfs_quota}, |
242 | | #endif /* HAVE_NFS_QUOTAS */ |
243 | | {NULL, NULL, NULL} |
244 | | }; |
245 | | |
246 | | static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) |
247 | 0 | { |
248 | 0 | const struct loadparm_substitution *lp_sub = |
249 | 0 | loadparm_s3_global_substitution(); |
250 | 0 | const char *get_quota_command = NULL; |
251 | 0 | char **lines = NULL; |
252 | 0 | const char *p = NULL; |
253 | 0 | char *p2 = NULL; |
254 | 0 | int _id = -1; |
255 | 0 | int error = 0; |
256 | 0 | char **argl = NULL; |
257 | |
|
258 | 0 | get_quota_command = lp_get_quota_command(talloc_tos(), lp_sub); |
259 | 0 | if ((get_quota_command == NULL) || (get_quota_command[0] == '\0')) { |
260 | 0 | errno = ENOSYS; |
261 | 0 | return -1; |
262 | 0 | } |
263 | | |
264 | 0 | switch(qtype) { |
265 | 0 | case SMB_USER_QUOTA_TYPE: |
266 | 0 | case SMB_USER_FS_QUOTA_TYPE: |
267 | 0 | _id = id.uid; |
268 | 0 | break; |
269 | 0 | case SMB_GROUP_QUOTA_TYPE: |
270 | 0 | case SMB_GROUP_FS_QUOTA_TYPE: |
271 | 0 | _id = id.gid; |
272 | 0 | break; |
273 | 0 | default: |
274 | 0 | DEBUG(0,("invalid quota type.\n")); |
275 | 0 | return -1; |
276 | 0 | } |
277 | | |
278 | 0 | argl = str_list_make_empty(talloc_tos()); |
279 | 0 | str_list_add_printf(&argl, "%s", get_quota_command); |
280 | 0 | str_list_add_printf(&argl, "%s", path); |
281 | 0 | str_list_add_printf(&argl, "%d", qtype); |
282 | 0 | str_list_add_printf(&argl, "%d", _id); |
283 | 0 | if (argl == NULL) { |
284 | 0 | return -1; |
285 | 0 | } |
286 | | |
287 | 0 | DBG_NOTICE("Running command %s %s %d %d\n", |
288 | 0 | get_quota_command, |
289 | 0 | path, |
290 | 0 | qtype, |
291 | 0 | _id); |
292 | |
|
293 | 0 | lines = file_lines_ploadv(talloc_tos(), argl, NULL); |
294 | 0 | TALLOC_FREE(argl); |
295 | |
|
296 | 0 | if (lines) { |
297 | 0 | char *line = lines[0]; |
298 | |
|
299 | 0 | DEBUG (3, ("Read output from get_quota, \"%s\"\n", line)); |
300 | | |
301 | | /* we need to deal with long long unsigned here, if supported */ |
302 | |
|
303 | 0 | dp->qflags = smb_strtoul(line, |
304 | 0 | &p2, |
305 | 0 | 10, |
306 | 0 | &error, |
307 | 0 | SMB_STR_STANDARD); |
308 | 0 | if (error != 0) { |
309 | 0 | goto invalid_param; |
310 | 0 | } |
311 | | |
312 | 0 | p = p2; |
313 | 0 | while (p && *p && isspace(*p)) { |
314 | 0 | p++; |
315 | 0 | } |
316 | |
|
317 | 0 | if (p && *p) { |
318 | 0 | dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p); |
319 | 0 | } else { |
320 | 0 | goto invalid_param; |
321 | 0 | } |
322 | | |
323 | 0 | while (p && *p && isspace(*p)) { |
324 | 0 | p++; |
325 | 0 | } |
326 | |
|
327 | 0 | if (p && *p) { |
328 | 0 | dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p); |
329 | 0 | } else { |
330 | 0 | goto invalid_param; |
331 | 0 | } |
332 | | |
333 | 0 | while (p && *p && isspace(*p)) { |
334 | 0 | p++; |
335 | 0 | } |
336 | |
|
337 | 0 | if (p && *p) { |
338 | 0 | dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p); |
339 | 0 | } else { |
340 | 0 | goto invalid_param; |
341 | 0 | } |
342 | | |
343 | 0 | while (p && *p && isspace(*p)) { |
344 | 0 | p++; |
345 | 0 | } |
346 | |
|
347 | 0 | if (p && *p) { |
348 | 0 | dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p); |
349 | 0 | } else { |
350 | 0 | goto invalid_param; |
351 | 0 | } |
352 | | |
353 | 0 | while (p && *p && isspace(*p)) { |
354 | 0 | p++; |
355 | 0 | } |
356 | |
|
357 | 0 | if (p && *p) { |
358 | 0 | dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p); |
359 | 0 | } else { |
360 | 0 | goto invalid_param; |
361 | 0 | } |
362 | | |
363 | 0 | while (p && *p && isspace(*p)) { |
364 | 0 | p++; |
365 | 0 | } |
366 | |
|
367 | 0 | if (p && *p) { |
368 | 0 | dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p); |
369 | 0 | } else { |
370 | 0 | goto invalid_param; |
371 | 0 | } |
372 | | |
373 | 0 | while (p && *p && isspace(*p)) { |
374 | 0 | p++; |
375 | 0 | } |
376 | |
|
377 | 0 | if (p && *p) { |
378 | 0 | dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL); |
379 | 0 | } else { |
380 | 0 | dp->bsize = 1024; |
381 | 0 | } |
382 | |
|
383 | 0 | TALLOC_FREE(lines); |
384 | 0 | lines = NULL; |
385 | |
|
386 | 0 | DBG_INFO("Parsed output of get_quota, ...\n" |
387 | 0 | "qflags:%" PRIu32 " curblocks:%" PRIu64 |
388 | 0 | " softlimit:%" PRIu64 " hardlimit:%" PRIu64 |
389 | 0 | "\n" |
390 | 0 | "curinodes:%" PRIu64 " isoftlimit:%" PRIu64 |
391 | 0 | " ihardlimit:%" PRIu64 " bsize:%" PRIu64 "\n", |
392 | 0 | dp->qflags, |
393 | 0 | dp->curblocks, |
394 | 0 | dp->softlimit, |
395 | 0 | dp->hardlimit, |
396 | 0 | dp->curinodes, |
397 | 0 | dp->isoftlimit, |
398 | 0 | dp->ihardlimit, |
399 | 0 | dp->bsize); |
400 | 0 | return 0; |
401 | 0 | } |
402 | | |
403 | 0 | DEBUG (0, ("get_quota_command failed!\n")); |
404 | 0 | return -1; |
405 | | |
406 | 0 | invalid_param: |
407 | |
|
408 | 0 | TALLOC_FREE(lines); |
409 | 0 | DEBUG(0,("The output of get_quota_command is invalid!\n")); |
410 | 0 | return -1; |
411 | 0 | } |
412 | | |
413 | | static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) |
414 | 0 | { |
415 | 0 | const struct loadparm_substitution *lp_sub = |
416 | 0 | loadparm_s3_global_substitution(); |
417 | 0 | const char *set_quota_command = NULL; |
418 | 0 | char **lines = NULL; |
419 | 0 | int _id = -1; |
420 | 0 | char **argl = NULL; |
421 | |
|
422 | 0 | set_quota_command = lp_set_quota_command(talloc_tos(), lp_sub); |
423 | |
|
424 | 0 | if ((set_quota_command == NULL) || (set_quota_command[0] == '\0')) { |
425 | 0 | errno = ENOSYS; |
426 | 0 | return -1; |
427 | 0 | } |
428 | | |
429 | 0 | switch (qtype) { |
430 | 0 | case SMB_USER_QUOTA_TYPE: |
431 | 0 | case SMB_USER_FS_QUOTA_TYPE: |
432 | 0 | _id = id.uid; |
433 | 0 | break; |
434 | 0 | case SMB_GROUP_QUOTA_TYPE: |
435 | 0 | case SMB_GROUP_FS_QUOTA_TYPE: |
436 | 0 | _id = id.gid; |
437 | 0 | break; |
438 | 0 | default: |
439 | 0 | return -1; |
440 | 0 | } |
441 | | |
442 | 0 | argl = str_list_make_empty(talloc_tos()); |
443 | 0 | str_list_add_printf(&argl, "%s", set_quota_command); |
444 | 0 | str_list_add_printf(&argl, "%s", path); |
445 | 0 | str_list_add_printf(&argl, "%d", qtype); |
446 | 0 | str_list_add_printf(&argl, "%d", _id); |
447 | 0 | str_list_add_printf(&argl, "%u", dp->qflags); |
448 | 0 | str_list_add_printf(&argl, "%" PRIu64, dp->softlimit); |
449 | 0 | str_list_add_printf(&argl, "%" PRIu64, dp->hardlimit); |
450 | 0 | str_list_add_printf(&argl, "%" PRIu64, dp->isoftlimit); |
451 | 0 | str_list_add_printf(&argl, "%" PRIu64, dp->ihardlimit); |
452 | 0 | str_list_add_printf(&argl, "%" PRIu64, dp->bsize); |
453 | 0 | if (argl == NULL) { |
454 | 0 | return -1; |
455 | 0 | } |
456 | | |
457 | 0 | DBG_NOTICE("Running command " |
458 | 0 | "%s %s %d %d " |
459 | 0 | "%" PRIu32 " %" PRIu64 " %" PRIu64 " " |
460 | 0 | "%" PRIu64 " %" PRIu64 " %" PRIu64 "\n", |
461 | 0 | set_quota_command, |
462 | 0 | path, |
463 | 0 | qtype, |
464 | 0 | _id, |
465 | 0 | dp->qflags, |
466 | 0 | dp->softlimit, |
467 | 0 | dp->hardlimit, |
468 | 0 | dp->isoftlimit, |
469 | 0 | dp->ihardlimit, |
470 | 0 | dp->bsize); |
471 | |
|
472 | 0 | lines = file_lines_ploadv(talloc_tos(), argl, NULL); |
473 | 0 | TALLOC_FREE(argl); |
474 | 0 | if (lines) { |
475 | 0 | char *line = lines[0]; |
476 | |
|
477 | 0 | DEBUG (3, ("Read output from set_quota, \"%s\"\n", line)); |
478 | |
|
479 | 0 | TALLOC_FREE(lines); |
480 | |
|
481 | 0 | return 0; |
482 | 0 | } |
483 | 0 | DEBUG (0, ("set_quota_command failed!\n")); |
484 | 0 | return -1; |
485 | 0 | } |
486 | | |
487 | | int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) |
488 | 0 | { |
489 | 0 | int ret = -1; |
490 | 0 | int i; |
491 | 0 | bool ready = False; |
492 | 0 | char *mntpath = NULL; |
493 | 0 | char *bdev = NULL; |
494 | 0 | char *fs = NULL; |
495 | |
|
496 | 0 | if (!path||!dp) |
497 | 0 | smb_panic("sys_get_quota: called with NULL pointer"); |
498 | | |
499 | 0 | if (command_get_quota(path, qtype, id, dp)==0) { |
500 | 0 | return 0; |
501 | 0 | } else if (errno != ENOSYS) { |
502 | 0 | return -1; |
503 | 0 | } |
504 | | |
505 | 0 | if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { |
506 | 0 | DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path)); |
507 | 0 | return ret; |
508 | 0 | } |
509 | | |
510 | 0 | errno = 0; |
511 | 0 | DEBUG(10,("sys_get_quota() uid(%u, %u), fs(%s)\n", (unsigned)getuid(), (unsigned)geteuid(), fs)); |
512 | |
|
513 | 0 | for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) { |
514 | 0 | if (strcmp(fs,sys_quota_backends[i].name)==0) { |
515 | 0 | ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp); |
516 | 0 | if (ret!=0) { |
517 | 0 | DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n", |
518 | 0 | fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno))); |
519 | 0 | } else { |
520 | 0 | DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n", |
521 | 0 | fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid))); |
522 | 0 | } |
523 | 0 | ready = True; |
524 | 0 | break; |
525 | 0 | } |
526 | 0 | } |
527 | |
|
528 | 0 | if (!ready) { |
529 | | /* use the default vfs quota functions */ |
530 | 0 | ret=sys_get_vfs_quota(mntpath, bdev, qtype, id, dp); |
531 | 0 | if (ret!=0) { |
532 | 0 | DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s\n", |
533 | 0 | "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno))); |
534 | 0 | } else { |
535 | 0 | DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n", |
536 | 0 | "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid))); |
537 | 0 | } |
538 | 0 | } |
539 | |
|
540 | 0 | SAFE_FREE(mntpath); |
541 | 0 | SAFE_FREE(bdev); |
542 | 0 | SAFE_FREE(fs); |
543 | |
|
544 | 0 | return ret; |
545 | 0 | } |
546 | | |
547 | | int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) |
548 | 0 | { |
549 | 0 | int ret = -1; |
550 | 0 | int i; |
551 | 0 | bool ready = False; |
552 | 0 | char *mntpath = NULL; |
553 | 0 | char *bdev = NULL; |
554 | 0 | char *fs = NULL; |
555 | | |
556 | | /* find the block device file */ |
557 | |
|
558 | 0 | if (!path||!dp) |
559 | 0 | smb_panic("get_smb_quota: called with NULL pointer"); |
560 | | |
561 | 0 | if (command_set_quota(path, qtype, id, dp)==0) { |
562 | 0 | return 0; |
563 | 0 | } else if (errno != ENOSYS) { |
564 | 0 | return -1; |
565 | 0 | } |
566 | | |
567 | 0 | if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { |
568 | 0 | DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path)); |
569 | 0 | return ret; |
570 | 0 | } |
571 | | |
572 | 0 | errno = 0; |
573 | 0 | DEBUG(10,("sys_set_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid())); |
574 | |
|
575 | 0 | for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) { |
576 | 0 | if (strcmp(fs,sys_quota_backends[i].name)==0) { |
577 | 0 | ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp); |
578 | 0 | if (ret!=0) { |
579 | 0 | DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n", |
580 | 0 | fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno))); |
581 | 0 | } else { |
582 | 0 | DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n", |
583 | 0 | fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid))); |
584 | 0 | } |
585 | 0 | ready = True; |
586 | 0 | break; |
587 | 0 | } |
588 | 0 | } |
589 | |
|
590 | 0 | if (!ready) { |
591 | | /* use the default vfs quota functions */ |
592 | 0 | ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp); |
593 | 0 | if (ret!=0) { |
594 | 0 | DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n", |
595 | 0 | "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno))); |
596 | 0 | } else { |
597 | 0 | DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n", |
598 | 0 | "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid))); |
599 | 0 | } |
600 | 0 | } |
601 | |
|
602 | 0 | SAFE_FREE(mntpath); |
603 | 0 | SAFE_FREE(bdev); |
604 | 0 | SAFE_FREE(fs); |
605 | |
|
606 | 0 | return ret; |
607 | 0 | } |
608 | | |
609 | | #else /* HAVE_SYS_QUOTAS */ |
610 | | void dummy_sysquotas_c(void); |
611 | | |
612 | | void dummy_sysquotas_c(void) |
613 | | { |
614 | | return; |
615 | | } |
616 | | #endif /* HAVE_SYS_QUOTAS */ |