PageRenderTime 41ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/release/src/router/samba3/source/lib/sysquotas.c

https://gitlab.com/envieidoc/tomato
C | 542 lines | 400 code | 103 blank | 39 comment | 102 complexity | a6c0462946a3142c55a3ba18b57cea92 MD5 | raw file
  1. /*
  2. Unix SMB/CIFS implementation.
  3. System QUOTA function wrappers
  4. Copyright (C) Stefan (metze) Metzmacher 2003
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include "includes.h"
  18. #undef DBGC_CLASS
  19. #define DBGC_CLASS DBGC_QUOTA
  20. #ifdef HAVE_SYS_QUOTAS
  21. #if defined(HAVE_QUOTACTL_4A)
  22. /*#endif HAVE_QUOTACTL_4A */
  23. #elif defined(HAVE_QUOTACTL_4B)
  24. #error HAVE_QUOTACTL_4B not implemeted
  25. /*#endif HAVE_QUOTACTL_4B */
  26. #elif defined(HAVE_QUOTACTL_3)
  27. #error HAVE_QUOTACTL_3 not implemented
  28. /* #endif HAVE_QUOTACTL_3 */
  29. #else /* NO_QUOTACTL_USED */
  30. #endif /* NO_QUOTACTL_USED */
  31. #ifdef HAVE_MNTENT
  32. static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
  33. {
  34. int ret = -1;
  35. SMB_STRUCT_STAT S;
  36. FILE *fp;
  37. struct mntent *mnt;
  38. SMB_DEV_T devno;
  39. /* find the block device file */
  40. if (!path||!mntpath||!bdev||!fs)
  41. smb_panic("sys_path_to_bdev: called with NULL pointer");
  42. (*mntpath) = NULL;
  43. (*bdev) = NULL;
  44. (*fs) = NULL;
  45. if ( sys_stat(path, &S) == -1 )
  46. return (-1);
  47. devno = S.st_dev ;
  48. fp = setmntent(MOUNTED,"r");
  49. if (fp == NULL) {
  50. return -1;
  51. }
  52. while ((mnt = getmntent(fp))) {
  53. if ( sys_stat(mnt->mnt_dir,&S) == -1 )
  54. continue ;
  55. if (S.st_dev == devno) {
  56. (*mntpath) = SMB_STRDUP(mnt->mnt_dir);
  57. (*bdev) = SMB_STRDUP(mnt->mnt_fsname);
  58. (*fs) = SMB_STRDUP(mnt->mnt_type);
  59. if ((*mntpath)&&(*bdev)&&(*fs)) {
  60. ret = 0;
  61. } else {
  62. SAFE_FREE(*mntpath);
  63. SAFE_FREE(*bdev);
  64. SAFE_FREE(*fs);
  65. ret = -1;
  66. }
  67. break;
  68. }
  69. }
  70. endmntent(fp) ;
  71. return ret;
  72. }
  73. /* #endif HAVE_MNTENT */
  74. #elif defined(HAVE_DEVNM)
  75. /* we have this on HPUX, ... */
  76. static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
  77. {
  78. int ret = -1;
  79. char dev_disk[256];
  80. SMB_STRUCT_STAT S;
  81. if (!path||!mntpath||!bdev||!fs)
  82. smb_panic("sys_path_to_bdev: called with NULL pointer");
  83. (*mntpath) = NULL;
  84. (*bdev) = NULL;
  85. (*fs) = NULL;
  86. /* find the block device file */
  87. if ((ret=sys_stat(path, &S))!=0) {
  88. return ret;
  89. }
  90. if ((ret=devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1))!=0) {
  91. return ret;
  92. }
  93. /* we should get the mntpath right...
  94. * but I don't know how
  95. * --metze
  96. */
  97. (*mntpath) = SMB_STRDUP(path);
  98. (*bdev) = SMB_STRDUP(dev_disk);
  99. if ((*mntpath)&&(*bdev)) {
  100. ret = 0;
  101. } else {
  102. SAFE_FREE(*mntpath);
  103. SAFE_FREE(*bdev);
  104. ret = -1;
  105. }
  106. return ret;
  107. }
  108. /* #endif HAVE_DEVNM */
  109. #else
  110. /* we should fake this up...*/
  111. static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs)
  112. {
  113. int ret = -1;
  114. if (!path||!mntpath||!bdev||!fs)
  115. smb_panic("sys_path_to_bdev: called with NULL pointer");
  116. (*mntpath) = NULL;
  117. (*bdev) = NULL;
  118. (*fs) = NULL;
  119. (*mntpath) = SMB_STRDUP(path);
  120. if (*mntpath) {
  121. ret = 0;
  122. } else {
  123. SAFE_FREE(*mntpath);
  124. ret = -1;
  125. }
  126. return ret;
  127. }
  128. #endif
  129. /*********************************************************************
  130. Now the list of all filesystem specific quota systems we have found
  131. **********************************************************************/
  132. static struct {
  133. const char *name;
  134. int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
  135. int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
  136. } sys_quota_backends[] = {
  137. #ifdef HAVE_XFS_QUOTAS
  138. {"xfs", sys_get_xfs_quota, sys_set_xfs_quota},
  139. #endif /* HAVE_XFS_QUOTAS */
  140. {NULL, NULL, NULL}
  141. };
  142. static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
  143. {
  144. const char *get_quota_command;
  145. char **lines = NULL;
  146. get_quota_command = lp_get_quota_command();
  147. if (get_quota_command && *get_quota_command) {
  148. const char *p;
  149. char *p2;
  150. pstring syscmd;
  151. int _id = -1;
  152. switch(qtype) {
  153. case SMB_USER_QUOTA_TYPE:
  154. case SMB_USER_FS_QUOTA_TYPE:
  155. _id = id.uid;
  156. break;
  157. case SMB_GROUP_QUOTA_TYPE:
  158. case SMB_GROUP_FS_QUOTA_TYPE:
  159. _id = id.gid;
  160. break;
  161. default:
  162. DEBUG(0,("invalid quota type.\n"));
  163. return -1;
  164. }
  165. slprintf(syscmd, sizeof(syscmd)-1,
  166. "%s \"%s\" %d %d",
  167. get_quota_command, path, qtype, _id);
  168. DEBUG (3, ("get_quota: Running command %s\n", syscmd));
  169. lines = file_lines_pload(syscmd, NULL);
  170. if (lines) {
  171. char *line = lines[0];
  172. DEBUG (3, ("Read output from get_quota, \"%s\"\n", line));
  173. /* we need to deal with long long unsigned here, if supported */
  174. dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10);
  175. p = p2;
  176. while (p && *p && isspace(*p)) {
  177. p++;
  178. }
  179. if (p && *p) {
  180. dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p);
  181. } else {
  182. goto invalid_param;
  183. }
  184. while (p && *p && isspace(*p)) {
  185. p++;
  186. }
  187. if (p && *p) {
  188. dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p);
  189. } else {
  190. goto invalid_param;
  191. }
  192. while (p && *p && isspace(*p)) {
  193. p++;
  194. }
  195. if (p && *p) {
  196. dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p);
  197. } else {
  198. goto invalid_param;
  199. }
  200. while (p && *p && isspace(*p)) {
  201. p++;
  202. }
  203. if (p && *p) {
  204. dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p);
  205. } else {
  206. goto invalid_param;
  207. }
  208. while (p && *p && isspace(*p)) {
  209. p++;
  210. }
  211. if (p && *p) {
  212. dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p);
  213. } else {
  214. goto invalid_param;
  215. }
  216. while (p && *p && isspace(*p)) {
  217. p++;
  218. }
  219. if (p && *p) {
  220. dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p);
  221. } else {
  222. goto invalid_param;
  223. }
  224. while (p && *p && isspace(*p)) {
  225. p++;
  226. }
  227. if (p && *p) {
  228. dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL);
  229. } else {
  230. dp->bsize = 1024;
  231. }
  232. file_lines_free(lines);
  233. lines = NULL;
  234. DEBUG (3, ("Parsed output of get_quota, ...\n"));
  235. #ifdef LARGE_SMB_OFF_T
  236. DEBUGADD (5,(
  237. "qflags:%u curblocks:%llu softlimit:%llu hardlimit:%llu\n"
  238. "curinodes:%llu isoftlimit:%llu ihardlimit:%llu bsize:%llu\n",
  239. dp->qflags,(long long unsigned)dp->curblocks,
  240. (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
  241. (long long unsigned)dp->curinodes,
  242. (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
  243. (long long unsigned)dp->bsize));
  244. #else /* LARGE_SMB_OFF_T */
  245. DEBUGADD (5,(
  246. "qflags:%u curblocks:%lu softlimit:%lu hardlimit:%lu\n"
  247. "curinodes:%lu isoftlimit:%lu ihardlimit:%lu bsize:%lu\n",
  248. dp->qflags,(long unsigned)dp->curblocks,
  249. (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
  250. (long unsigned)dp->curinodes,
  251. (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
  252. (long unsigned)dp->bsize));
  253. #endif /* LARGE_SMB_OFF_T */
  254. return 0;
  255. }
  256. DEBUG (0, ("get_quota_command failed!\n"));
  257. return -1;
  258. }
  259. errno = ENOSYS;
  260. return -1;
  261. invalid_param:
  262. file_lines_free(lines);
  263. DEBUG(0,("The output of get_quota_command is invalid!\n"));
  264. return -1;
  265. }
  266. static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
  267. {
  268. const char *set_quota_command;
  269. set_quota_command = lp_set_quota_command();
  270. if (set_quota_command && *set_quota_command) {
  271. char **lines;
  272. pstring syscmd;
  273. int _id = -1;
  274. switch(qtype) {
  275. case SMB_USER_QUOTA_TYPE:
  276. case SMB_USER_FS_QUOTA_TYPE:
  277. _id = id.uid;
  278. break;
  279. case SMB_GROUP_QUOTA_TYPE:
  280. case SMB_GROUP_FS_QUOTA_TYPE:
  281. _id = id.gid;
  282. break;
  283. default:
  284. return -1;
  285. }
  286. #ifdef LARGE_SMB_OFF_T
  287. slprintf(syscmd, sizeof(syscmd)-1,
  288. "%s \"%s\" %d %d "
  289. "%u %llu %llu "
  290. "%llu %llu %llu ",
  291. set_quota_command, path, qtype, _id, dp->qflags,
  292. (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit,
  293. (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit,
  294. (long long unsigned)dp->bsize);
  295. #else /* LARGE_SMB_OFF_T */
  296. slprintf(syscmd, sizeof(syscmd)-1,
  297. "%s \"%s\" %d %d "
  298. "%u %lu %lu "
  299. "%lu %lu %lu ",
  300. set_quota_command, path, qtype, _id, dp->qflags,
  301. (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit,
  302. (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit,
  303. (long unsigned)dp->bsize);
  304. #endif /* LARGE_SMB_OFF_T */
  305. DEBUG (3, ("get_quota: Running command %s\n", syscmd));
  306. lines = file_lines_pload(syscmd, NULL);
  307. if (lines) {
  308. char *line = lines[0];
  309. DEBUG (3, ("Read output from set_quota, \"%s\"\n", line));
  310. file_lines_free(lines);
  311. return 0;
  312. }
  313. DEBUG (0, ("set_quota_command failed!\n"));
  314. return -1;
  315. }
  316. errno = ENOSYS;
  317. return -1;
  318. }
  319. int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
  320. {
  321. int ret = -1;
  322. int i;
  323. BOOL ready = False;
  324. char *mntpath = NULL;
  325. char *bdev = NULL;
  326. char *fs = NULL;
  327. if (!path||!dp)
  328. smb_panic("sys_get_quota: called with NULL pointer");
  329. if (command_get_quota(path, qtype, id, dp)==0) {
  330. return 0;
  331. } else if (errno != ENOSYS) {
  332. return -1;
  333. }
  334. if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
  335. DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
  336. return ret;
  337. }
  338. errno = 0;
  339. DEBUG(10,("sys_get_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid()));
  340. for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) {
  341. if (strcmp(fs,sys_quota_backends[i].name)==0) {
  342. ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp);
  343. if (ret!=0) {
  344. DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
  345. fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
  346. } else {
  347. DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
  348. fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
  349. }
  350. ready = True;
  351. break;
  352. }
  353. }
  354. if (!ready) {
  355. /* use the default vfs quota functions */
  356. ret=sys_get_vfs_quota(mntpath, bdev, qtype, id, dp);
  357. if (ret!=0) {
  358. DEBUG(3,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s\n",
  359. "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
  360. } else {
  361. DEBUG(10,("sys_get_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
  362. "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
  363. }
  364. }
  365. SAFE_FREE(mntpath);
  366. SAFE_FREE(bdev);
  367. SAFE_FREE(fs);
  368. if ((ret!=0)&& (errno == EDQUOT)) {
  369. DEBUG(10,("sys_get_quota() warning over quota!\n"));
  370. return 0;
  371. }
  372. return ret;
  373. }
  374. int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
  375. {
  376. int ret = -1;
  377. int i;
  378. BOOL ready = False;
  379. char *mntpath = NULL;
  380. char *bdev = NULL;
  381. char *fs = NULL;
  382. /* find the block device file */
  383. if (!path||!dp)
  384. smb_panic("get_smb_quota: called with NULL pointer");
  385. if (command_set_quota(path, qtype, id, dp)==0) {
  386. return 0;
  387. } else if (errno != ENOSYS) {
  388. return -1;
  389. }
  390. if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) {
  391. DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path));
  392. return ret;
  393. }
  394. errno = 0;
  395. DEBUG(10,("sys_set_quota() uid(%u, %u)\n", (unsigned)getuid(), (unsigned)geteuid()));
  396. for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) {
  397. if (strcmp(fs,sys_quota_backends[i].name)==0) {
  398. ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp);
  399. if (ret!=0) {
  400. DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
  401. fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
  402. } else {
  403. DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
  404. fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
  405. }
  406. ready = True;
  407. break;
  408. }
  409. }
  410. if (!ready) {
  411. /* use the default vfs quota functions */
  412. ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp);
  413. if (ret!=0) {
  414. DEBUG(3,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d]: %s.\n",
  415. "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),strerror(errno)));
  416. } else {
  417. DEBUG(10,("sys_set_%s_quota() called for mntpath[%s] bdev[%s] qtype[%d] id[%d].\n",
  418. "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid)));
  419. }
  420. }
  421. SAFE_FREE(mntpath);
  422. SAFE_FREE(bdev);
  423. SAFE_FREE(fs);
  424. if ((ret!=0)&& (errno == EDQUOT)) {
  425. DEBUG(10,("sys_set_quota() warning over quota!\n"));
  426. return 0;
  427. }
  428. return ret;
  429. }
  430. #else /* HAVE_SYS_QUOTAS */
  431. void dummy_sysquotas_c(void);
  432. void dummy_sysquotas_c(void)
  433. {
  434. return;
  435. }
  436. #endif /* HAVE_SYS_QUOTAS */