summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorTim Prouty <tprouty@samba.org>2009-01-02 17:35:04 -0800
committerTim Prouty <tprouty@samba.org>2009-01-11 22:13:37 -0800
commit9872dbf439e94ffd56019f789145c4b5eb3e606c (patch)
treeb5de67773f14260296b3f71f379f07879f2a8e27 /source3
parenta1e428914b9bc468d99775607781ff15169defa4 (diff)
downloadsamba-9872dbf439e94ffd56019f789145c4b5eb3e606c.tar.gz
samba-9872dbf439e94ffd56019f789145c4b5eb3e606c.tar.bz2
samba-9872dbf439e94ffd56019f789145c4b5eb3e606c.zip
s3: Differentiate between posix files with colons and actual streams
It is possible for a posix file created locally or over nfs to have a ":" in the name. Since ":" is a reserved character in windows, filenames containing a colon must be mangled in a directory listing. Right now files containing colons will not even be displayed in directory listings if streams modules are in use. During the directory listing the file will be detected as a stream because of the colon, but the streams module will fail to find the stream since it doesn't exist. This fix adds a step to is_ntfs_stream_name that stats the filename to differentiate between actual streams and files containing colons. While this is an improvement, it isn't perfect. Consider the case where there is a file on disk called "a.txt:s1" and also a file called "a.txt" that has a stream called "s1". This patch will always preference "a.txt:s1" over a.txt's s1 stream. The real issue is that at the vfs level, the vfs modules have no way to tell between a demangled name with a colon and an actual stream. A more invasive, but better, long-term fix would be to add all paths that come over the wire into a struct containing metadata about the path. This metadata could include a flag to indicate whether the path came over the wire with a colon ":" (guaranteeing that the client is requesting a stream). Passing this struct down to the lower levels, including all path-based vfs calls, would allow the above case to be handled correctly in all cases.
Diffstat (limited to 'source3')
-rw-r--r--source3/smbd/nttrans.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index f1423c028e..63b4776fbc 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -259,14 +259,46 @@ void send_nt_replies(connection_struct *conn,
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.
+
+ Both Windows stream names and POSIX files can contain the ':' character.
+ This function first checks for the existence of a colon in the last component
+ of the given name. If the name contains a colon we differentiate between a
+ stream and POSIX file by checking if the latter exists through a POSIX stat.
+
+ Function assumes we've already chdir() to the "root" directory of fname.
****************************************************************************/
bool is_ntfs_stream_name(const char *fname)
{
+ const char *lastcomp;
+ SMB_STRUCT_STAT sbuf;
+
+ /* If all pathnames are treated as POSIX we ignore streams. */
if (lp_posix_pathnames()) {
- return False;
+ return false;
}
- return (strchr_m(fname, ':') != NULL) ? True : False;
+
+ /* Find the last component of the name. */
+ if ((lastcomp = strrchr_m(fname, '/')) != NULL)
+ ++lastcomp;
+ else
+ lastcomp = fname;
+
+ /* If there is no colon in the last component, it's not a stream. */
+ if (strchr_m(lastcomp, ':') == NULL)
+ return false;
+
+ /*
+ * If file already exists on disk, it's not a stream. The stat must
+ * bypass the vfs layer so streams modules don't intefere.
+ */
+ if (sys_stat(fname, &sbuf) == 0) {
+ DEBUG(5, ("is_ntfs_stream_name: file %s contains a ':' but is "
+ "not a stream\n", fname));
+ return false;
+ }
+
+ return true;
}
/****************************************************************************