*/
/*
- * This is a second implemetation of a shadow copy module for exposing
+ * This is a second implementation of a shadow copy module for exposing
* file system snapshots to windows clients as shadow copies.
*
* See the manual page for documentation.
time_t fetch_time; /* snaplist update time */
};
-
/*
* shadow_copy2 private structure. This structure will be
* used to keep module specific information
bool labels);
/**
- *This function will create a new snapshot list entry and
+ * This function will create a new snapshot list entry and
* return to the caller. This entry will also be added to
* the global snapshot list.
*
}
/**
- *This function will delete the entire snaplist and reset
+ * This function will delete the entire snaplist and reset
* priv->snaps->snaplist to NULL.
*
* @param[in] priv shadow_copye specific data structure
config->snapdir, snaptime_string);
}
if (result == NULL) {
- DEBUG(1, (__location__ " talloc_asprintf failed\n"));
+ DBG_WARNING("talloc_asprintf failed\n");
}
return result;
result = talloc_asprintf(mem_ctx, "%s/%s",
priv->config->snapshot_basepath, snaptime_string);
if (result == NULL) {
- DEBUG(1, (__location__ " talloc_asprintf failed\n"));
+ DBG_WARNING("talloc_asprintf failed\n");
}
return result;
goto fail;
}
- ZERO_STRUCT(converted_fname);
- converted_fname.base_name = converted;
+ converted_fname = (struct smb_filename) {
+ .base_name = converted,
+ };
ret = SMB_VFS_NEXT_LSTAT(handle, &converted_fname);
DEBUG(10, ("Trying[not snapdirseverywhere] %s: %d (%s)\n",
insertlen = talloc_get_size(insert)-1;
/*
- * Note: We deliberatly don't expensively initialize the
+ * Note: We deliberately don't expensively initialize the
* array with talloc_zero here: Putting zero into
* converted[pathlen+insertlen] below is sufficient, because
* in the following for loop, the insert string is inserted
memcpy(converted, path, pathlen+1);
converted[pathlen+insertlen] = '\0';
- ZERO_STRUCT(converted_fname);
- converted_fname.base_name = converted;
+ converted_fname = (struct smb_filename) {
+ .base_name = converted,
+ };
for (i = num_slashes-1; i>=0; i--) {
int ret;
if (fsp->base_fsp != NULL) {
struct smb_filename *base_fname = fsp->base_fsp->fsp_name;
- SMB_ASSERT(is_named_stream(smb_fname_in));
+ if (smb_fname_in->base_name[0] == '/') {
+ /*
+ * Special-case stream names from streams_depot
+ */
+ result = cp_smb_filename(mem_ctx, smb_fname_in);
+ } else {
- result = synthetic_smb_fname(
- mem_ctx,
- base_fname->base_name,
- smb_fname_in->stream_name,
- &smb_fname_in->st,
- smb_fname_in->twrp,
- smb_fname_in->flags);
+ SMB_ASSERT(is_named_stream(smb_fname_in));
+
+ result = synthetic_smb_fname(mem_ctx,
+ base_fname->base_name,
+ smb_fname_in->stream_name,
+ &smb_fname_in->st,
+ smb_fname_in->twrp,
+ smb_fname_in->flags);
+ }
} else {
result = full_path_from_dirfsp_atname(
mem_ctx, dirfsp, smb_fname_in);
struct smb_filename *smb_fname = NULL;
time_t timestamp = 0;
char *stripped = NULL;
- bool is_converted = false;
int saved_errno = 0;
int ret;
bool ok;
return -1;
}
- ok = shadow_copy2_strip_snapshot_converted(talloc_tos(),
- handle,
- smb_fname,
- ×tamp,
- &stripped,
- &is_converted);
+ ok = shadow_copy2_strip_snapshot(talloc_tos(),
+ handle,
+ smb_fname,
+ ×tamp,
+ &stripped);
if (!ok) {
+ TALLOC_FREE(smb_fname);
return -1;
}
if (timestamp == 0) {
- if (is_converted) {
- /*
- * Just pave over the user requested mode and use
- * O_RDONLY. Later attempts by the client to write on
- * the handle will fail in the pwrite() syscall with
- * EINVAL which we carefully map to EROFS. In sum, this
- * matches Windows behaviour.
- */
- how.flags &= ~(O_WRONLY | O_RDWR | O_CREAT);
- }
+ TALLOC_FREE(stripped);
+ TALLOC_FREE(smb_fname);
return SMB_VFS_NEXT_OPENAT(handle,
dirfsp,
smb_fname_in,
}
TALLOC_FREE(stripped);
- /*
- * Just pave over the user requested mode and use O_RDONLY. Later
- * attempts by the client to write on the handle will fail in the
- * pwrite() syscall with EINVAL which we carefully map to EROFS. In sum,
- * this matches Windows behaviour.
- */
- how.flags &= ~(O_WRONLY | O_RDWR | O_CREAT);
-
ret = SMB_VFS_NEXT_OPENAT(handle,
dirfsp,
smb_fname,
* otherwise return NULL.
*/
static char *have_snapdir(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
const char *path)
{
struct smb_filename smb_fname;
SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
return NULL);
- ZERO_STRUCT(smb_fname);
- smb_fname.base_name = talloc_asprintf(talloc_tos(), "%s/%s",
- path, priv->config->snapdir);
+ smb_fname = (struct smb_filename) {
+ .base_name = talloc_asprintf(
+ mem_ctx, "%s/%s", path, priv->config->snapdir),
+ };
if (smb_fname.base_name == NULL) {
return NULL;
}
config = priv->config;
/*
- * If the non-snapdisrseverywhere mode, we should not search!
+ * If the non-snapdirseverywhere mode, we should not search!
*/
if (!config->snapdirseverywhere) {
return config->snapshot_basepath;
return NULL;
}
- snapdir = have_snapdir(handle, path);
+ snapdir = have_snapdir(handle, talloc_tos(), path);
if (snapdir != NULL) {
TALLOC_FREE(path);
return snapdir;
p[0] = '\0';
- snapdir = have_snapdir(handle, path);
+ snapdir = have_snapdir(handle, talloc_tos(), path);
if (snapdir != NULL) {
TALLOC_FREE(path);
return snapdir;
const char *name,
char *gmt, size_t gmt_len)
{
- struct tm timestamp;
+ struct tm timestamp = { .tm_sec = 0, };
time_t timestamp_t;
unsigned long int timestamp_long;
const char *fmt;
}
}
- ZERO_STRUCT(timestamp);
if (config->use_sscanf) {
if (sscanf(name, fmt, ×tamp_long) != 1) {
DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
}
DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n",
fmt, name));
-
+
if (config->use_localtime) {
timestamp.tm_isdst = -1;
timestamp_t = mktime(×tamp);
time(&(priv->snaps->fetch_time));
}
- while ((d = SMB_VFS_NEXT_READDIR(handle, dirfsp, p, NULL))) {
+ while ((d = SMB_VFS_NEXT_READDIR(handle, dirfsp, p))) {
char snapshot[GMT_NAME_LEN+1];
SHADOW_COPY_LABEL *tlabels;
full_fname,
×tamp,
NULL)) {
+ TALLOC_FREE(full_fname);
return -1;
}
TALLOC_FREE(full_fname);
return status;
}
-static NTSTATUS shadow_copy2_get_real_filename_at(
- struct vfs_handle_struct *handle,
- struct files_struct *dirfsp,
- const char *name,
- TALLOC_CTX *mem_ctx,
- char **found_name)
-{
- struct shadow_copy2_private *priv = NULL;
- time_t timestamp = 0;
- char *stripped = NULL;
- char *conv;
- struct smb_filename *conv_fname = NULL;
- NTSTATUS status;
- bool ok;
-
- SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
- return NT_STATUS_INTERNAL_ERROR);
-
- DBG_DEBUG("Path=[%s] name=[%s]\n", fsp_str_dbg(dirfsp), name);
-
- ok = shadow_copy2_strip_snapshot(
- talloc_tos(), handle, dirfsp->fsp_name, ×tamp, &stripped);
- if (!ok) {
- status = map_nt_error_from_unix(errno);
- DEBUG(10, ("shadow_copy2_strip_snapshot failed\n"));
- return status;
- }
- if (timestamp == 0) {
- DEBUG(10, ("timestamp == 0\n"));
- return SMB_VFS_NEXT_GET_REAL_FILENAME_AT(
- handle, dirfsp, name, mem_ctx, found_name);
- }
-
- /*
- * Note that stripped may be an empty string "" if path was ".". As
- * shadow_copy2_convert() combines "" with the shadow-copy tree connect
- * root fullpath and get_real_filename_full_scan() has an explicit check
- * for "" this works.
- */
- DBG_DEBUG("stripped [%s]\n", stripped);
-
- conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
- if (conv == NULL) {
- status = map_nt_error_from_unix(errno);
- DBG_DEBUG("shadow_copy2_convert [%s] failed: %s\n",
- stripped,
- strerror(errno));
- return status;
- }
-
- status = synthetic_pathref(
- talloc_tos(),
- dirfsp->conn->cwd_fsp,
- conv,
- NULL,
- NULL,
- 0,
- 0,
- &conv_fname);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- DEBUG(10, ("Calling NEXT_GET_REAL_FILE_NAME for conv=[%s], "
- "name=[%s]\n", conv, name));
- status = SMB_VFS_NEXT_GET_REAL_FILENAME_AT(
- handle, conv_fname->fsp, name, mem_ctx, found_name);
- DEBUG(10, ("NEXT_REAL_FILE_NAME returned %s\n", nt_errstr(status)));
- if (NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(conv_fname);
- return NT_STATUS_OK;
- }
- if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
- TALLOC_FREE(conv_fname);
- TALLOC_FREE(conv);
- return NT_STATUS_NOT_SUPPORTED;
- }
-
- status = get_real_filename_full_scan_at(
- conv_fname->fsp, name, false, mem_ctx, found_name);
- TALLOC_FREE(conv_fname);
- if (!NT_STATUS_IS_OK(status)) {
- DBG_DEBUG("Scan [%s] for [%s] failed\n",
- conv, name);
- return status;
- }
-
- DBG_DEBUG("Scan [%s] for [%s] returned [%s]\n",
- conv, name, *found_name);
-
- TALLOC_FREE(conv);
- return NT_STATUS_OK;
-}
-
static const char *shadow_copy2_connectpath(
struct vfs_handle_struct *handle,
const struct files_struct *dirfsp,
char *stripped = NULL;
char *tmp = NULL;
const char *fname = smb_fname_in->base_name;
+ const struct smb_filename *full = NULL;
struct smb_filename smb_fname = {0};
struct smb_filename *result_fname = NULL;
char *result = NULL;
return priv->shadow_connectpath;
}
- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, smb_fname_in,
+ full = full_path_from_dirfsp_atname(
+ talloc_tos(), dirfsp, smb_fname_in);
+ if (full == NULL) {
+ return NULL;
+ }
+
+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, full,
×tamp, &stripped)) {
goto done;
}
const char *snapsharepath = NULL;
const char *mount_point;
- DEBUG(10, (__location__ ": cnum[%u], connectpath[%s]\n",
- (unsigned)handle->conn->cnum,
- handle->conn->connectpath));
+ DBG_DEBUG("cnum[%" PRIu32 "], connectpath[%s]\n",
+ handle->conn->cnum,
+ handle->conn->connectpath);
ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
if (ret < 0) {
"shadow", "mountpoint", NULL);
if (mount_point != NULL) {
if (mount_point[0] != '/') {
- DEBUG(1, (__location__ " Warning: 'mountpoint' is "
- "relative ('%s'), but it has to be an "
- "absolute path. Ignoring provided value.\n",
- mount_point));
+ DBG_WARNING("Warning: 'mountpoint' is relative "
+ "('%s'), but it has to be an absolute "
+ "path. Ignoring provided value.\n",
+ mount_point);
mount_point = NULL;
} else {
char *p;
if (mount_point != NULL) {
config->mount_point = talloc_strdup(config, mount_point);
if (config->mount_point == NULL) {
- DEBUG(0, (__location__ " talloc_strdup() failed\n"));
+ DBG_ERR("talloc_strdup() failed\n");
return -1;
}
} else {
if (basedir != NULL) {
if (basedir[0] != '/') {
- DEBUG(1, (__location__ " Warning: 'basedir' is "
- "relative ('%s'), but it has to be an "
- "absolute path. Disabling basedir.\n",
- basedir));
+ DBG_WARNING("Warning: 'basedir' is "
+ "relative ('%s'), but it has to be an "
+ "absolute path. Disabling basedir.\n",
+ basedir);
basedir = NULL;
} else {
char *p;
}
if (config->snapdirseverywhere && basedir != NULL) {
- DEBUG(1, (__location__ " Warning: 'basedir' is incompatible "
- "with 'snapdirseverywhere'. Disabling basedir.\n"));
+ DBG_WARNING("Warning: 'basedir' is incompatible "
+ "with 'snapdirseverywhere'. Disabling basedir.\n");
basedir = NULL;
}
if (config->snapdir[0] == '/') {
config->snapdir_absolute = true;
- if (config->snapdirseverywhere == true) {
- DEBUG(1, (__location__ " Warning: An absolute snapdir "
- "is incompatible with 'snapdirseverywhere', "
- "setting 'snapdirseverywhere' to false.\n"));
+ if (config->snapdirseverywhere) {
+ DBG_WARNING("Warning: An absolute snapdir is "
+ "incompatible with 'snapdirseverywhere', "
+ "setting 'snapdirseverywhere' to "
+ "false.\n");
config->snapdirseverywhere = false;
}
- if (config->crossmountpoints == true) {
- DEBUG(1, (__location__ " Warning: 'crossmountpoints' "
- "is not supported with an absolute snapdir. "
- "Disabling it.\n"));
+ if (config->crossmountpoints) {
+ DBG_WARNING("Warning: 'crossmountpoints' is not "
+ "supported with an absolute snapdir. "
+ "Disabling it.\n");
config->crossmountpoints = false;
}
return 0;
}
-static struct dirent *shadow_copy2_readdir(vfs_handle_struct *handle,
- struct files_struct *dirfsp,
- DIR *dirp,
- SMB_STRUCT_STAT *sbuf)
-{
- struct shadow_copy2_private *priv = NULL;
- struct dirent *ent = NULL;
- struct smb_filename atname;
- struct smb_filename *full_fname = NULL;
- time_t timestamp = 0;
- char *stripped = NULL;
- char *conv = NULL;
- char *abspath = NULL;
- bool converted = false;
-
- SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
- return NULL);
-
- ent = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp, sbuf);
- if (ent == NULL) {
- return NULL;
- }
- if (sbuf == NULL) {
- return ent;
- }
- if (ISDOT(dirfsp->fsp_name->base_name) && ISDOTDOT(ent->d_name)) {
- return ent;
- }
-
- atname = (struct smb_filename) {
- .base_name = ent->d_name,
- .twrp = dirfsp->fsp_name->twrp,
- .flags = dirfsp->fsp_name->flags,
- };
-
- full_fname = full_path_from_dirfsp_atname(talloc_tos(),
- dirfsp,
- &atname);
- if (full_fname == NULL) {
- return NULL;
- }
-
- if (!shadow_copy2_strip_snapshot_converted(talloc_tos(),
- handle,
- full_fname,
- ×tamp,
- &stripped,
- &converted)) {
- TALLOC_FREE(full_fname);
- return NULL;
- }
-
- if (timestamp == 0 && !converted) {
- /* Not a snapshot path, no need for convert_sbuf() */
- TALLOC_FREE(stripped);
- TALLOC_FREE(full_fname);
- return ent;
- }
-
- if (timestamp == 0) {
- abspath = make_path_absolute(talloc_tos(),
- priv,
- full_fname->base_name);
- TALLOC_FREE(full_fname);
- if (abspath == NULL) {
- return NULL;
- }
- } else {
- conv = shadow_copy2_convert(talloc_tos(),
- handle,
- stripped,
- timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return NULL;
- }
-
- abspath = make_path_absolute(talloc_tos(), priv, conv);
- TALLOC_FREE(conv);
- if (abspath == NULL) {
- return NULL;
- }
- }
-
- convert_sbuf(handle, abspath, sbuf);
-
- TALLOC_FREE(abspath);
- return ent;
-}
-
static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
.connect_fn = shadow_copy2_connect,
.disk_free_fn = shadow_copy2_disk_free,
.mkdirat_fn = shadow_copy2_mkdirat,
.fsetxattr_fn = shadow_copy2_fsetxattr,
.fchflags_fn = shadow_copy2_fchflags,
- .get_real_filename_at_fn = shadow_copy2_get_real_filename_at,
.pwrite_fn = shadow_copy2_pwrite,
.pwrite_send_fn = shadow_copy2_pwrite_send,
.pwrite_recv_fn = shadow_copy2_pwrite_recv,
.connectpath_fn = shadow_copy2_connectpath,
.parent_pathname_fn = shadow_copy2_parent_pathname,
- .readdir_fn = shadow_copy2_readdir,
};
static_decl_vfs;