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;
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,
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
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);
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);
#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))
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,
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,
* 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] == '/')) {
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,
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,
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));
free_1k = ((*bsize) / 1024) * (*dfree);
}
- SAFE_FREE(rpath);
+ TALLOC_FREE(rpath_fname);
return free_1k;
}
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;
}
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;
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;
out:
save_errno = errno;
TALLOC_FREE(section);
- SAFE_FREE(rpath);
+ TALLOC_FREE(rpath_fname);
errno = save_errno;
return rc;
}
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,
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) {
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,
* 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;
}
/*
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(
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;
}
/**
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;
(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);
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)
{
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");
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;
}
-
- result = SMB_VFS_NEXT_REALPATH(handle, tmp);
- if (result == NULL) {
+ conv_smb_fname->base_name = snapper_gmt_convert(conv_smb_fname, handle,
+ stripped, timestamp);
+ if (conv_smb_fname->base_name == 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,
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,
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,
{
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;
/* 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
*/
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;
out:
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
TALLOC_FREE(link_target);
if (oldwd_fname != NULL) {
int ret = vfs_ChDir(conn, oldwd_fname);
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;
}
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;
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 "
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;
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);
}
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;
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 "
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
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) {
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:
"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,
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;
}
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;
}
conn_rootdir));
DEBUGADD(2, ("resolved_name=%s\n",
resolved_name));
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
return NT_STATUS_ACCESS_DENIED;
}
}
"in resolved_name: %s\n",
*p,
fname));
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
return NT_STATUS_ACCESS_DENIED;
}
* 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;
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;
}
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;
}
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,
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;
}