1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00
samba-mirror/source3/modules/vfs_fake_dfq.c
Jeremy Allison 606398a3a6 s3: VFS: Add SMB_VFS_RENAMEAT().
Currently identical to SMB_VFS_RENAME() - uses
AT_FDCWD for both src and dst directories.

Next, move add to all VFS modules that implement
rename and eventually remove rename.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2019-08-16 19:52:32 +00:00

282 lines
6.6 KiB
C

/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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);
}