char **psnappath,
bool *_already_converted)
{
- const char *orig_name = smb_fname->base_name;
- struct tm tm;
- time_t timestamp = 0;
- const char *p;
- char *q;
char *stripped = NULL;
- size_t rest_len, dst_len;
struct shadow_copy2_private *priv;
- ptrdiff_t len_before_gmt;
- const char *name = orig_name;
char *abs_path = NULL;
bool ret = true;
bool already_converted = false;
SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
return false);
- DEBUG(10, (__location__ ": enter path '%s'\n", name));
+ DBG_DEBUG("Enter path '%s'\n", smb_fname_str_dbg(smb_fname));
if (_already_converted != NULL) {
*_already_converted = false;
}
- abs_path = make_path_absolute(mem_ctx, priv, name);
+ abs_path = make_path_absolute(mem_ctx, priv, smb_fname->base_name);
if (abs_path == NULL) {
ret = false;
goto out;
}
- name = abs_path;
- DEBUG(10, (__location__ ": abs path '%s'\n", name));
+ DBG_DEBUG("abs path '%s'\n", abs_path);
err = check_for_converted_path(mem_ctx,
handle,
*ptimestamp = nt_time_to_unix(smb_fname->twrp);
}
- /*
- * From here we're only looking to strip an
- * SMB-layer @GMT- token.
- */
-
- p = strstr_m(name, "@GMT-");
- if (p == NULL) {
- DEBUG(11, ("@GMT not found\n"));
- goto out;
- }
- if ((p > name) && (p[-1] != '/')) {
- /* the GMT-token does not start a path-component */
- DEBUG(10, ("not at start, p=%p, name=%p, p[-1]=%d\n",
- p, name, (int)p[-1]));
- goto out;
- }
-
- len_before_gmt = p - name;
-
- q = strptime(p, GMT_FORMAT, &tm);
- if (q == NULL) {
- DEBUG(10, ("strptime failed\n"));
- goto out;
- }
- tm.tm_isdst = -1;
- timestamp = timegm(&tm);
- if (timestamp == (time_t)-1) {
- DEBUG(10, ("timestamp==-1\n"));
- goto out;
- }
- if (q[0] == '\0') {
- /*
- * The name consists of only the GMT token or the GMT
- * token is at the end of the path. XP seems to send
- * @GMT- at the end under certain circumstances even
- * with a path prefix.
- */
- if (pstripped != NULL) {
- if (len_before_gmt > 1) {
- /*
- * There is a path (and not only a slash)
- * before the @GMT-. Remove the trailing
- * slash character.
- */
- len_before_gmt -= 1;
- }
- stripped = talloc_strndup(mem_ctx, name,
- len_before_gmt);
- if (stripped == NULL) {
- ret = false;
- goto out;
- }
- if (orig_name[0] != '/') {
- if (make_relative_path(priv->shadow_cwd,
- stripped) == false) {
- DEBUG(10, (__location__ ": path '%s' "
- "doesn't start with cwd '%s'\n",
- stripped, priv->shadow_cwd));
- ret = false;
- errno = ENOENT;
- goto out;
- }
- }
- *pstripped = stripped;
- }
- *ptimestamp = timestamp;
- goto out;
- }
- if (q[0] != '/') {
- /*
- * It is not a complete path component, i.e. the path
- * component continues after the gmt-token.
- */
- DEBUG(10, ("q[0] = %d\n", (int)q[0]));
- goto out;
- }
- q += 1;
-
- rest_len = strlen(q);
- dst_len = len_before_gmt + rest_len;
-
if (pstripped != NULL) {
- stripped = talloc_array(mem_ctx, char, dst_len+1);
+ stripped = talloc_strdup(mem_ctx, abs_path);
if (stripped == NULL) {
ret = false;
goto out;
}
- if (p > name) {
- memcpy(stripped, name, len_before_gmt);
- }
- if (rest_len > 0) {
- memcpy(stripped + len_before_gmt, q, rest_len);
- }
- stripped[dst_len] = '\0';
- if (orig_name[0] != '/') {
- if (make_relative_path(priv->shadow_cwd,
- stripped) == false) {
- DEBUG(10, (__location__ ": path '%s' "
+
+ if (smb_fname->base_name[0] != '/') {
+ ret = make_relative_path(priv->shadow_cwd, stripped);
+ if (!ret) {
+ DBG_DEBUG("Path '%s' "
"doesn't start with cwd '%s'\n",
- stripped, priv->shadow_cwd));
+ stripped, priv->shadow_cwd);
ret = false;
errno = ENOENT;
goto out;
{
char *startp = strchr_m(smb_fname->base_name, '@');
char *endp = NULL;
+ char *tmp = NULL;
struct tm tm;
time_t t;
+ NTTIME nt;
NTSTATUS status;
if (twrp != 0) {
- struct tm *ptm = NULL;
- char *twrp_name = NULL;
-
- t = nt_time_to_unix(twrp);
- ptm = gmtime_r(&t, &tm);
-
- twrp_name = talloc_asprintf(
- smb_fname,
- "@GMT-%04u.%02u.%02u-%02u.%02u.%02u/%s",
- ptm->tm_year + 1900,
- ptm->tm_mon + 1,
- ptm->tm_mday,
- ptm->tm_hour,
- ptm->tm_min,
- ptm->tm_sec,
- smb_fname->base_name);
- if (twrp_name == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- TALLOC_FREE(smb_fname->base_name);
- smb_fname->base_name = twrp_name;
-
smb_fname->twrp = twrp;
- return NT_STATUS_OK;
}
if (startp == NULL) {
return status;
}
- tm.tm_isdst = -1;
- t = timegm(&tm);
- unix_to_nt_time(&smb_fname->twrp, t);
+ startp = smb_fname->base_name + GMT_NAME_LEN;
+ if (startp[0] == '/') {
+ startp++;
+ }
+
+ tmp = talloc_strdup(smb_fname, startp);
+ if (tmp == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ TALLOC_FREE(smb_fname->base_name);
+ smb_fname->base_name = tmp;
+
+ if (smb_fname->twrp == 0) {
+ tm.tm_isdst = -1;
+ t = timegm(&tm);
+ unix_to_nt_time(&nt, t);
+ smb_fname->twrp = nt;
+ }
return NT_STATUS_OK;
}
if(!state->component_was_mangled && !state->name_has_wildcard) {
stat_cache_add(state->orig_path,
state->dirpath,
+ state->smb_fname->twrp,
state->conn->case_sensitive);
}
&state->smb_fname->base_name,
&state->dirpath,
&state->name,
+ state->smb_fname->twrp,
&state->smb_fname->st);
if (found) {
goto done;
/* Add the path (not including the stream) to the cache. */
stat_cache_add(state->orig_path,
state->smb_fname->base_name,
+ state->smb_fname->twrp,
state->conn->case_sensitive);
DBG_DEBUG("Conversion of base_name finished "
"[%s] -> [%s]\n",
if(!state->component_was_mangled && !state->name_has_wildcard) {
stat_cache_add(state->orig_path,
state->smb_fname->base_name,
+ state->smb_fname->twrp,
state->conn->case_sensitive);
}
void stat_cache_add( const char *full_orig_name,
const char *translated_path,
+ NTTIME twrp,
bool case_sensitive);
bool stat_cache_lookup(connection_struct *conn,
bool posix_paths,
char **pp_name,
char **pp_dirpath,
char **pp_start,
+ NTTIME twrp,
SMB_STRUCT_STAT *pst);
void smbd_send_stat_cache_delete_message(struct messaging_context *msg_ctx,
const char *name);
#include "smbprofile.h"
#include <tdb.h>
+#define STAT_CACHE_TWRP_TOKEN "%016" PRIx64 "@%s"
+#define STAT_CACHE_TWRP_TOKEN_LEN 17
+
/****************************************************************************
Stat cache code used in unix_convert.
*****************************************************************************/
void stat_cache_add( const char *full_orig_name,
const char *translated_path_in,
+ NTTIME twrp,
bool case_sensitive)
{
size_t translated_path_length;
return;
}
- translated_path = talloc_strdup(ctx, translated_path_in);
+ translated_path = talloc_asprintf(ctx,
+ STAT_CACHE_TWRP_TOKEN,
+ twrp,
+ translated_path_in);
if (translated_path == NULL) {
return;
}
}
if(case_sensitive) {
- original_path = talloc_strdup(ctx,full_orig_name);
+ original_path = talloc_asprintf(ctx,
+ STAT_CACHE_TWRP_TOKEN,
+ twrp,
+ full_orig_name);
} else {
- original_path = talloc_strdup_upper(ctx,full_orig_name);
+ char *upper = NULL;
+
+ upper = talloc_strdup_upper(ctx, full_orig_name);
+ if (upper == NULL) {
+ TALLOC_FREE(translated_path);
+ return;
+ }
+ original_path = talloc_asprintf(ctx,
+ STAT_CACHE_TWRP_TOKEN,
+ twrp,
+ upper);
+ TALLOC_FREE(upper);
}
if (!original_path) {
char **pp_name,
char **pp_dirpath,
char **pp_start,
+ NTTIME twrp,
SMB_STRUCT_STAT *pst)
{
char *chk_name;
}
if (conn->case_sensitive) {
- chk_name = talloc_strdup(ctx,name);
+ chk_name = talloc_asprintf(ctx,
+ STAT_CACHE_TWRP_TOKEN,
+ twrp,
+ name);
if (!chk_name) {
DEBUG(0, ("stat_cache_lookup: strdup failed!\n"));
return False;
}
} else {
- chk_name = talloc_strdup_upper(ctx,name);
+ char *upper = NULL;
+
+ upper = talloc_strdup_upper(ctx,name);
+ if (upper == NULL) {
+ DBG_ERR("talloc_strdup_upper failed!\n");
+ return False;
+ }
+ chk_name = talloc_asprintf(ctx,
+ STAT_CACHE_TWRP_TOKEN,
+ twrp,
+ upper);
if (!chk_name) {
DEBUG(0, ("stat_cache_lookup: talloc_strdup_upper failed!\n"));
return False;
}
}
- translated_path = talloc_strdup(ctx,(char *)data_val.data);
+ SMB_ASSERT(data_val.length >= STAT_CACHE_TWRP_TOKEN_LEN);
+
+ translated_path = talloc_strdup(
+ ctx,(char *)data_val.data + STAT_CACHE_TWRP_TOKEN_LEN);
if (!translated_path) {
smb_panic("talloc failed");
}
- translated_path_length = data_val.length - 1;
+ translated_path_length = data_val.length - 1 - STAT_CACHE_TWRP_TOKEN_LEN;
DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] "
"-> [%s]\n", chk_name, translated_path ));
DO_PROFILE_INC(statcache_hits);
- ZERO_STRUCT(smb_fname);
- smb_fname.base_name = translated_path;
+ smb_fname = (struct smb_filename) {
+ .base_name = translated_path,
+ .twrp = twrp,
+ };
if (posix_paths) {
ret = SMB_VFS_LSTAT(conn, &smb_fname);
void stat_cache_delete(const char *name)
{
- char *lname = talloc_strdup_upper(talloc_tos(), name);
+ char *upper = talloc_strdup_upper(talloc_tos(), name);
+ char *lname = NULL;
+
+ if (upper == NULL) {
+ return;
+ }
- if (!lname) {
+ lname = talloc_asprintf(talloc_tos(),
+ STAT_CACHE_TWRP_TOKEN,
+ (uintmax_t)0,
+ upper);
+ TALLOC_FREE(upper);
+ if (lname == NULL) {
return;
}
DEBUG(10,("stat_cache_delete: deleting name [%s] -> %s\n",