From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- source3/modules/vfs_fake_dfq.c | 281 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 source3/modules/vfs_fake_dfq.c (limited to 'source3/modules/vfs_fake_dfq.c') diff --git a/source3/modules/vfs_fake_dfq.c b/source3/modules/vfs_fake_dfq.c new file mode 100644 index 0000000..47c0b07 --- /dev/null +++ b/source3/modules/vfs_fake_dfq.c @@ -0,0 +1,281 @@ +/* + * Fake Disk-Free and Quota VFS module. Implements passthrough operation + * of all VFS calls, except for "disk free" and "get quota" which + * are handled by reading a text file named ".dfq" in the current directory. + * + * This module is intended for testing purposes. + * + * Copyright (C) Uri Simchoni, 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" +#include "smbd/smbd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + +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) +{ + uint64_t ret; + + char *option = + talloc_asprintf(talloc_tos(), "%s/%s/%s", section, param, path); + if (option == NULL) { + return def_val; + } + + ret = (uint64_t)lp_parm_ulonglong(snum, "fake_dfq", option, + (unsigned long long)def_val); + + TALLOC_FREE(option); + + return ret; +} + +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; + int snum = SNUM(handle->conn); + uint64_t dfq_bsize = 0; + struct smb_filename *rpath_fname = NULL; + + /* look up the params based on real path to be resilient + * to refactoring of path<->realpath + */ + 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) { + 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_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)); + } else { + free_1k = ((*bsize) / 1024) * (*dfree); + } + + TALLOC_FREE(rpath_fname); + return free_1k; +} + +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; + struct smb_filename *rpath_fname = NULL; + + rpath_fname = SMB_VFS_NEXT_REALPATH(handle, talloc_tos(), smb_fname); + if (rpath_fname == NULL) { + goto dflt; + } + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + section = talloc_asprintf(talloc_tos(), "u%llu", + (unsigned long long)id.uid); + break; + case SMB_GROUP_QUOTA_TYPE: + 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; + } + + if (section == NULL) { + goto dflt; + } + + bsize = dfq_load_param(snum, rpath_fname->base_name, + section, "block size", 4096); + if (bsize == 0) { + goto dflt; + } + + 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_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_fname->base_name, + section, "inode hard limit", 0); + qt->isoftlimit = + 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, smb_fname, qtype, id, qt); + +out: + save_errno = errno; + TALLOC_FREE(section); + TALLOC_FREE(rpath_fname); + errno = save_errno; + return rc; +} + +static void dfq_fake_stat(struct vfs_handle_struct *handle, + struct smb_filename *smb_fname, + SMB_STRUCT_STAT *sbuf) +{ + 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 operations */ + + .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(TALLOC_CTX *ctx) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fake_dfq", + &vfs_fake_dfq_fns); +} -- cgit v1.2.3