return -1;
}
-static int skel_vfs_readlink(vfs_handle_struct *handle, const char *path,
- char *buf, size_t bufsiz)
+static int skel_vfs_readlink(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
errno = ENOSYS;
return -1;
return SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
}
-static int skel_vfs_readlink(vfs_handle_struct *handle, const char *path,
- char *buf, size_t bufsiz)
+static int skel_vfs_readlink(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
- return SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
+ return SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz);
}
static int skel_link(vfs_handle_struct *handle,
to const struct smb_filename * */
/* Version 37 - Change statvfs from const char *
to const struct smb_filename * */
+/* Version 37 - Change readlink from const char *
+ to const struct smb_filename * */
#define SMB_VFS_INTERFACE_VERSION 37
int (*linux_setlease_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, int leasetype);
bool (*getlock_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid);
int (*symlink_fn)(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath);
- int (*readlink_fn)(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz);
+ int (*readlink_fn)(struct vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz);
int (*link_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *old_smb_fname,
const struct smb_filename *new_smb_fname);
int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
const char *newpath);
int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
- const char *path, char *buf, size_t bufsiz);
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz);
int smb_vfs_call_link(struct vfs_handle_struct *handle,
const struct smb_filename *old_smb_fname,
const struct smb_filename *new_smb_fname);
#define SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath) \
smb_vfs_call_symlink((handle)->next, (oldpath), (newpath))
-#define SMB_VFS_READLINK(conn, path, buf, bufsiz) \
- smb_vfs_call_readlink((conn)->vfs_handles, (path), (buf), (bufsiz))
-#define SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz) \
- smb_vfs_call_readlink((handle)->next, (path), (buf), (bufsiz))
+#define SMB_VFS_READLINK(conn, smb_fname, buf, bufsiz) \
+ smb_vfs_call_readlink((conn)->vfs_handles, (smb_fname), (buf), (bufsiz))
+#define SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz) \
+ smb_vfs_call_readlink((handle)->next, (smb_fname), (buf), (bufsiz))
#define SMB_VFS_LINK(conn, oldpath, newpath) \
smb_vfs_call_link((conn)->vfs_handles, (oldpath), (newpath))
return SMB_VFS_NEXT_SYMLINK(handle, capold, capnew);
}
-static int cap_readlink(vfs_handle_struct *handle, const char *path,
- char *buf, size_t bufsiz)
+static int cap_readlink(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
- char *cappath = capencode(talloc_tos(), path);
+ char *cappath = capencode(talloc_tos(), smb_fname->base_name);
+ struct smb_filename *cap_smb_fname = NULL;
+ int saved_errno = 0;
+ int ret;
if (!cappath) {
errno = ENOMEM;
return -1;
}
- return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz);
+ cap_smb_fname = synthetic_smb_fname(talloc_tos(),
+ cappath,
+ NULL,
+ NULL,
+ smb_fname->flags);
+ if (cap_smb_fname == NULL) {
+ TALLOC_FREE(cappath);
+ errno = ENOMEM;
+ return -1;
+ }
+ ret = SMB_VFS_NEXT_READLINK(handle, cap_smb_fname, buf, bufsiz);
+ if (ret == -1) {
+ saved_errno = errno;
+ }
+ TALLOC_FREE(cappath);
+ TALLOC_FREE(cap_smb_fname);
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
+ return ret;
}
static int cap_link(vfs_handle_struct *handle,
WRAP_RETURN(result);
}
-static int cephwrap_readlink(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
+static int cephwrap_readlink(struct vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
int result = -1;
- DBG_DEBUG("[CEPH] readlink(%p, %s, %p, %llu)\n", handle, path, buf, llu(bufsiz));
- result = ceph_readlink(handle->data, path, buf, bufsiz);
+ DBG_DEBUG("[CEPH] readlink(%p, %s, %p, %llu)\n", handle,
+ smb_fname->base_name, buf, llu(bufsiz));
+ result = ceph_readlink(handle->data, smb_fname->base_name, buf, bufsiz);
DBG_DEBUG("[CEPH] readlink(...) = %d\n", result);
WRAP_RETURN(result);
}
return result;
}
-static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
+static int vfswrap_readlink(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
int result;
START_PROFILE(syscall_readlink);
- result = readlink(path, buf, bufsiz);
+ result = readlink(smb_fname->base_name, buf, bufsiz);
END_PROFILE(syscall_readlink);
return result;
}
}
static int expand_msdfs_readlink(struct vfs_handle_struct *handle,
- const char *path, char *buf, size_t bufsiz)
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
TALLOC_CTX *ctx = talloc_tos();
int result;
return -1;
}
- result = SMB_VFS_NEXT_READLINK(handle, path, target,
+ result = SMB_VFS_NEXT_READLINK(handle, smb_fname, target,
PATH_MAX);
if (result <= 0)
}
static int smb_full_audit_readlink(vfs_handle_struct *handle,
- const char *path, char *buf, size_t bufsiz)
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
int result;
- result = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
+ result = SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz);
- do_log(SMB_VFS_OP_READLINK, (result >= 0), handle, "%s", path);
+ do_log(SMB_VFS_OP_READLINK, (result >= 0), handle, "%s",
+ smb_fname->base_name);
return result;
}
}
static int vfs_gluster_readlink(struct vfs_handle_struct *handle,
- const char *path, char *buf, size_t bufsiz)
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
- return glfs_readlink(handle->data, path, buf, bufsiz);
+ return glfs_readlink(handle->data, smb_fname->base_name, buf, bufsiz);
}
static int vfs_gluster_link(struct vfs_handle_struct *handle,
* Failure: set errno, return -1
*/
static int mh_readlink(vfs_handle_struct *handle,
- const char *path,
+ const struct smb_filename *smb_fname,
char *buf,
size_t bufsiz)
{
int status;
- char *clientPath;
- TALLOC_CTX *ctx;
+ struct smb_filename *clientFname = NULL;
DEBUG(MH_INFO_DEBUG, ("Entering mh_readlink\n"));
- if (!is_in_media_files(path))
- {
- status = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
+ if (!is_in_media_files(smb_fname->base_name)) {
+ status = SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz);
goto out;
}
- clientPath = NULL;
- ctx = talloc_tos();
-
- if ((status = alloc_get_client_path(handle, ctx,
- path,
- &clientPath)))
- {
+ if ((status = alloc_get_client_smb_fname(handle, talloc_tos(),
+ smb_fname,
+ &clientFname))) {
goto err;
}
- status = SMB_VFS_NEXT_READLINK(handle, clientPath, buf, bufsiz);
+ status = SMB_VFS_NEXT_READLINK(handle, clientFname, buf, bufsiz);
err:
- TALLOC_FREE(clientPath);
+ TALLOC_FREE(clientFname);
out:
return status;
}
}
static int shadow_copy2_readlink(vfs_handle_struct *handle,
- const char *fname, char *buf, size_t bufsiz)
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
time_t timestamp = 0;
char *stripped = NULL;
int saved_errno = 0;
int ret;
- char *conv;
+ struct smb_filename *conv = NULL;
- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
+ smb_fname->base_name,
×tamp, &stripped)) {
return -1;
}
if (timestamp == 0) {
- return SMB_VFS_NEXT_READLINK(handle, fname, buf, bufsiz);
+ return SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz);
}
- conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
+ conv = cp_smb_filename(talloc_tos(), smb_fname);
if (conv == NULL) {
+ TALLOC_FREE(stripped);
+ errno = ENOMEM;
+ return -1;
+ }
+ conv->base_name = shadow_copy2_convert(
+ conv, handle, stripped, timestamp);
+ TALLOC_FREE(stripped);
+ if (conv->base_name == NULL) {
return -1;
}
ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz);
}
static int snapper_gmt_readlink(vfs_handle_struct *handle,
- const char *fname, char *buf, size_t bufsiz)
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
- time_t timestamp;
- char *stripped;
- int ret, saved_errno;
- char *conv;
+ time_t timestamp = 0;
+ char *stripped = NULL;
+ int ret;
+ int saved_errno = 0;
+ struct smb_filename *conv = NULL;
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname,
+ if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
+ smb_fname->base_name,
×tamp, &stripped)) {
return -1;
}
if (timestamp == 0) {
- return SMB_VFS_NEXT_READLINK(handle, fname, buf, bufsiz);
+ return SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz);
}
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
+ conv = cp_smb_filename(talloc_tos(), smb_fname);
if (conv == NULL) {
+ TALLOC_FREE(stripped);
+ errno = ENOMEM;
+ return -1;
+ }
+ conv->base_name = snapper_gmt_convert(conv, handle,
+ stripped, timestamp);
+ TALLOC_FREE(stripped);
+ if (conv->base_name == NULL) {
return -1;
}
ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz);
- saved_errno = errno;
+ if (ret == -1) {
+ saved_errno = errno;
+ }
TALLOC_FREE(conv);
- errno = saved_errno;
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
return ret;
}
}
static int smb_time_audit_readlink(vfs_handle_struct *handle,
- const char *path, char *buf, size_t bufsiz)
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
int result;
struct timespec ts1,ts2;
double timediff;
clock_gettime_mono(&ts1);
- result = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
+ result = SMB_VFS_NEXT_READLINK(handle, smb_fname,
+ buf, bufsiz);
clock_gettime_mono(&ts2);
timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
if (timediff > audit_timeout) {
- smb_time_audit_log_fname("readlink", timediff, path);
+ smb_time_audit_log_fname("readlink", timediff,
+ smb_fname->base_name);
}
return result;
}
static int um_readlink(vfs_handle_struct *handle,
- const char *path,
- char *buf,
- size_t bufsiz)
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
int status;
- char *client_path = NULL;
+ struct smb_filename *client_fname = NULL;
DEBUG(10, ("Entering um_readlink\n"));
- if (!is_in_media_files(path)) {
- return SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
+ if (!is_in_media_files(smb_fname->base_name)) {
+ return SMB_VFS_NEXT_READLINK(handle, smb_fname,
+ buf, bufsiz);
}
- 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;
}
- status = SMB_VFS_NEXT_READLINK(handle, client_path, buf, bufsiz);
+ status = SMB_VFS_NEXT_READLINK(handle, client_fname, buf, bufsiz);
err:
- TALLOC_FREE(client_path);
+ TALLOC_FREE(client_fname);
return status;
}
static bool is_msdfs_link_internal(TALLOC_CTX *ctx,
connection_struct *conn,
- const char *path,
- char **pp_link_target,
- SMB_STRUCT_STAT *sbufp)
+ struct smb_filename *smb_fname,
+ char **pp_link_target)
{
int referral_len = 0;
#if defined(HAVE_BROKEN_READLINK)
#endif
size_t bufsize = 0;
char *link_target = NULL;
- struct smb_filename smb_fname;
if (pp_link_target) {
bufsize = 1024;
link_target = link_target_buf;
}
- ZERO_STRUCT(smb_fname);
- smb_fname.base_name = discard_const_p(char, path);
-
- if (SMB_VFS_LSTAT(conn, &smb_fname) != 0) {
+ if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
DEBUG(5,("is_msdfs_link_read_target: %s does not exist.\n",
- path));
+ smb_fname->base_name));
goto err;
}
- if (!S_ISLNK(smb_fname.st.st_ex_mode)) {
+ if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
DEBUG(5,("is_msdfs_link_read_target: %s is not a link.\n",
- path));
+ smb_fname->base_name));
goto err;
}
- if (sbufp != NULL) {
- *sbufp = smb_fname.st;
- }
- referral_len = SMB_VFS_READLINK(conn, path, link_target, bufsize - 1);
+ referral_len = SMB_VFS_READLINK(conn, smb_fname,
+ link_target, bufsize - 1);
if (referral_len == -1) {
DEBUG(0,("is_msdfs_link_read_target: Error reading "
"msdfs link %s: %s\n",
- path, strerror(errno)));
+ smb_fname->base_name, strerror(errno)));
goto err;
}
link_target[referral_len] = '\0';
- DEBUG(5,("is_msdfs_link_internal: %s -> %s\n",path,
+ DEBUG(5,("is_msdfs_link_internal: %s -> %s\n", smb_fname->base_name,
link_target));
if (!strnequal(link_target, "msdfs:", 6)) {
**********************************************************************/
bool is_msdfs_link(connection_struct *conn,
- const char *path,
- SMB_STRUCT_STAT *sbufp)
+ struct smb_filename *smb_fname)
{
return is_msdfs_link_internal(talloc_tos(),
conn,
- path,
- NULL,
- sbufp);
+ smb_fname,
+ NULL);
}
/*****************************************************************
/* Optimization - check if we can redirect the whole path. */
- if (is_msdfs_link_internal(ctx, conn, smb_fname->base_name,
- pp_targetpath, NULL)) {
+ if (is_msdfs_link_internal(ctx, conn, smb_fname, pp_targetpath)) {
/* XX_ALLOW_WCARD_XXX is called from search functions. */
if (ucf_flags &
(UCF_COND_ALLOW_WCARD_LCOMP|
}
if (is_msdfs_link_internal(ctx, conn,
- smb_fname->base_name, pp_targetpath,
- NULL)) {
+ smb_fname, pp_targetpath)) {
DEBUG(4, ("dfs_path_lookup: Redirecting %s because "
"parent %s is dfs link\n", dfspath,
smb_fname_str_dbg(smb_fname)));
while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced))
!= NULL) {
- if (is_msdfs_link(conn,
- dname,
- NULL)) {
+ struct smb_filename *smb_dname =
+ synthetic_smb_fname(talloc_tos(),
+ dname,
+ NULL,
+ NULL,
+ 0);
+ if (smb_dname == NULL) {
+ goto out;
+ }
+ if (is_msdfs_link(conn, smb_dname)) {
cnt++;
}
TALLOC_FREE(talloced);
+ TALLOC_FREE(smb_dname);
}
SMB_VFS_CLOSEDIR(conn,dirp);
while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced))
!= NULL) {
char *link_target = NULL;
+ struct smb_filename *smb_dname = NULL;
+
if (cnt >= jn_remain) {
DEBUG(2, ("form_junctions: ran out of MSDFS "
"junction slots"));
TALLOC_FREE(talloced);
goto out;
}
+ smb_dname = synthetic_smb_fname(talloc_tos(),
+ dname,
+ NULL,
+ NULL,
+ 0);
+ if (smb_dname == NULL) {
+ TALLOC_FREE(talloced);
+ goto out;
+ }
if (is_msdfs_link_internal(ctx,
conn,
- dname, &link_target,
- NULL)) {
+ smb_dname, &link_target)) {
if (parse_msdfs_symlink(ctx, snum,
link_target,
&jucn[cnt].referral_list,
TALLOC_FREE(link_target);
}
TALLOC_FREE(talloced);
+ TALLOC_FREE(smb_dname);
}
out:
/* Read the link target. */
link_len = SMB_VFS_READLINK(conn,
- smb_fname->base_name,
+ smb_fname,
link_target,
PATH_MAX - 1);
if (link_len == -1) {
/* The following definitions come from smbd/msdfs.c */
bool is_msdfs_link(connection_struct *conn,
- const char *path,
- SMB_STRUCT_STAT *sbufp);
+ struct smb_filename *smb_fname);
struct junction_map;
NTSTATUS get_referred_path(TALLOC_CTX *ctx,
const char *dfs_path,
****************************************************************************/
static bool check_msdfs_link(connection_struct *conn,
- const char *pathname,
- SMB_STRUCT_STAT *psbuf)
+ struct smb_filename *smb_fname)
{
int saved_errno = errno;
if(lp_host_msdfs() &&
lp_msdfs_root(SNUM(conn)) &&
- is_msdfs_link(conn, pathname, psbuf)) {
+ is_msdfs_link(conn, smb_fname)) {
DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
"as a directory\n",
- pathname));
- psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
+ smb_fname->base_name));
+ smb_fname->st.st_ex_mode =
+ (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
errno = saved_errno;
return true;
}
* directories */
ms_dfs_link = check_msdfs_link(state->conn,
- smb_fname->base_name,
- &smb_fname->st);
+ smb_fname);
if (!ms_dfs_link) {
DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
"Couldn't stat [%s] (%s)\n",
return NT_STATUS_DOS(ERRDOS, ERRbadlink);
#endif
link_len = SMB_VFS_READLINK(conn,
- smb_fname->base_name,
+ smb_fname,
buffer, PATH_MAX);
if (link_len == -1) {
return map_nt_error_from_unix(errno);
}
int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
- const char *path, char *buf, size_t bufsiz)
+ const struct smb_filename *smb_fname,
+ char *buf,
+ size_t bufsiz)
{
VFS_FIND(readlink);
- return handle->fns->readlink_fn(handle, path, buf, bufsiz);
+ return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz);
}
int smb_vfs_call_link(struct vfs_handle_struct *handle,
static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
char buffer[PATH_MAX];
+ struct smb_filename *smb_fname = NULL;
int size;
if (argc != 2) {
return NT_STATUS_OK;
}
- if ((size = SMB_VFS_READLINK(vfs->conn, argv[1], buffer, PATH_MAX)) == -1) {
+ smb_fname = synthetic_smb_fname_split(mem_ctx,
+ argv[1],
+ lp_posix_pathnames());
+ if (smb_fname == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ if ((size = SMB_VFS_READLINK(vfs->conn, smb_fname,
+ buffer, PATH_MAX)) == -1) {
printf("readlink: error=%d (%s)\n", errno, strerror(errno));
return NT_STATUS_UNSUCCESSFUL;
}