1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-02 09:47:23 +03:00

Add "split_ntfs_stream_name()" together with a torture test

(This used to be commit d813bd9e02d9baf916eb96c478be89f0c435e07c)
This commit is contained in:
Volker Lendecke 2008-01-19 23:10:09 +01:00
parent 14e7c292bc
commit 2411c6cb90
3 changed files with 162 additions and 0 deletions

View File

@ -3273,3 +3273,93 @@ void *talloc_zeronull(const void *context, size_t size, const char *name)
return talloc_named_const(context, size, name);
}
#endif
/* Split a path name into filename and stream name components. Canonicalise
* such that an implicit $DATA token is always explicit.
*
* The "specification" of this function can be found in the
* run_local_stream_name() function in torture.c, I've tried those
* combinations against a W2k3 server.
*/
NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
char **pbase, char **pstream)
{
char *base = NULL;
char *stream = NULL;
char *sname; /* stream name */
const char *stype; /* stream type */
DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
sname = strchr_m(fname, ':');
if (lp_posix_pathnames() || (sname == NULL)) {
if (pbase != NULL) {
base = talloc_strdup(mem_ctx, fname);
NT_STATUS_HAVE_NO_MEMORY(base);
}
goto done;
}
if (pbase != NULL) {
base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
NT_STATUS_HAVE_NO_MEMORY(base);
}
sname += 1;
stype = strchr_m(sname, ':');
if (stype == NULL) {
sname = talloc_strdup(mem_ctx, sname);
stype = "$DATA";
}
else {
if (StrCaseCmp(stype, ":$DATA") != 0) {
/*
* If there is an explicit stream type, so far we only
* allow $DATA. Is there anything else allowed? -- vl
*/
DEBUG(10, ("[%s] is an invalid stream type\n", stype));
TALLOC_FREE(base);
return NT_STATUS_OBJECT_NAME_INVALID;
}
sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
stype += 1;
}
if (sname == NULL) {
TALLOC_FREE(base);
return NT_STATUS_NO_MEMORY;
}
if (sname[0] == '\0') {
/*
* no stream name, so no stream
*/
goto done;
}
if (pstream != NULL) {
stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
if (stream == NULL) {
TALLOC_FREE(sname);
TALLOC_FREE(base);
return NT_STATUS_NO_MEMORY;
}
/*
* upper-case the type field
*/
strupper_m(strchr_m(stream, ':')+1);
}
done:
if (pbase != NULL) {
*pbase = base;
}
if (pstream != NULL) {
*pstream = stream;
}
return NT_STATUS_OK;
}

View File

@ -271,6 +271,9 @@ void send_nt_replies(connection_struct *conn,
/****************************************************************************
Is it an NTFS stream name ?
An NTFS file name is <path>.<extention>:<stream name>:<stream type>
$DATA can be used as both a stream name and a stream type. A missing stream
name or type implies $DATA.
****************************************************************************/
bool is_ntfs_stream_name(const char *fname)

View File

@ -5098,6 +5098,74 @@ static bool run_local_rbtree(int dummy)
return ret;
}
static bool test_stream_name(const char *fname, const char *expected_base,
const char *expected_stream,
NTSTATUS expected_status)
{
NTSTATUS status;
char *base = NULL;
char *stream = NULL;
status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
if (!NT_STATUS_EQUAL(status, expected_status)) {
goto error;
}
if (!NT_STATUS_IS_OK(status)) {
return true;
}
if (base == NULL) goto error;
if (strcmp(expected_base, base) != 0) goto error;
if ((expected_stream != NULL) && (stream == NULL)) goto error;
if ((expected_stream == NULL) && (stream != NULL)) goto error;
if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
goto error;
TALLOC_FREE(base);
TALLOC_FREE(stream);
return true;
error:
d_fprintf(stderr, "test_stream(%s, %s, %s, %s)\n",
fname, expected_base ? expected_base : "<NULL>",
expected_stream ? expected_stream : "<NULL>",
nt_errstr(expected_status));
d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
base ? base : "<NULL>", stream ? stream : "<NULL>",
nt_errstr(status));
TALLOC_FREE(base);
TALLOC_FREE(stream);
return false;
}
static bool run_local_stream_name(int dummy)
{
bool ret = true;
ret &= test_stream_name(
"bla", "bla", NULL, NT_STATUS_OK);
ret &= test_stream_name(
"bla::$DATA", "bla", NULL, NT_STATUS_OK);
ret &= test_stream_name(
"bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
ret &= test_stream_name(
"bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
ret &= test_stream_name(
"bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
ret &= test_stream_name(
"bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
ret &= test_stream_name(
"bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
ret &= test_stream_name(
"bla:x", "bla", "x:$DATA", NT_STATUS_OK);
return ret;
}
static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
{
if (a.length != b.length) {
@ -5328,6 +5396,7 @@ static struct {
{ "LOCAL-GENCACHE", run_local_gencache, 0},
{ "LOCAL-RBTREE", run_local_rbtree, 0},
{ "LOCAL-MEMCACHE", run_local_memcache, 0},
{ "LOCAL-STREAM-NAME", run_local_stream_name, 0},
{NULL, NULL, 0}};