1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-27 22:50:26 +03:00

s3: VFS: Change SMB_VFS_REALPATH to take and return struct smb_filename * instead of char *.

We need to migrate all pathname based VFS calls to use a struct
to finish modernising the VFS with extra timestamp and flags parameters.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com>
This commit is contained in:
Jeremy Allison 2017-06-30 11:32:59 -07:00
parent bd9285b197
commit c29438f823
20 changed files with 309 additions and 188 deletions

View File

@ -512,7 +512,9 @@ static int skel_mknod(vfs_handle_struct *handle,
return -1;
}
static char *skel_realpath(vfs_handle_struct *handle, const char *path)
static struct smb_filename *skel_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
errno = ENOSYS;
return NULL;

View File

@ -602,9 +602,11 @@ static int skel_mknod(vfs_handle_struct *handle,
return SMB_VFS_NEXT_MKNOD(handle, smb_fname, mode, dev);
}
static char *skel_realpath(vfs_handle_struct *handle, const char *path)
static struct smb_filename *skel_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
return SMB_VFS_NEXT_REALPATH(handle, path);
return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
}
static int skel_chflags(vfs_handle_struct *handle,

View File

@ -234,6 +234,8 @@
to const struct smb_filename * */
/* Version 37 - Change conn->cwd from char *
to struct smb_filename * */
/* Version 37 - Change realpath from char *
to struct smb_filename * */
#define SMB_VFS_INTERFACE_VERSION 37
@ -769,7 +771,9 @@ struct vfs_fn_pointers {
const struct smb_filename *smb_fname,
mode_t mode,
SMB_DEV_T dev);
char *(*realpath_fn)(struct vfs_handle_struct *handle, const char *path);
struct smb_filename *(*realpath_fn)(struct vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname);
int (*chflags_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
unsigned int flags);
@ -1279,7 +1283,9 @@ int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode,
SMB_DEV_T dev);
char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path);
struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname);
int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
unsigned int flags);

View File

@ -331,10 +331,10 @@
#define SMB_VFS_NEXT_MKNOD(handle, smb_fname, mode, dev) \
smb_vfs_call_mknod((handle)->next, (smb_fname), (mode), (dev))
#define SMB_VFS_REALPATH(conn, path) \
smb_vfs_call_realpath((conn)->vfs_handles, (path))
#define SMB_VFS_NEXT_REALPATH(handle, path) \
smb_vfs_call_realpath((handle)->next, (path))
#define SMB_VFS_REALPATH(conn, ctx, smb_fname) \
smb_vfs_call_realpath((conn)->vfs_handles, (ctx), (smb_fname))
#define SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname) \
smb_vfs_call_realpath((handle)->next, (ctx), (smb_fname))
#define SMB_VFS_CHFLAGS(conn, smb_fname, flags) \
smb_vfs_call_chflags((conn)->vfs_handles, (smb_fname), (flags))

View File

@ -667,16 +667,40 @@ static int cap_mknod(vfs_handle_struct *handle,
return ret;
}
static char *cap_realpath(vfs_handle_struct *handle, const char *path)
static struct smb_filename *cap_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
/* monyo need capencode'ed and capdecode'ed? */
char *cappath = capencode(talloc_tos(), path);
struct smb_filename *cap_smb_fname = NULL;
struct smb_filename *return_fname = NULL;
char *cappath = capencode(talloc_tos(), smb_fname->base_name);
int saved_errno = 0;
if (!cappath) {
errno = ENOMEM;
return NULL;
}
return SMB_VFS_NEXT_REALPATH(handle, cappath);
cap_smb_fname = synthetic_smb_fname(ctx,
cappath,
NULL,
NULL,
smb_fname->flags);
if (cap_smb_fname == NULL) {
TALLOC_FREE(cappath);
errno = ENOMEM;
return NULL;
}
return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, cap_smb_fname);
if (return_fname == NULL) {
saved_errno = errno;
}
TALLOC_FREE(cappath);
TALLOC_FREE(cap_smb_fname);
if (saved_errno != 0) {
errno = saved_errno;
}
return return_fname;
}
static int cap_chmod_acl(vfs_handle_struct *handle,

View File

@ -1055,24 +1055,38 @@ static int catia_ntimes(vfs_handle_struct *handle,
return ret;
}
static char *
catia_realpath(vfs_handle_struct *handle, const char *path)
static struct smb_filename *
catia_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
char *mapped_name = NULL;
struct smb_filename *catia_smb_fname = NULL;
struct smb_filename *return_fname = NULL;
NTSTATUS status;
char *ret = NULL;
status = catia_string_replace_allocate(handle->conn, path,
status = catia_string_replace_allocate(handle->conn,
smb_fname->base_name,
&mapped_name, vfs_translate_to_unix);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return NULL;
}
ret = SMB_VFS_NEXT_REALPATH(handle, mapped_name);
catia_smb_fname = synthetic_smb_fname(talloc_tos(),
mapped_name,
NULL,
NULL,
smb_fname->flags);
if (catia_smb_fname == NULL) {
TALLOC_FREE(mapped_name);
errno = ENOMEM;
return NULL;
}
return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, catia_smb_fname);
TALLOC_FREE(mapped_name);
return ret;
TALLOC_FREE(catia_smb_fname);
return return_fname;
}
static int catia_chflags(struct vfs_handle_struct *handle,

View File

@ -1191,10 +1191,14 @@ static int cephwrap_mknod(struct vfs_handle_struct *handle,
* This is a simple version of real-path ... a better version is needed to
* ask libceph about symbolic links.
*/
static char *cephwrap_realpath(struct vfs_handle_struct *handle, const char *path)
static struct smb_filename *cephwrap_realpath(struct vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
char *result;
const char *path = smb_fname->base_name;
size_t len = strlen(path);
struct smb_filename *result_fname = NULL;
result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
if (len && (path[0] == '/')) {
@ -1216,7 +1220,13 @@ static char *cephwrap_realpath(struct vfs_handle_struct *handle, const char *pa
if (r < 0) return NULL;
}
DBG_DEBUG("[CEPH] realpath(%p, %s) = %s\n", handle, path, result);
return result;
result_fname = synthetic_smb_fname(ctx,
result,
NULL,
NULL,
0);
SAFE_FREE(result);
return result_fname;
}
static int cephwrap_chflags(struct vfs_handle_struct *handle,

View File

@ -2487,14 +2487,21 @@ static int vfswrap_mknod(vfs_handle_struct *handle,
return result;
}
static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
char *result;
struct smb_filename *result_fname = NULL;
START_PROFILE(syscall_realpath);
result = sys_realpath(path);
result = sys_realpath(smb_fname->base_name);
END_PROFILE(syscall_realpath);
return result;
if (result) {
result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
SAFE_FREE(result);
}
return result_fname;
}
static int vfswrap_chflags(vfs_handle_struct *handle,

View File

@ -61,24 +61,27 @@ static uint64_t dfq_disk_free(vfs_handle_struct *handle,
uint64_t free_1k;
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, smb_fname->base_name);
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);
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);
*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));
@ -86,7 +89,7 @@ static uint64_t dfq_disk_free(vfs_handle_struct *handle,
free_1k = ((*bsize) / 1024) * (*dfree);
}
SAFE_FREE(rpath);
TALLOC_FREE(rpath_fname);
return free_1k;
}
@ -101,10 +104,10 @@ static int dfq_get_quota(struct vfs_handle_struct *handle,
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, smb_fname->base_name);
if (rpath == NULL) {
rpath_fname = SMB_VFS_NEXT_REALPATH(handle, talloc_tos(), smb_fname);
if (rpath_fname == NULL) {
goto dflt;
}
@ -131,18 +134,21 @@ static int dfq_get_quota(struct vfs_handle_struct *handle,
goto dflt;
}
bsize = dfq_load_param(snum, rpath, section, "block size", 4096);
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, section, "nosys", 0) != 0) {
if (dfq_load_param(snum, rpath_fname->base_name,
section, "nosys", 0) != 0) {
errno = ENOSYS;
rc = -1;
goto out;
@ -151,15 +157,22 @@ static int dfq_get_quota(struct vfs_handle_struct *handle,
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);
qt->qflags = dfq_load_param(snum, rpath, section, "qflags", QUOTAS_DENY_DISK);
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;
@ -169,7 +182,7 @@ dflt:
out:
save_errno = errno;
TALLOC_FREE(section);
SAFE_FREE(rpath);
TALLOC_FREE(rpath_fname);
errno = save_errno;
return rc;
}

View File

@ -1685,16 +1685,18 @@ static int smb_full_audit_mknod(vfs_handle_struct *handle,
return result;
}
static char *smb_full_audit_realpath(vfs_handle_struct *handle,
const char *path)
static struct smb_filename *smb_full_audit_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
char *result;
struct smb_filename *result_fname = NULL;
result = SMB_VFS_NEXT_REALPATH(handle, path);
result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
do_log(SMB_VFS_OP_REALPATH, (result != NULL), handle, "%s", path);
do_log(SMB_VFS_OP_REALPATH, (result_fname != NULL), handle, "%s",
smb_fname->base_name);
return result;
return result_fname;
}
static int smb_full_audit_chflags(vfs_handle_struct *handle,

View File

@ -1149,10 +1149,12 @@ static int vfs_gluster_fallocate(struct vfs_handle_struct *handle,
return -1;
}
static char *vfs_gluster_realpath(struct vfs_handle_struct *handle,
const char *path)
static struct smb_filename *vfs_gluster_realpath(struct vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
char *result = NULL;
struct smb_filename *result_fname = NULL;
char *resolved_path = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
if (resolved_path == NULL) {
@ -1160,12 +1162,15 @@ static char *vfs_gluster_realpath(struct vfs_handle_struct *handle,
return NULL;
}
result = glfs_realpath(handle->data, path, resolved_path);
if (result == NULL) {
SAFE_FREE(resolved_path);
result = glfs_realpath(handle->data,
smb_fname->base_name,
resolved_path);
if (result != NULL) {
result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
}
return result;
SAFE_FREE(resolved_path);
return result_fname;
}
static bool vfs_gluster_lock(struct vfs_handle_struct *handle,

View File

@ -1863,36 +1863,28 @@ out:
* Success: return path pointer
* Failure: set errno, return NULL pointer
*/
static char *mh_realpath(vfs_handle_struct *handle,
const char *path)
static struct smb_filename *mh_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
char *buf;
char *clientPath;
TALLOC_CTX *ctx;
struct smb_filename *result_fname = NULL;
struct smb_filename *clientFname = NULL;
DEBUG(MH_INFO_DEBUG, ("Entering mh_realpath\n"));
if (!is_in_media_files(path))
{
buf = SMB_VFS_NEXT_REALPATH(handle, path);
goto out;
if (!is_in_media_files(smb_fname->base_name)) {
return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
}
clientPath = NULL;
ctx = talloc_tos();
if (alloc_get_client_path(handle, ctx,
path,
&clientPath))
{
buf = NULL;
if (alloc_get_client_smb_fname(handle, ctx,
smb_fname,
&clientFname) != 0) {
goto err;
}
buf = SMB_VFS_NEXT_REALPATH(handle, clientPath);
result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, clientFname);
err:
TALLOC_FREE(clientPath);
out:
return buf;
TALLOC_FREE(clientFname);
return result_fname;
}
/*

View File

@ -78,8 +78,8 @@ struct shadow_copy2_private {
char *shadow_cwd; /* Absolute $cwd path. */
/* Absolute connectpath - can vary depending on $cwd. */
char *shadow_connectpath;
/* malloc'ed realpath return. */
char *shadow_realpath;
/* talloc'ed realpath return. */
struct smb_filename *shadow_realpath;
};
static int shadow_copy2_get_shadow_copy_data(
@ -1742,40 +1742,47 @@ static int shadow_copy2_mknod(vfs_handle_struct *handle,
return ret;
}
static char *shadow_copy2_realpath(vfs_handle_struct *handle,
const char *fname)
static struct smb_filename *shadow_copy2_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
time_t timestamp = 0;
char *stripped = NULL;
char *tmp = NULL;
char *result = NULL;
struct smb_filename *result_fname = NULL;
struct smb_filename *conv_fname = NULL;
int saved_errno = 0;
if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
&timestamp, &stripped)) {
if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
smb_fname->base_name,
&timestamp, &stripped)) {
goto done;
}
if (timestamp == 0) {
return SMB_VFS_NEXT_REALPATH(handle, fname);
return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
}
tmp = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
if (tmp == NULL) {
conv_fname = cp_smb_filename(talloc_tos(), smb_fname);
if (conv_fname == NULL) {
goto done;
}
conv_fname->base_name = shadow_copy2_convert(
conv_fname, handle, stripped, timestamp);
if (conv_fname->base_name == NULL) {
goto done;
}
result = SMB_VFS_NEXT_REALPATH(handle, tmp);
result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, conv_fname);
done:
if (result == NULL) {
if (result_fname == NULL) {
saved_errno = errno;
}
TALLOC_FREE(tmp);
TALLOC_FREE(conv_fname);
TALLOC_FREE(stripped);
if (saved_errno != 0) {
errno = saved_errno;
}
return result;
return result_fname;
}
/**
@ -2698,6 +2705,8 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
time_t timestamp = 0;
char *stripped = NULL;
char *tmp = NULL;
struct smb_filename smb_fname = {0};
struct smb_filename *result_fname = NULL;
char *result = NULL;
char *parent_dir = NULL;
int saved_errno = 0;
@ -2760,17 +2769,20 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
(int)rootpath_len, tmp);
tmp[rootpath_len] = '\0';
result = SMB_VFS_NEXT_REALPATH(handle, tmp);
if (result == NULL) {
smb_fname = (struct smb_filename) { .base_name = tmp };
result_fname = SMB_VFS_NEXT_REALPATH(handle, priv, &smb_fname);
if (result_fname == NULL) {
goto done;
}
/*
* SMB_VFS_NEXT_REALPATH returns a malloc'ed string.
* SMB_VFS_NEXT_REALPATH returns a talloc'ed string.
* Don't leak memory.
*/
SAFE_FREE(priv->shadow_realpath);
priv->shadow_realpath = result;
TALLOC_FREE(priv->shadow_realpath);
priv->shadow_realpath = result_fname;
result = priv->shadow_realpath->base_name;
DBG_DEBUG("connect path is [%s]\n", result);
@ -2890,12 +2902,6 @@ static int shadow_copy2_get_quota(vfs_handle_struct *handle,
return ret;
}
static int shadow_copy2_private_destructor(struct shadow_copy2_private *priv)
{
SAFE_FREE(priv->shadow_realpath);
return 0;
}
static int shadow_copy2_connect(struct vfs_handle_struct *handle,
const char *service, const char *user)
{
@ -2927,8 +2933,6 @@ static int shadow_copy2_connect(struct vfs_handle_struct *handle,
return -1;
}
talloc_set_destructor(priv, shadow_copy2_private_destructor);
priv->snaps = talloc_zero(priv, struct shadow_copy2_snaplist_info);
if (priv->snaps == NULL) {
DBG_ERR("talloc_zero() failed\n");

View File

@ -2507,39 +2507,47 @@ static int snapper_gmt_mknod(vfs_handle_struct *handle,
return ret;
}
static char *snapper_gmt_realpath(vfs_handle_struct *handle,
const char *fname)
static struct smb_filename *snapper_gmt_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
time_t timestamp;
time_t timestamp = 0;
char *stripped = NULL;
char *tmp = NULL;
char *result = NULL;
int saved_errno;
struct smb_filename *result_fname = NULL;
struct smb_filename *conv_smb_fname = NULL;
int saved_errno = 0;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname,
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
smb_fname->base_name,
&timestamp, &stripped)) {
goto done;
}
if (timestamp == 0) {
return SMB_VFS_NEXT_REALPATH(handle, fname);
return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
}
tmp = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
if (tmp == NULL) {
conv_smb_fname = cp_smb_filename(talloc_tos(), smb_fname);
if (conv_smb_fname == NULL) {
goto done;
}
conv_smb_fname->base_name = snapper_gmt_convert(conv_smb_fname, handle,
stripped, timestamp);
if (conv_smb_fname->base_name == NULL) {
goto done;
}
result = SMB_VFS_NEXT_REALPATH(handle, tmp);
if (result == NULL) {
goto done;
}
result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, conv_smb_fname);
done:
saved_errno = errno;
TALLOC_FREE(tmp);
if (result_fname == NULL) {
saved_errno = errno;
}
TALLOC_FREE(conv_smb_fname);
TALLOC_FREE(stripped);
errno = saved_errno;
return result;
if (saved_errno != 0) {
errno = saved_errno;
}
return result_fname;
}
static NTSTATUS snapper_gmt_fget_nt_acl(vfs_handle_struct *handle,

View File

@ -1513,23 +1513,25 @@ static int smb_time_audit_mknod(vfs_handle_struct *handle,
return result;
}
static char *smb_time_audit_realpath(vfs_handle_struct *handle,
const char *path)
static struct smb_filename *smb_time_audit_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
char *result;
struct smb_filename *result_fname;
struct timespec ts1,ts2;
double timediff;
clock_gettime_mono(&ts1);
result = SMB_VFS_NEXT_REALPATH(handle, path);
result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
clock_gettime_mono(&ts2);
timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
if (timediff > audit_timeout) {
smb_time_audit_log_fname("realpath", timediff, path);
smb_time_audit_log_fname("realpath", timediff,
smb_fname->base_name);
}
return result;
return result_fname;
}
static int smb_time_audit_chflags(vfs_handle_struct *handle,

View File

@ -1444,30 +1444,31 @@ err:
return status;
}
static char *um_realpath(vfs_handle_struct *handle,
const char *path)
static struct smb_filename *um_realpath(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
char *buf = NULL;
char *client_path = NULL;
struct smb_filename *client_fname = NULL;
struct smb_filename *result_fname = NULL;
int status;
DEBUG(10, ("Entering um_realpath\n"));
if (!is_in_media_files(path)) {
return SMB_VFS_NEXT_REALPATH(handle, path);
if (!is_in_media_files(smb_fname->base_name)) {
return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
}
status = alloc_get_client_path(handle, talloc_tos(),
path, &client_path);
status = alloc_get_client_smb_fname(handle, talloc_tos(),
smb_fname, &client_fname);
if (status != 0) {
goto err;
}
buf = SMB_VFS_NEXT_REALPATH(handle, client_path);
result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, client_fname);
err:
TALLOC_FREE(client_path);
return buf;
TALLOC_FREE(client_fname);
return result_fname;
}
static int um_chflags(vfs_handle_struct *handle,

View File

@ -410,9 +410,11 @@ static int process_symlink_open(struct connection_struct *conn,
{
int fd = -1;
char *link_target = NULL;
struct smb_filename target_fname = {0};
int link_len = -1;
struct smb_filename *oldwd_fname = NULL;
size_t rootdir_len = 0;
struct smb_filename *resolved_fname = NULL;
char *resolved_name = NULL;
bool matched = false;
int saved_errno = 0;
@ -444,12 +446,14 @@ static int process_symlink_open(struct connection_struct *conn,
/* Ensure it's at least null terminated. */
link_target[link_len] = '\0';
target_fname = (struct smb_filename){ .base_name = link_target };
/* Convert to an absolute path. */
resolved_name = SMB_VFS_REALPATH(conn, link_target);
if (resolved_name == NULL) {
resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(), &target_fname);
if (resolved_fname == NULL) {
goto out;
}
resolved_name = resolved_fname->base_name;
/*
* We know conn_rootdir starts with '/' and
@ -471,18 +475,22 @@ static int process_symlink_open(struct connection_struct *conn,
*/
if (resolved_name[rootdir_len] == '\0') {
/* Link to the root of the share. */
smb_fname->base_name = talloc_strdup(talloc_tos(), ".");
if (smb_fname->base_name == NULL) {
errno = ENOMEM;
goto out;
}
TALLOC_FREE(smb_fname->base_name);
smb_fname->base_name = talloc_strdup(smb_fname, ".");
} else if (resolved_name[rootdir_len] == '/') {
smb_fname->base_name = &resolved_name[rootdir_len+1];
TALLOC_FREE(smb_fname->base_name);
smb_fname->base_name = talloc_strdup(smb_fname,
&resolved_name[rootdir_len+1]);
} else {
errno = EACCES;
goto out;
}
if (smb_fname->base_name == NULL) {
errno = ENOMEM;
goto out;
}
oldwd_fname = vfs_GetWd(talloc_tos(), conn);
if (oldwd_fname == NULL) {
goto out;
@ -507,7 +515,7 @@ static int process_symlink_open(struct connection_struct *conn,
out:
SAFE_FREE(resolved_name);
TALLOC_FREE(resolved_fname);
TALLOC_FREE(link_target);
if (oldwd_fname != NULL) {
int ret = vfs_ChDir(conn, oldwd_fname);

View File

@ -36,12 +36,14 @@
static bool canonicalize_connect_path(connection_struct *conn)
{
bool ret;
char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath);
if (!resolved_name) {
struct smb_filename con_fname = { .base_name = conn->connectpath };
struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
&con_fname);
if (resolved_fname == NULL) {
return false;
}
ret = set_conn_connectpath(conn,resolved_name);
SAFE_FREE(resolved_name);
ret = set_conn_connectpath(conn,resolved_fname->base_name);
TALLOC_FREE(resolved_fname);
return ret;
}

View File

@ -1024,8 +1024,9 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
const char *conn_rootdir;
size_t rootdir_len;
char *dir_name = NULL;
const char *last_component = NULL;
char *resolved_name = NULL;
const char *last_component = NULL;
struct smb_filename *resolved_fname = NULL;
struct smb_filename *saved_dir_fname = NULL;
struct smb_filename *smb_fname_cwd = NULL;
struct privilege_paths *priv_paths = NULL;
@ -1072,12 +1073,19 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
goto err;
}
smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
if (smb_fname_cwd == NULL) {
status = NT_STATUS_NO_MEMORY;
goto err;
}
/* Get the absolute path of the parent directory. */
resolved_name = SMB_VFS_REALPATH(conn,".");
if (!resolved_name) {
resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
if (resolved_fname == NULL) {
status = map_nt_error_from_unix(errno);
goto err;
}
resolved_name = resolved_fname->base_name;
if (*resolved_name != '/') {
DEBUG(0,("check_reduced_name_with_privilege: realpath "
@ -1091,12 +1099,6 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
resolved_name));
/* Now check the stat value is the same. */
smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
if (smb_fname_cwd == NULL) {
status = NT_STATUS_NO_MEMORY;
goto err;
}
if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
status = map_nt_error_from_unix(errno);
goto err;
@ -1186,7 +1188,7 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
vfs_ChDir(conn, saved_dir_fname);
TALLOC_FREE(saved_dir_fname);
}
SAFE_FREE(resolved_name);
TALLOC_FREE(resolved_fname);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(priv_paths);
}
@ -1209,6 +1211,9 @@ NTSTATUS check_reduced_name(connection_struct *conn,
const char *cwd_name,
const char *fname)
{
TALLOC_CTX *ctx = talloc_tos();
struct smb_filename smb_fname = { .base_name = discard_const(fname) };
struct smb_filename *resolved_fname;
char *resolved_name = NULL;
char *new_fname = NULL;
bool allow_symlinks = true;
@ -1216,9 +1221,9 @@ NTSTATUS check_reduced_name(connection_struct *conn,
DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
resolved_name = SMB_VFS_REALPATH(conn,fname);
resolved_fname = SMB_VFS_REALPATH(conn, ctx, &smb_fname);
if (!resolved_name) {
if (resolved_fname == NULL) {
switch (errno) {
case ENOTDIR:
DEBUG(3,("check_reduced_name: Component not a "
@ -1227,11 +1232,9 @@ NTSTATUS check_reduced_name(connection_struct *conn,
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
case ENOENT:
{
TALLOC_CTX *ctx = talloc_tos();
char *dir_name = NULL;
struct smb_filename dir_fname = {0};
const char *last_component = NULL;
char *new_name = NULL;
int ret;
/* Last component didn't exist.
Remove it and try and canonicalise
@ -1242,8 +1245,12 @@ NTSTATUS check_reduced_name(connection_struct *conn,
return NT_STATUS_NO_MEMORY;
}
resolved_name = SMB_VFS_REALPATH(conn,dir_name);
if (!resolved_name) {
dir_fname = (struct smb_filename)
{ .base_name = dir_name };
resolved_fname = SMB_VFS_REALPATH(conn,
ctx,
&dir_fname);
if (resolved_fname == NULL) {
NTSTATUS status = map_nt_error_from_unix(errno);
if (errno == ENOENT || errno == ENOTDIR) {
@ -1257,13 +1264,13 @@ NTSTATUS check_reduced_name(connection_struct *conn,
nt_errstr(status)));
return status;
}
ret = asprintf(&new_name, "%s/%s",
resolved_name, last_component);
SAFE_FREE(resolved_name);
if (ret == -1) {
resolved_name = talloc_asprintf(ctx,
"%s/%s",
resolved_fname->base_name,
last_component);
if (resolved_name == NULL) {
return NT_STATUS_NO_MEMORY;
}
resolved_name = new_name;
break;
}
default:
@ -1271,6 +1278,8 @@ NTSTATUS check_reduced_name(connection_struct *conn,
"realpath for %s\n", fname));
return map_nt_error_from_unix(errno);
}
} else {
resolved_name = resolved_fname->base_name;
}
DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
@ -1279,7 +1288,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
if (*resolved_name != '/') {
DEBUG(0,("check_reduced_name: realpath doesn't return "
"absolute paths !\n"));
SAFE_FREE(resolved_name);
TALLOC_FREE(resolved_fname);
return NT_STATUS_OBJECT_NAME_INVALID;
}
@ -1295,7 +1304,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
if (conn_rootdir == NULL) {
DEBUG(2, ("check_reduced_name: Could not get "
"conn_rootdir\n"));
SAFE_FREE(resolved_name);
TALLOC_FREE(resolved_fname);
return NT_STATUS_ACCESS_DENIED;
}
@ -1324,7 +1333,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
conn_rootdir));
DEBUGADD(2, ("resolved_name=%s\n",
resolved_name));
SAFE_FREE(resolved_name);
TALLOC_FREE(resolved_fname);
return NT_STATUS_ACCESS_DENIED;
}
}
@ -1347,7 +1356,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
"in resolved_name: %s\n",
*p,
fname));
SAFE_FREE(resolved_name);
TALLOC_FREE(resolved_fname);
return NT_STATUS_ACCESS_DENIED;
}
@ -1361,12 +1370,12 @@ NTSTATUS check_reduced_name(connection_struct *conn,
* sent (cwd_name+fname).
*/
if (cwd_name != NULL && !ISDOT(cwd_name)) {
new_fname = talloc_asprintf(talloc_tos(),
new_fname = talloc_asprintf(ctx,
"%s/%s",
cwd_name,
fname);
if (new_fname == NULL) {
SAFE_FREE(resolved_name);
TALLOC_FREE(resolved_fname);
return NT_STATUS_NO_MEMORY;
}
fname = new_fname;
@ -1376,7 +1385,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
DEBUG(2, ("check_reduced_name: Bad access "
"attempt: %s is a symlink to %s\n",
fname, p));
SAFE_FREE(resolved_name);
TALLOC_FREE(resolved_fname);
TALLOC_FREE(new_fname);
return NT_STATUS_ACCESS_DENIED;
}
@ -1386,7 +1395,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
out:
DBG_INFO("%s reduced to %s\n", fname, resolved_name);
SAFE_FREE(resolved_name);
TALLOC_FREE(resolved_fname);
TALLOC_FREE(new_fname);
return NT_STATUS_OK;
}
@ -2212,10 +2221,12 @@ int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
}
char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path)
struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const struct smb_filename *smb_fname)
{
VFS_FIND(realpath);
return handle->fns->realpath_fn(handle, path);
return handle->fns->realpath_fn(handle, ctx, smb_fname);
}
int smb_vfs_call_chflags(struct vfs_handle_struct *handle,

View File

@ -1340,12 +1340,20 @@ static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc,
static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
struct smb_filename *smb_fname = NULL;
if (argc != 2) {
printf("Usage: realpath <path>\n");
return NT_STATUS_OK;
}
if (SMB_VFS_REALPATH(vfs->conn, argv[1]) == NULL) {
smb_fname = synthetic_smb_fname_split(mem_ctx,
argv[1],
lp_posix_pathnames());
if (smb_fname == NULL) {
return NT_STATUS_NO_MEMORY;
}
if (SMB_VFS_REALPATH(vfs->conn, mem_ctx, smb_fname) == NULL) {
printf("realpath: error=%d (%s)\n", errno, strerror(errno));
return NT_STATUS_UNSUCCESSFUL;
}