summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1998-08-17 07:40:06 +0000
committerAndrew Tridgell <tridge@samba.org>1998-08-17 07:40:06 +0000
commit0922615405838af7430ef39490ee578711866320 (patch)
treef04bd1071fa108bca40c2a6e8b0d39ac761e3500 /source3
parent4c5c26b1ef4be862fc2037dd5fcc120cb35bacca (diff)
downloadsamba-0922615405838af7430ef39490ee578711866320.tar.gz
samba-0922615405838af7430ef39490ee578711866320.tar.bz2
samba-0922615405838af7430ef39490ee578711866320.zip
more splitting of server.c
created dosmode.c and filename.c (This used to be commit 534a90ca44641417c21f6ed6d4b94b1de60f808d)
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in3
-rw-r--r--source3/include/proto.h21
-rw-r--r--source3/smbd/dosmode.c202
-rw-r--r--source3/smbd/fileio.c12
-rw-r--r--source3/smbd/filename.c380
-rw-r--r--source3/smbd/server.c573
6 files changed, 627 insertions, 564 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index e940afbd93..2fd50bdbcb 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -125,7 +125,8 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o smbd/fileio.o \
smbd/groupname.o smbd/ipc.o smbd/mangle.o smbd/negprot.o \
smbd/message.o smbd/nttrans.o smbd/pipes.o smbd/predict.o \
- smbd/quotas.o smbd/reply.o smbd/ssl.o smbd/trans2.o smbd/uid.o
+ smbd/quotas.o smbd/reply.o smbd/ssl.o smbd/trans2.o smbd/uid.o \
+ smbd/dosmode.o smbd/filename.o
PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/printing.o
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 667fc01a3b..f154b8f469 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1960,11 +1960,26 @@ void DirCacheAdd( char *path, char *name, char *dname, int snum );
char *DirCacheCheck( char *path, char *name, int snum );
void DirCacheFlush(int snum);
+/*The following definitions come from smbd/dosmode.c */
+
+mode_t unix_mode(connection_struct *conn,int dosmode);
+int dos_mode(connection_struct *conn,char *path,struct stat *sbuf);
+int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st);
+
/*The following definitions come from smbd/fileio.c */
int seek_file(files_struct *fsp,uint32 pos);
int read_file(files_struct *fsp,char *data,uint32 pos,int n);
int write_file(files_struct *fsp,char *data,int n);
+void sync_file(connection_struct *conn, files_struct *fsp);
+
+/*The following definitions come from smbd/filename.c */
+
+BOOL fname_equal(char *name1, char *name2);
+BOOL mangled_equal(char *name1, char *name2);
+BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path);
+BOOL check_name(char *name,connection_struct *conn);
+BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache);
/*The following definitions come from smbd/files.c */
@@ -2153,15 +2168,9 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_si
void *dflt_sig(void);
void killkids(void);
-mode_t unix_mode(connection_struct *conn,int dosmode);
-int dos_mode(connection_struct *conn,char *path,struct stat *sbuf);
-int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st);
int file_utime(connection_struct *conn, char *fname, struct utimbuf *times);
BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime);
-BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path);
-BOOL check_name(char *name,connection_struct *conn);
void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u);
-void sync_file(connection_struct *conn, files_struct *fsp);
void close_file(files_struct *fsp, BOOL normal_close);
void close_directory(files_struct *fsp);
int open_directory(files_struct *fsp,connection_struct *conn,
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
new file mode 100644
index 0000000000..c1af18d80b
--- /dev/null
+++ b/source3/smbd/dosmode.c
@@ -0,0 +1,202 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ dos mode handling functions
+ Copyright (C) Andrew Tridgell 1992-1998
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+/****************************************************************************
+ change a dos mode to a unix mode
+ base permission for files:
+ everybody gets read bit set
+ dos readonly is represented in unix by removing everyone's write bit
+ dos archive is represented in unix by the user's execute bit
+ dos system is represented in unix by the group's execute bit
+ dos hidden is represented in unix by the other's execute bit
+ Then apply create mask,
+ then add force bits.
+ base permission for directories:
+ dos directory is represented in unix by unix's dir bit and the exec bit
+ Then apply create mask,
+ then add force bits.
+****************************************************************************/
+mode_t unix_mode(connection_struct *conn,int dosmode)
+{
+ mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
+
+ if ( !IS_DOS_READONLY(dosmode) )
+ result |= (S_IWUSR | S_IWGRP | S_IWOTH);
+
+ if (IS_DOS_DIR(dosmode)) {
+ /* We never make directories read only for the owner as under DOS a user
+ can always create a file in a read-only directory. */
+ result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
+ /* Apply directory mask */
+ result &= lp_dir_mode(SNUM(conn));
+ /* Add in force bits */
+ result |= lp_force_dir_mode(SNUM(conn));
+ } else {
+ if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode))
+ result |= S_IXUSR;
+
+ if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
+ result |= S_IXGRP;
+
+ if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
+ result |= S_IXOTH;
+
+ /* Apply mode mask */
+ result &= lp_create_mode(SNUM(conn));
+ /* Add in force bits */
+ result |= lp_force_create_mode(SNUM(conn));
+ }
+ return(result);
+}
+
+
+/****************************************************************************
+ change a unix mode to a dos mode
+****************************************************************************/
+int dos_mode(connection_struct *conn,char *path,struct stat *sbuf)
+{
+ int result = 0;
+ extern struct current_user current_user;
+
+ DEBUG(8,("dos_mode: %s\n", path));
+
+ if (CAN_WRITE(conn) && !lp_alternate_permissions(SNUM(conn))) {
+ if (!((sbuf->st_mode & S_IWOTH) ||
+ conn->admin_user ||
+ ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
+ ((sbuf->st_mode & S_IWGRP) &&
+ in_group(sbuf->st_gid,current_user.gid,
+ current_user.ngroups,current_user.groups))))
+ result |= aRONLY;
+ } else {
+ if ((sbuf->st_mode & S_IWUSR) == 0)
+ result |= aRONLY;
+ }
+
+ if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
+ result |= aARCH;
+
+ if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0))
+ result |= aSYSTEM;
+
+ if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
+ result |= aHIDDEN;
+
+ if (S_ISDIR(sbuf->st_mode))
+ result = aDIR | (result & aRONLY);
+
+#ifdef S_ISLNK
+#if LINKS_READ_ONLY
+ if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
+ result |= aRONLY;
+#endif
+#endif
+
+ /* hide files with a name starting with a . */
+ if (lp_hide_dot_files(SNUM(conn)))
+ {
+ char *p = strrchr(path,'/');
+ if (p)
+ p++;
+ else
+ p = path;
+
+ if (p[0] == '.' && p[1] != '.' && p[1] != 0)
+ result |= aHIDDEN;
+ }
+
+ /* Optimization : Only call is_hidden_path if it's not already
+ hidden. */
+ if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path))
+ {
+ result |= aHIDDEN;
+ }
+
+ DEBUG(8,("dos_mode returning "));
+
+ if (result & aHIDDEN) DEBUG(8, ("h"));
+ if (result & aRONLY ) DEBUG(8, ("r"));
+ if (result & aSYSTEM) DEBUG(8, ("s"));
+ if (result & aDIR ) DEBUG(8, ("d"));
+ if (result & aARCH ) DEBUG(8, ("a"));
+
+ DEBUG(8,("\n"));
+
+ return(result);
+}
+
+/*******************************************************************
+chmod a file - but preserve some bits
+********************************************************************/
+int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st)
+{
+ struct stat st1;
+ int mask=0;
+ int tmp;
+ int unixmode;
+
+ if (!st) {
+ st = &st1;
+ if (sys_stat(fname,st)) return(-1);
+ }
+
+ if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
+
+ if (dos_mode(conn,fname,st) == dosmode) return(0);
+
+ unixmode = unix_mode(conn,dosmode);
+
+ /* preserve the s bits */
+ mask |= (S_ISUID | S_ISGID);
+
+ /* preserve the t bit */
+#ifdef S_ISVTX
+ mask |= S_ISVTX;
+#endif
+
+ /* possibly preserve the x bits */
+ if (!MAP_ARCHIVE(conn)) mask |= S_IXUSR;
+ if (!MAP_SYSTEM(conn)) mask |= S_IXGRP;
+ if (!MAP_HIDDEN(conn)) mask |= S_IXOTH;
+
+ unixmode |= (st->st_mode & mask);
+
+ /* if we previously had any r bits set then leave them alone */
+ if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
+ unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
+ unixmode |= tmp;
+ }
+
+ /* if we previously had any w bits set then leave them alone
+ if the new mode is not rdonly */
+ if (!IS_DOS_READONLY(dosmode) &&
+ (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
+ unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
+ unixmode |= tmp;
+ }
+
+ return(sys_chmod(fname,unixmode));
+}
+
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index edf87f3e7b..971d309ff9 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -115,3 +115,15 @@ int write_file(files_struct *fsp,char *data,int n)
return(write_data(fsp->fd_ptr->fd,data,n));
}
+
+/*******************************************************************
+sync a file
+********************************************************************/
+void sync_file(connection_struct *conn, files_struct *fsp)
+{
+#ifdef HAVE_FSYNC
+ if(lp_strict_sync(SNUM(conn)))
+ fsync(fsp->fd_ptr->fd);
+#endif
+}
+
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
new file mode 100644
index 0000000000..a6a9e7e7f0
--- /dev/null
+++ b/source3/smbd/filename.c
@@ -0,0 +1,380 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ filename handling routines
+ Copyright (C) Andrew Tridgell 1992-1998
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+extern BOOL case_sensitive;
+extern BOOL case_preserve;
+extern BOOL short_case_preserve;
+extern fstring remote_machine;
+extern BOOL use_mangled_map;
+
+/****************************************************************************
+check if two filenames are equal
+
+this needs to be careful about whether we are case sensitive
+****************************************************************************/
+BOOL fname_equal(char *name1, char *name2)
+{
+ int l1 = strlen(name1);
+ int l2 = strlen(name2);
+
+ /* handle filenames ending in a single dot */
+ if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
+ {
+ BOOL ret;
+ name1[l1-1] = 0;
+ ret = fname_equal(name1,name2);
+ name1[l1-1] = '.';
+ return(ret);
+ }
+
+ if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
+ {
+ BOOL ret;
+ name2[l2-1] = 0;
+ ret = fname_equal(name1,name2);
+ name2[l2-1] = '.';
+ return(ret);
+ }
+
+ /* now normal filename handling */
+ if (case_sensitive)
+ return(strcmp(name1,name2) == 0);
+
+ return(strequal(name1,name2));
+}
+
+
+/****************************************************************************
+mangle the 2nd name and check if it is then equal to the first name
+****************************************************************************/
+BOOL mangled_equal(char *name1, char *name2)
+{
+ pstring tmpname;
+
+ if (is_8_3(name2, True))
+ return(False);
+
+ pstrcpy(tmpname,name2);
+ mangle_name_83(tmpname,sizeof(tmpname));
+
+ return(strequal(name1,tmpname));
+}
+
+/****************************************************************************
+This routine is called to convert names from the dos namespace to unix
+namespace. It needs to handle any case conversions, mangling, format
+changes etc.
+
+We assume that we have already done a chdir() to the right "root" directory
+for this service.
+
+The function will return False if some part of the name except for the last
+part cannot be resolved
+
+If the saved_last_component != 0, then the unmodified last component
+of the pathname is returned there. This is used in an exceptional
+case in reply_mv (so far). If saved_last_component == 0 then nothing
+is returned there.
+
+The bad_path arg is set to True if the filename walk failed. This is
+used to pick the correct error code to return between ENOENT and ENOTDIR
+as Windows applications depend on ERRbadpath being returned if a component
+of a pathname does not exist.
+****************************************************************************/
+BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path)
+{
+ struct stat st;
+ char *start, *end;
+ pstring dirpath;
+ int saved_errno;
+
+ *dirpath = 0;
+ *bad_path = False;
+
+ if(saved_last_component)
+ *saved_last_component = 0;
+
+ /* convert to basic unix format - removing \ chars and cleaning it up */
+ unix_format(name);
+ unix_clean_name(name);
+
+ /* names must be relative to the root of the service - trim any leading /.
+ also trim trailing /'s */
+ trim_string(name,"/","/");
+
+ /*
+ * Ensure saved_last_component is valid even if file exists.
+ */
+ if(saved_last_component) {
+ end = strrchr(name, '/');
+ if(end)
+ pstrcpy(saved_last_component, end + 1);
+ else
+ pstrcpy(saved_last_component, name);
+ }
+
+ if (!case_sensitive &&
+ (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
+ strnorm(name);
+
+ /* check if it's a printer file */
+ if (conn->printer)
+ {
+ if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
+ {
+ char *s;
+ fstring name2;
+ slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
+ /* sanitise the name */
+ for (s=name2 ; *s ; s++)
+ if (!issafe(*s)) *s = '_';
+ pstrcpy(name,(char *)mktemp(name2));
+ }
+ return(True);
+ }
+
+ /* stat the name - if it exists then we are all done! */
+ if (sys_stat(name,&st) == 0)
+ return(True);
+
+ saved_errno = errno;
+
+ DEBUG(5,("unix_convert(%s)\n",name));
+
+ /* a special case - if we don't have any mangling chars and are case
+ sensitive then searching won't help */
+ if (case_sensitive && !is_mangled(name) &&
+ !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
+ return(False);
+
+ /* now we need to recursively match the name against the real
+ directory structure */
+
+ start = name;
+ while (strncmp(start,"./",2) == 0)
+ start += 2;
+
+ /* now match each part of the path name separately, trying the names
+ as is first, then trying to scan the directory for matching names */
+ for (;start;start = (end?end+1:(char *)NULL))
+ {
+ /* pinpoint the end of this section of the filename */
+ end = strchr(start, '/');
+
+ /* chop the name at this point */
+ if (end) *end = 0;
+
+ if(saved_last_component != 0)
+ pstrcpy(saved_last_component, end ? end + 1 : start);
+
+ /* check if the name exists up to this point */
+ if (sys_stat(name, &st) == 0)
+ {
+ /* it exists. it must either be a directory or this must be
+ the last part of the path for it to be OK */
+ if (end && !(st.st_mode & S_IFDIR))
+ {
+ /* an intermediate part of the name isn't a directory */
+ DEBUG(5,("Not a dir %s\n",start));
+ *end = '/';
+ return(False);
+ }
+ }
+ else
+ {
+ pstring rest;
+
+ *rest = 0;
+
+ /* remember the rest of the pathname so it can be restored
+ later */
+ if (end) pstrcpy(rest,end+1);
+
+ /* try to find this part of the path in the directory */
+ if (strchr(start,'?') || strchr(start,'*') ||
+ !scan_directory(dirpath, start, conn, end?True:False))
+ {
+ if (end)
+ {
+ /* an intermediate part of the name can't be found */
+ DEBUG(5,("Intermediate not found %s\n",start));
+ *end = '/';
+ /* We need to return the fact that the intermediate
+ name resolution failed. This is used to return an
+ error of ERRbadpath rather than ERRbadfile. Some
+ Windows applications depend on the difference between
+ these two errors.
+ */
+ *bad_path = True;
+ return(False);
+ }
+
+ /* just the last part of the name doesn't exist */
+ /* we may need to strupper() or strlower() it in case
+ this conversion is being used for file creation
+ purposes */
+ /* if the filename is of mixed case then don't normalise it */
+ if (!case_preserve &&
+ (!strhasupper(start) || !strhaslower(start)))
+ strnorm(start);
+
+ /* check on the mangled stack to see if we can recover the
+ base of the filename */
+ if (is_mangled(start))
+ check_mangled_cache( start );
+
+ DEBUG(5,("New file %s\n",start));
+ return(True);
+ }
+
+ /* restore the rest of the string */
+ if (end)
+ {
+ pstrcpy(start+strlen(start)+1,rest);
+ end = start + strlen(start);
+ }
+ }
+
+ /* add to the dirpath that we have resolved so far */
+ if (*dirpath) pstrcat(dirpath,"/");
+ pstrcat(dirpath,start);
+
+ /* restore the / that we wiped out earlier */
+ if (end) *end = '/';
+ }
+
+ /* the name has been resolved */
+ DEBUG(5,("conversion finished %s\n",name));
+ return(True);
+}
+
+
+/****************************************************************************
+check a filename - possibly caling reducename
+
+This is called by every routine before it allows an operation on a filename.
+It does any final confirmation necessary to ensure that the filename is
+a valid one for the user to access.
+****************************************************************************/
+BOOL check_name(char *name,connection_struct *conn)
+{
+ BOOL ret;
+
+ errno = 0;
+
+ if (IS_VETO_PATH(conn, name)) {
+ DEBUG(5,("file path name %s vetoed\n",name));
+ return(0);
+ }
+
+ ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn)));
+
+ /* Check if we are allowing users to follow symlinks */
+ /* Patch from David Clerc <David.Clerc@cui.unige.ch>
+ University of Geneva */
+
+#ifdef S_ISLNK
+ if (!lp_symlinks(SNUM(conn)))
+ {
+ struct stat statbuf;
+ if ( (sys_lstat(name,&statbuf) != -1) &&
+ (S_ISLNK(statbuf.st_mode)) )
+ {
+ DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
+ ret=0;
+ }
+ }
+#endif
+
+ if (!ret)
+ DEBUG(5,("check_name on %s failed\n",name));
+
+ return(ret);
+}
+
+
+/****************************************************************************
+scan a directory to find a filename, matching without case sensitivity
+
+If the name looks like a mangled name then try via the mangling functions
+****************************************************************************/
+BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache)
+{
+ void *cur_dir;
+ char *dname;
+ BOOL mangled;
+ pstring name2;
+
+ mangled = is_mangled(name);
+
+ /* handle null paths */
+ if (*path == 0)
+ path = ".";
+
+ if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
+ pstrcpy(name, dname);
+ return(True);
+ }
+
+ /*
+ * The incoming name can be mangled, and if we de-mangle it
+ * here it will not compare correctly against the filename (name2)
+ * read from the directory and then mangled by the name_map_mangle()
+ * call. We need to mangle both names or neither.
+ * (JRA).
+ */
+ if (mangled)
+ mangled = !check_mangled_cache( name );
+
+ /* open the directory */
+ if (!(cur_dir = OpenDir(conn, path, True)))
+ {
+ DEBUG(3,("scan dir didn't open dir [%s]\n",path));
+ return(False);
+ }
+
+ /* now scan for matching names */
+ while ((dname = ReadDirName(cur_dir)))
+ {
+ if (*dname == '.' &&
+ (strequal(dname,".") || strequal(dname,"..")))
+ continue;
+
+ pstrcpy(name2,dname);
+ if (!name_map_mangle(name2,False,SNUM(conn))) continue;
+
+ if ((mangled && mangled_equal(name,name2))
+ || fname_equal(name, name2))
+ {
+ /* we've found the file, change it's name and return */
+ if (docache) DirCacheAdd(path,name,dname,SNUM(conn));
+ pstrcpy(name, dname);
+ CloseDir(cur_dir);
+ return(True);
+ }
+ }
+
+ CloseDir(cur_dir);
+ return(False);
+}
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index ccb830637d..d81d80047b 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -114,188 +114,10 @@ void killkids(void)
if(am_parent) kill(0,SIGTERM);
}
-/****************************************************************************
- change a dos mode to a unix mode
- base permission for files:
- everybody gets read bit set
- dos readonly is represented in unix by removing everyone's write bit
- dos archive is represented in unix by the user's execute bit
- dos system is represented in unix by the group's execute bit
- dos hidden is represented in unix by the other's execute bit
- Then apply create mask,
- then add force bits.
- base permission for directories:
- dos directory is represented in unix by unix's dir bit and the exec bit
- Then apply create mask,
- then add force bits.
-****************************************************************************/
-mode_t unix_mode(connection_struct *conn,int dosmode)
-{
- mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
-
- if ( !IS_DOS_READONLY(dosmode) )
- result |= (S_IWUSR | S_IWGRP | S_IWOTH);
-
- if (IS_DOS_DIR(dosmode)) {
- /* We never make directories read only for the owner as under DOS a user
- can always create a file in a read-only directory. */
- result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
- /* Apply directory mask */
- result &= lp_dir_mode(SNUM(conn));
- /* Add in force bits */
- result |= lp_force_dir_mode(SNUM(conn));
- } else {
- if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode))
- result |= S_IXUSR;
-
- if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
- result |= S_IXGRP;
-
- if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
- result |= S_IXOTH;
-
- /* Apply mode mask */
- result &= lp_create_mode(SNUM(conn));
- /* Add in force bits */
- result |= lp_force_create_mode(SNUM(conn));
- }
- return(result);
-}
-
-
-/****************************************************************************
- change a unix mode to a dos mode
-****************************************************************************/
-int dos_mode(connection_struct *conn,char *path,struct stat *sbuf)
-{
- int result = 0;
- extern struct current_user current_user;
-
- DEBUG(8,("dos_mode: %s\n", path));
-
- if (CAN_WRITE(conn) && !lp_alternate_permissions(SNUM(conn))) {
- if (!((sbuf->st_mode & S_IWOTH) ||
- conn->admin_user ||
- ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
- ((sbuf->st_mode & S_IWGRP) &&
- in_group(sbuf->st_gid,current_user.gid,
- current_user.ngroups,current_user.groups))))
- result |= aRONLY;
- } else {
- if ((sbuf->st_mode & S_IWUSR) == 0)
- result |= aRONLY;
- }
-
- if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
- result |= aARCH;
-
- if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0))
- result |= aSYSTEM;
-
- if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
- result |= aHIDDEN;
-
- if (S_ISDIR(sbuf->st_mode))
- result = aDIR | (result & aRONLY);
-
-#ifdef S_ISLNK
-#if LINKS_READ_ONLY
- if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
- result |= aRONLY;
-#endif
-#endif
-
- /* hide files with a name starting with a . */
- if (lp_hide_dot_files(SNUM(conn)))
- {
- char *p = strrchr(path,'/');
- if (p)
- p++;
- else
- p = path;
-
- if (p[0] == '.' && p[1] != '.' && p[1] != 0)
- result |= aHIDDEN;
- }
-
- /* Optimization : Only call is_hidden_path if it's not already
- hidden. */
- if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path))
- {
- result |= aHIDDEN;
- }
-
- DEBUG(8,("dos_mode returning "));
-
- if (result & aHIDDEN) DEBUG(8, ("h"));
- if (result & aRONLY ) DEBUG(8, ("r"));
- if (result & aSYSTEM) DEBUG(8, ("s"));
- if (result & aDIR ) DEBUG(8, ("d"));
- if (result & aARCH ) DEBUG(8, ("a"));
-
- DEBUG(8,("\n"));
-
- return(result);
-}
-
-/*******************************************************************
-chmod a file - but preserve some bits
-********************************************************************/
-int dos_chmod(connection_struct *conn,char *fname,int dosmode,struct stat *st)
-{
- struct stat st1;
- int mask=0;
- int tmp;
- int unixmode;
-
- if (!st) {
- st = &st1;
- if (sys_stat(fname,st)) return(-1);
- }
-
- if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
-
- if (dos_mode(conn,fname,st) == dosmode) return(0);
-
- unixmode = unix_mode(conn,dosmode);
-
- /* preserve the s bits */
- mask |= (S_ISUID | S_ISGID);
-
- /* preserve the t bit */
-#ifdef S_ISVTX
- mask |= S_ISVTX;
-#endif
-
- /* possibly preserve the x bits */
- if (!MAP_ARCHIVE(conn)) mask |= S_IXUSR;
- if (!MAP_SYSTEM(conn)) mask |= S_IXGRP;
- if (!MAP_HIDDEN(conn)) mask |= S_IXOTH;
-
- unixmode |= (st->st_mode & mask);
-
- /* if we previously had any r bits set then leave them alone */
- if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
- unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
- unixmode |= tmp;
- }
-
- /* if we previously had any w bits set then leave them alone
- if the new mode is not rdonly */
- if (!IS_DOS_READONLY(dosmode) &&
- (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
- unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
- unixmode |= tmp;
- }
-
- return(sys_chmod(fname,unixmode));
-}
-
/*******************************************************************
Wrapper around sys_utime that possibly allows DOS semantics rather
than POSIX.
*******************************************************************/
-
int file_utime(connection_struct *conn, char *fname, struct utimbuf *times)
{
extern struct current_user current_user;
@@ -343,7 +165,6 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times)
/*******************************************************************
Change a filetime - possibly allowing DOS semantics.
*******************************************************************/
-
BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime)
{
struct utimbuf times;
@@ -359,373 +180,6 @@ BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime)
return(True);
}
-/****************************************************************************
-check if two filenames are equal
-
-this needs to be careful about whether we are case sensitive
-****************************************************************************/
-static BOOL fname_equal(char *name1, char *name2)
-{
- int l1 = strlen(name1);
- int l2 = strlen(name2);
-
- /* handle filenames ending in a single dot */
- if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
- {
- BOOL ret;
- name1[l1-1] = 0;
- ret = fname_equal(name1,name2);
- name1[l1-1] = '.';
- return(ret);
- }
-
- if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
- {
- BOOL ret;
- name2[l2-1] = 0;
- ret = fname_equal(name1,name2);
- name2[l2-1] = '.';
- return(ret);
- }
-
- /* now normal filename handling */
- if (case_sensitive)
- return(strcmp(name1,name2) == 0);
-
- return(strequal(name1,name2));
-}
-
-
-/****************************************************************************
-mangle the 2nd name and check if it is then equal to the first name
-****************************************************************************/
-static BOOL mangled_equal(char *name1, char *name2)
-{
- pstring tmpname;
-
- if (is_8_3(name2, True))
- return(False);
-
- pstrcpy(tmpname,name2);
- mangle_name_83(tmpname,sizeof(tmpname));
-
- return(strequal(name1,tmpname));
-}
-
-
-/****************************************************************************
-scan a directory to find a filename, matching without case sensitivity
-
-If the name looks like a mangled name then try via the mangling functions
-****************************************************************************/
-static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache)
-{
- void *cur_dir;
- char *dname;
- BOOL mangled;
- pstring name2;
-
- mangled = is_mangled(name);
-
- /* handle null paths */
- if (*path == 0)
- path = ".";
-
- if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
- pstrcpy(name, dname);
- return(True);
- }
-
- /*
- * The incoming name can be mangled, and if we de-mangle it
- * here it will not compare correctly against the filename (name2)
- * read from the directory and then mangled by the name_map_mangle()
- * call. We need to mangle both names or neither.
- * (JRA).
- */
- if (mangled)
- mangled = !check_mangled_cache( name );
-
- /* open the directory */
- if (!(cur_dir = OpenDir(conn, path, True)))
- {
- DEBUG(3,("scan dir didn't open dir [%s]\n",path));
- return(False);
- }
-
- /* now scan for matching names */
- while ((dname = ReadDirName(cur_dir)))
- {
- if (*dname == '.' &&
- (strequal(dname,".") || strequal(dname,"..")))
- continue;
-
- pstrcpy(name2,dname);
- if (!name_map_mangle(name2,False,SNUM(conn))) continue;
-
- if ((mangled && mangled_equal(name,name2))
- || fname_equal(name, name2))
- {
- /* we've found the file, change it's name and return */
- if (docache) DirCacheAdd(path,name,dname,SNUM(conn));
- pstrcpy(name, dname);
- CloseDir(cur_dir);
- return(True);
- }
- }
-
- CloseDir(cur_dir);
- return(False);
-}
-
-/****************************************************************************
-This routine is called to convert names from the dos namespace to unix
-namespace. It needs to handle any case conversions, mangling, format
-changes etc.
-
-We assume that we have already done a chdir() to the right "root" directory
-for this service.
-
-The function will return False if some part of the name except for the last
-part cannot be resolved
-
-If the saved_last_component != 0, then the unmodified last component
-of the pathname is returned there. This is used in an exceptional
-case in reply_mv (so far). If saved_last_component == 0 then nothing
-is returned there.
-
-The bad_path arg is set to True if the filename walk failed. This is
-used to pick the correct error code to return between ENOENT and ENOTDIR
-as Windows applications depend on ERRbadpath being returned if a component
-of a pathname does not exist.
-****************************************************************************/
-BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path)
-{
- struct stat st;
- char *start, *end;
- pstring dirpath;
- int saved_errno;
-
- *dirpath = 0;
- *bad_path = False;
-
- if(saved_last_component)
- *saved_last_component = 0;
-
- /* convert to basic unix format - removing \ chars and cleaning it up */
- unix_format(name);
- unix_clean_name(name);
-
- /* names must be relative to the root of the service - trim any leading /.
- also trim trailing /'s */
- trim_string(name,"/","/");
-
- /*
- * Ensure saved_last_component is valid even if file exists.
- */
- if(saved_last_component) {
- end = strrchr(name, '/');
- if(end)
- pstrcpy(saved_last_component, end + 1);
- else
- pstrcpy(saved_last_component, name);
- }
-
- if (!case_sensitive &&
- (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
- strnorm(name);
-
- /* check if it's a printer file */
- if (conn->printer)
- {
- if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
- {
- char *s;
- fstring name2;
- slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
- /* sanitise the name */
- for (s=name2 ; *s ; s++)
- if (!issafe(*s)) *s = '_';
- pstrcpy(name,(char *)mktemp(name2));
- }
- return(True);
- }
-
- /* stat the name - if it exists then we are all done! */
- if (sys_stat(name,&st) == 0)
- return(True);
-
- saved_errno = errno;
-
- DEBUG(5,("unix_convert(%s)\n",name));
-
- /* a special case - if we don't have any mangling chars and are case
- sensitive then searching won't help */
- if (case_sensitive && !is_mangled(name) &&
- !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
- return(False);
-
- /* now we need to recursively match the name against the real
- directory structure */
-
- start = name;
- while (strncmp(start,"./",2) == 0)
- start += 2;
-
- /* now match each part of the path name separately, trying the names
- as is first, then trying to scan the directory for matching names */
- for (;start;start = (end?end+1:(char *)NULL))
- {
- /* pinpoint the end of this section of the filename */
- end = strchr(start, '/');
-
- /* chop the name at this point */
- if (end) *end = 0;
-
- if(saved_last_component != 0)
- pstrcpy(saved_last_component, end ? end + 1 : start);
-
- /* check if the name exists up to this point */
- if (sys_stat(name, &st) == 0)
- {
- /* it exists. it must either be a directory or this must be
- the last part of the path for it to be OK */
- if (end && !(st.st_mode & S_IFDIR))
- {
- /* an intermediate part of the name isn't a directory */
- DEBUG(5,("Not a dir %s\n",start));
- *end = '/';
- return(False);
- }
- }
- else
- {
- pstring rest;
-
- *rest = 0;
-
- /* remember the rest of the pathname so it can be restored
- later */
- if (end) pstrcpy(rest,end+1);
-
- /* try to find this part of the path in the directory */
- if (strchr(start,'?') || strchr(start,'*') ||
- !scan_directory(dirpath, start, conn, end?True:False))
- {
- if (end)
- {
- /* an intermediate part of the name can't be found */
- DEBUG(5,("Intermediate not found %s\n",start));
- *end = '/';
- /* We need to return the fact that the intermediate
- name resolution failed. This is used to return an
- error of ERRbadpath rather than ERRbadfile. Some
- Windows applications depend on the difference between
- these two errors.
- */
- *bad_path = True;
- return(False);
- }
-
- /* just the last part of the name doesn't exist */
- /* we may need to strupper() or strlower() it in case
- this conversion is being used for file creation
- purposes */
- /* if the filename is of mixed case then don't normalise it */
- if (!case_preserve &&
- (!strhasupper(start) || !strhaslower(start)))
- strnorm(start);
-
- /* check on the mangled stack to see if we can recover the
- base of the filename */
- if (is_mangled(start))
- check_mangled_cache( start );
-
- DEBUG(5,("New file %s\n",start));
- return(True);
- }
-
- /* restore the rest of the string */
- if (end)
- {
- pstrcpy(start+strlen(start)+1,rest);
- end = start + strlen(start);
- }
- }
-
- /* add to the dirpath that we have resolved so far */
- if (*dirpath) pstrcat(dirpath,"/");
- pstrcat(dirpath,start);
-
- /* restore the / that we wiped out earlier */
- if (end) *end = '/';
- }
-
- /* the name has been resolved */
- DEBUG(5,("conversion finished %s\n",name));
- return(True);
-}
-
-
-/****************************************************************************
-check a filename - possibly caling reducename
-
-This is called by every routine before it allows an operation on a filename.
-It does any final confirmation necessary to ensure that the filename is
-a valid one for the user to access.
-****************************************************************************/
-BOOL check_name(char *name,connection_struct *conn)
-{
- BOOL ret;
-
- errno = 0;
-
- if (IS_VETO_PATH(conn, name)) {
- DEBUG(5,("file path name %s vetoed\n",name));
- return(0);
- }
-
- ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn)));
-
- /* Check if we are allowing users to follow symlinks */
- /* Patch from David Clerc <David.Clerc@cui.unige.ch>
- University of Geneva */
-
-#ifdef S_ISLNK
- if (!lp_symlinks(SNUM(conn)))
- {
- struct stat statbuf;
- if ( (sys_lstat(name,&statbuf) != -1) &&
- (S_ISLNK(statbuf.st_mode)) )
- {
- DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
- ret=0;
- }
- }
-#endif
-
- if (!ret)
- DEBUG(5,("check_name on %s failed\n",name));
-
- return(ret);
-}
-
-/****************************************************************************
-check a filename - possibly caling reducename
-****************************************************************************/
-static void check_for_pipe(char *fname)
-{
- /* special case of pipe opens */
- char s[10];
- StrnCpy(s,fname,9);
- strlower(s);
- if (strstr(s,"pipe/"))
- {
- DEBUG(3,("Rejecting named pipe open for %s\n",fname));
- unix_ERR_class = ERRSRV;
- unix_ERR_code = ERRaccess;
- }
-}
/****************************************************************************
fd support routines - attempt to do a sys_open
@@ -946,6 +400,22 @@ static BOOL check_access_allowed_for_current_user( char *fname, int accmode )
}
/****************************************************************************
+check a filename for the pipe string
+****************************************************************************/
+static void check_for_pipe(char *fname)
+{
+ /* special case of pipe opens */
+ char s[10];
+ StrnCpy(s,fname,9);
+ strlower(s);
+ if (strstr(s,"pipe/")) {
+ DEBUG(3,("Rejecting named pipe open for %s\n",fname));
+ unix_ERR_class = ERRSRV;
+ unix_ERR_code = ERRaccess;
+ }
+}
+
+/****************************************************************************
open a file
****************************************************************************/
static void open_file(files_struct *fsp,connection_struct *conn,
@@ -1235,17 +705,6 @@ static void open_file(files_struct *fsp,connection_struct *conn,
#endif
}
-/*******************************************************************
-sync a file
-********************************************************************/
-void sync_file(connection_struct *conn, files_struct *fsp)
-{
-#ifdef HAVE_FSYNC
- if(lp_strict_sync(SNUM(conn)))
- fsync(fsp->fd_ptr->fd);
-#endif
-}
-
/****************************************************************************
run a file if it is a magic script
****************************************************************************/