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:
parent
bd9285b197
commit
c29438f823
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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,
|
||||
×tamp, &stripped)) {
|
||||
if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
|
||||
smb_fname->base_name,
|
||||
×tamp, &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");
|
||||
|
@ -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,
|
||||
×tamp, &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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user