#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
-static int dfq_get_quota_do(struct vfs_handle_struct *handle, const char *path,
- enum SMB_QUOTA_TYPE qtype, unid_t id,
- SMB_DISK_QUOTA *qt);
+static int dfq_get_quota(struct vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ enum SMB_QUOTA_TYPE qtype,
+ unid_t id,
+ SMB_DISK_QUOTA *qt);
static uint64_t dfq_load_param(int snum, const char *path, const char *section,
const char *param, uint64_t def_val)
return ret;
}
-static bool dfq_disk_quotas(vfs_handle_struct *handle, const char *path,
- uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
-{
- int r;
- SMB_DISK_QUOTA D;
- unid_t id;
-
- id.uid = geteuid();
-
- ZERO_STRUCT(D);
- r = dfq_get_quota_do(handle, path, SMB_USER_QUOTA_TYPE, id, &D);
-
- /* Use softlimit to determine disk space, except when it has been
- * exceeded */
- *bsize = D.bsize;
- if (r == -1) {
- if (errno == EDQUOT) {
- *dfree = 0;
- *dsize = D.curblocks;
- return (true);
- } else {
- goto try_group_quota;
- }
- }
-
- /* Use softlimit to determine disk space, except when it has been
- * exceeded */
- if ((D.softlimit && D.curblocks >= D.softlimit) ||
- (D.hardlimit && D.curblocks >= D.hardlimit) ||
- (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
- (D.ihardlimit && D.curinodes >= D.ihardlimit)) {
- *dfree = 0;
- *dsize = D.curblocks;
- } else if (D.softlimit == 0 && D.hardlimit == 0) {
- goto try_group_quota;
- } else {
- if (D.softlimit == 0) {
- D.softlimit = D.hardlimit;
- }
- *dfree = D.softlimit - D.curblocks;
- *dsize = D.softlimit;
- }
-
- return true;
-
-try_group_quota:
- id.gid = getegid();
-
- ZERO_STRUCT(D);
- r = dfq_get_quota_do(handle, path, SMB_GROUP_QUOTA_TYPE, id, &D);
-
- /* Use softlimit to determine disk space, except when it has been
- * exceeded */
- *bsize = D.bsize;
- if (r == -1) {
- if (errno == EDQUOT) {
- *dfree = 0;
- *dsize = D.curblocks;
- return (true);
- } else {
- return false;
- }
- }
-
- /* Use softlimit to determine disk space, except when it has been
- * exceeded */
- if ((D.softlimit && D.curblocks >= D.softlimit) ||
- (D.hardlimit && D.curblocks >= D.hardlimit) ||
- (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
- (D.ihardlimit && D.curinodes >= D.ihardlimit)) {
- *dfree = 0;
- *dsize = D.curblocks;
- } else if (D.softlimit == 0 && D.hardlimit == 0) {
- return false;
- } else {
- if (D.softlimit == 0) {
- D.softlimit = D.hardlimit;
- }
- *dfree = D.softlimit - D.curblocks;
- *dsize = D.softlimit;
- }
-
- return (true);
-}
-
-static uint64_t dfq_disk_free(vfs_handle_struct *handle, const char *path,
- uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
+static uint64_t dfq_disk_free(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ uint64_t *bsize,
+ uint64_t *dfree,
+ uint64_t *dsize)
{
uint64_t free_1k;
- uint64_t dfree_q = 0;
- uint64_t bsize_q = 0;
- uint64_t dsize_q = 0;
int snum = SNUM(handle->conn);
uint64_t dfq_bsize = 0;
- char *rpath = NULL;
+ struct smb_filename *rpath_fname = NULL;
/* look up the params based on real path to be resilient
* to refactoring of path<->realpath
*/
- rpath = SMB_VFS_NEXT_REALPATH(handle, path);
- if (rpath != NULL) {
- dfq_bsize = dfq_load_param(snum, rpath, "df", "block size", 0);
+ rpath_fname = SMB_VFS_NEXT_REALPATH(handle, talloc_tos(), smb_fname);
+ if (rpath_fname != NULL) {
+ dfq_bsize = dfq_load_param(snum, rpath_fname->base_name,
+ "df", "block size", 0);
}
if (dfq_bsize == 0) {
- SAFE_FREE(rpath);
- return SMB_VFS_NEXT_DISK_FREE(handle, path, bsize, dfree,
+ TALLOC_FREE(rpath_fname);
+ return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname, bsize, dfree,
dsize);
}
*bsize = dfq_bsize;
- *dfree = dfq_load_param(snum, rpath, "df", "disk free", 0);
- *dsize = dfq_load_param(snum, rpath, "df", "disk size", 0);
-
- if (dfq_disk_quotas(handle, path, &bsize_q, &dfree_q, &dsize_q)) {
- (*bsize) = bsize_q;
- (*dfree) = MIN(*dfree, dfree_q);
- (*dsize) = MIN(*dsize, dsize_q);
- }
-
- disk_norm(bsize, dfree, dsize);
+ *dfree = dfq_load_param(snum, rpath_fname->base_name,
+ "df", "disk free", 0);
+ *dsize = dfq_load_param(snum, rpath_fname->base_name,
+ "df", "disk size", 0);
if ((*bsize) < 1024) {
free_1k = (*dfree) / (1024 / (*bsize));
free_1k = ((*bsize) / 1024) * (*dfree);
}
- SAFE_FREE(rpath);
+ TALLOC_FREE(rpath_fname);
return free_1k;
}
-static int dfq_get_quota_do(struct vfs_handle_struct *handle, const char *path,
- enum SMB_QUOTA_TYPE qtype, unid_t id,
- SMB_DISK_QUOTA *qt)
+static int dfq_get_quota(struct vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ enum SMB_QUOTA_TYPE qtype,
+ unid_t id,
+ SMB_DISK_QUOTA *qt)
{
int rc = 0;
int save_errno;
char *section = NULL;
int snum = SNUM(handle->conn);
uint64_t bsize = 0;
- char *rpath = NULL;
+ struct smb_filename *rpath_fname = NULL;
- rpath = SMB_VFS_NEXT_REALPATH(handle, path);
- if (rpath == NULL) {
+ rpath_fname = SMB_VFS_NEXT_REALPATH(handle, talloc_tos(), smb_fname);
+ if (rpath_fname == NULL) {
goto dflt;
}
section = talloc_asprintf(talloc_tos(), "g%llu",
(unsigned long long)id.gid);
break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ section = talloc_strdup(talloc_tos(), "udflt");
+ break;
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ section = talloc_strdup(talloc_tos(), "gdflt");
+ break;
default:
break;
}
goto dflt;
}
- bsize = dfq_load_param(snum, rpath, section, "block size", 0);
+ bsize = dfq_load_param(snum, rpath_fname->base_name,
+ section, "block size", 4096);
if (bsize == 0) {
goto dflt;
}
- if (dfq_load_param(snum, rpath, section, "err", 0) != 0) {
+ if (dfq_load_param(snum, rpath_fname->base_name,
+ section, "err", 0) != 0) {
errno = ENOTSUP;
rc = -1;
goto out;
}
+ if (dfq_load_param(snum, rpath_fname->base_name,
+ section, "nosys", 0) != 0) {
+ errno = ENOSYS;
+ rc = -1;
+ goto out;
+ }
+
ZERO_STRUCTP(qt);
qt->bsize = bsize;
- qt->hardlimit = dfq_load_param(snum, rpath, section, "hard limit", 0);
- qt->softlimit = dfq_load_param(snum, rpath, section, "soft limit", 0);
- qt->curblocks = dfq_load_param(snum, rpath, section, "cur blocks", 0);
+ qt->hardlimit = dfq_load_param(snum, rpath_fname->base_name,
+ section, "hard limit", 0);
+ qt->softlimit = dfq_load_param(snum, rpath_fname->base_name,
+ section, "soft limit", 0);
+ qt->curblocks = dfq_load_param(snum, rpath_fname->base_name,
+ section, "cur blocks", 0);
qt->ihardlimit =
- dfq_load_param(snum, rpath, section, "inode hard limit", 0);
+ dfq_load_param(snum, rpath_fname->base_name,
+ section, "inode hard limit", 0);
qt->isoftlimit =
- dfq_load_param(snum, rpath, section, "inode soft limit", 0);
- qt->curinodes = dfq_load_param(snum, rpath, section, "cur inodes", 0);
-
- if (dfq_load_param(snum, rpath, section, "edquot", 0) != 0) {
- errno = EDQUOT;
- rc = -1;
- }
+ dfq_load_param(snum, rpath_fname->base_name,
+ section, "inode soft limit", 0);
+ qt->curinodes = dfq_load_param(snum, rpath_fname->base_name,
+ section, "cur inodes", 0);
+ qt->qflags = dfq_load_param(snum, rpath_fname->base_name,
+ section, "qflags", QUOTAS_DENY_DISK);
goto out;
dflt:
- rc = SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, qt);
+ rc = SMB_VFS_NEXT_GET_QUOTA(handle, smb_fname, qtype, id, qt);
out:
save_errno = errno;
TALLOC_FREE(section);
- SAFE_FREE(rpath);
+ TALLOC_FREE(rpath_fname);
errno = save_errno;
return rc;
}
-static int dfq_get_quota(struct vfs_handle_struct *handle,
- enum SMB_QUOTA_TYPE qtype, unid_t id,
- SMB_DISK_QUOTA *qt)
+static void dfq_fake_stat(struct vfs_handle_struct *handle,
+ struct smb_filename *smb_fname,
+ SMB_STRUCT_STAT *sbuf)
{
- return dfq_get_quota_do(handle, handle->conn->connectpath, qtype, id,
- qt);
+ int snum = SNUM(handle->conn);
+ char *full_path = NULL;
+ char *to_free = NULL;
+ char path[PATH_MAX + 1];
+ int len;
+ gid_t gid;
+
+ len = full_path_tos(handle->conn->cwd_fsp->fsp_name->base_name,
+ smb_fname->base_name,
+ path, sizeof(path),
+ &full_path, &to_free);
+ if (len == -1) {
+ DBG_ERR("Could not allocate memory in full_path_tos.\n");
+ return;
+ }
+
+ gid = dfq_load_param(snum, full_path, "stat", "sgid", 0);
+ if (gid != 0) {
+ sbuf->st_ex_gid = gid;
+ sbuf->st_ex_mode |= S_ISGID;
+ }
+
+ TALLOC_FREE(to_free);
+}
+
+static int dfq_stat(vfs_handle_struct *handle,
+ struct smb_filename *smb_fname)
+{
+ int ret;
+
+ ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
+ if (ret == -1) {
+ return ret;
+ }
+
+ dfq_fake_stat(handle, smb_fname, &smb_fname->st);
+
+ return 0;
+}
+
+static int dfq_fstat(vfs_handle_struct *handle,
+ files_struct *fsp,
+ SMB_STRUCT_STAT *sbuf)
+{
+ int ret;
+
+ ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+ if (ret == -1) {
+ return ret;
+ }
+
+ dfq_fake_stat(handle, fsp->fsp_name, sbuf);
+
+ return 0;
+}
+
+static int dfq_lstat(vfs_handle_struct *handle,
+ struct smb_filename *smb_fname)
+{
+ int ret;
+
+ ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+ if (ret == -1) {
+ return ret;
+ }
+
+ dfq_fake_stat(handle, smb_fname, &smb_fname->st);
+
+ return 0;
}
struct vfs_fn_pointers vfs_fake_dfq_fns = {
.disk_free_fn = dfq_disk_free,
.get_quota_fn = dfq_get_quota,
+
+ .stat_fn = dfq_stat,
+ .fstat_fn = dfq_fstat,
+ .lstat_fn = dfq_lstat,
};
static_decl_vfs;
-NTSTATUS vfs_fake_dfq_init(void)
+NTSTATUS vfs_fake_dfq_init(TALLOC_CTX *ctx)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fake_dfq",
&vfs_fake_dfq_fns);