diff -ur ../samba-2.2.8-grantb-saved/include/local.h source/include/local.h --- ../samba-2.2.8-grantb-saved/include/local.h Fri Mar 14 19:50:32 2003 +++ source/include/local.h Thu Aug 28 13:28:07 2003 @@ -196,4 +196,10 @@ /* Max number of simultaneous winbindd socket connections. */ #define WINBINDD_MAX_SIMULTANEOUS_CLIENTS 200 + +/* extended attribute to use for DOS attributes */ +#define XATTR_DOS_ATTRIB "user.DOSATTRIB" + #endif + + diff -ur ../samba-2.2.8-grantb-saved/include/proto.h source/include/proto.h --- ../samba-2.2.8-grantb-saved/include/proto.h Fri May 16 12:47:28 2003 +++ source/include/proto.h Thu Aug 28 13:34:48 2003 @@ -1064,6 +1064,12 @@ int sys_dlclose (void *handle); const char *sys_dlerror(void); void sys_adminlog(int priority, const char *format_str, ...); +ssize_t sys_getxattr(const char *path, const char *name, void *value, size_t size); +ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size); +int sys_setxattr(const char *path, const char *name, const void *value, + size_t size, int flags); +int sys_fsetxattr(int filedes, const char *name, const void *value, + size_t size, int flags); /* The following definitions come from lib/talloc.c */ diff -ur ../samba-2.2.8-grantb-saved/include/smb.h source/include/smb.h --- ../samba-2.2.8-grantb-saved/include/smb.h Fri Mar 14 19:50:33 2003 +++ source/include/smb.h Thu Aug 28 14:10:56 2003 @@ -93,6 +93,7 @@ #define aVOLID (1L<<3) /* 0x08 */ #define aDIR (1L<<4) /* 0x10 */ #define aARCH (1L<<5) /* 0x20 */ +#define aNORMAL (1L<<6) /* 0x80 */ /* deny modes */ #define DENY_DOS 0 diff -ur ../samba-2.2.8-grantb-saved/lib/system.c source/lib/system.c --- ../samba-2.2.8-grantb-saved/lib/system.c Fri Mar 14 19:50:33 2003 +++ source/lib/system.c Thu Aug 28 13:28:52 2003 @@ -1331,3 +1331,28 @@ #endif SAFE_FREE(*msgbuf); } + + +/* interface to extended attributes */ + +ssize_t sys_getxattr(const char *path, const char *name, void *value, size_t size) +{ + return getxattr(path, name, value, size); +} + +ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size) +{ + return fgetxattr(filedes, name, value, size); +} + +int sys_setxattr(const char *path, const char *name, const void *value, + size_t size, int flags) +{ + return setxattr(path, name, value, size, flags); +} + +int sys_fsetxattr(int filedes, const char *name, const void *value, + size_t size, int flags) +{ + return fsetxattr(filedes, name, value, size, flags); +} diff -ur ../samba-2.2.8-grantb-saved/smbd/dosmode.c source/smbd/dosmode.c --- ../samba-2.2.8-grantb-saved/smbd/dosmode.c Thu Aug 28 18:29:28 2003 +++ source/smbd/dosmode.c Thu Aug 28 15:25:59 2003 @@ -45,71 +45,60 @@ ****************************************************************************/ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) { - mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); - mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */ + mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); + mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */ - if ( !IS_DOS_READONLY(dosmode) ) - result |= (S_IWUSR | S_IWGRP | S_IWOTH); - - if (fname && lp_inherit_perms(SNUM(conn))) { - char *dname; - SMB_STRUCT_STAT sbuf; - - dname = parent_dirname(fname); - DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); - if (vfs_stat(conn,dname,&sbuf) != 0) { - DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); - return(0); /* *** shouldn't happen! *** */ - } - - /* Save for later - but explicitly remove setuid bit for safety. */ - dir_mode = sbuf.st_mode & ~S_ISUID; - DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode)); - /* Clear "result" */ - result = 0; - } - - 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_IWUSR); - - if (dir_mode) { - /* Inherit mode of parent directory. */ - result |= dir_mode; - } else { - /* Provisionally add all 'x' bits */ - result |= (S_IXUSR | S_IXGRP | S_IXOTH); - - /* Apply directory mask */ - result &= lp_dir_mask(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; - - if (dir_mode) { - /* Inherit 666 component of parent directory mode */ - result |= dir_mode - & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); - } else { - /* Apply mode mask */ - result &= lp_create_mask(SNUM(conn)); - /* Add in force bits */ - result |= lp_force_create_mode(SNUM(conn)); - } - } - - DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result )); - return(result); + if (fname && lp_inherit_perms(SNUM(conn))) { + char *dname; + SMB_STRUCT_STAT sbuf; + + dname = parent_dirname(fname); + DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); + if (vfs_stat(conn,dname,&sbuf) != 0) { + DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); + return(0); /* *** shouldn't happen! *** */ + } + + /* Save for later - but explicitly remove setuid bit for safety. */ + dir_mode = sbuf.st_mode & ~S_ISUID; + DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode)); + /* Clear "result" */ + result = 0; + } + + 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_IWUSR); + + if (dir_mode) { + /* Inherit mode of parent directory. */ + result |= dir_mode; + } else { + /* Provisionally add all 'x' bits */ + result |= (S_IXUSR | S_IXGRP | S_IXOTH); + + /* Apply directory mask */ + result &= lp_dir_mask(SNUM(conn)); + /* Add in force bits */ + result |= lp_force_dir_mode(SNUM(conn)); + } + + } else { + if (dir_mode) { + /* Inherit 666 component of parent directory mode */ + result |= dir_mode + & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); + } else { + /* Apply mode mask */ + result &= lp_create_mask(SNUM(conn)); + /* Add in force bits */ + result |= lp_force_create_mode(SNUM(conn)); + } + } + + DEBUG(4,("unix_mode(%s) returning 0%o\n",fname,(int)result )); + return(result); } @@ -118,63 +107,36 @@ ****************************************************************************/ int dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf) { - int result = 0; + fstring attr; + int rc, dosattr; + int ret = 0; - DEBUG(8,("dos_mode: %s\n", path)); - - if ((sbuf->st_mode & S_IWUSR) == 0) - result |= aRONLY; + if (S_ISDIR(sbuf->st_mode)) { + ret |= aDIR; + } - 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")); + rc = sys_getxattr(path, XATTR_DOS_ATTRIB, attr, sizeof(attr)); + if (rc == -1) { + if (errno != ENODATA) { + DEBUG(0,("getxattr failed for %s - %s\n", path, strerror(errno))); + } + return ret; + } + + attr[rc] = 0; + + if (rc < 2 || + strncmp(attr, "0x", 2) != 0 || + sscanf(attr, "%i", &dosattr) != 1) { + DEBUG(3,("Badly formed DOSATTRIB - %s\n", attr)); + return ret; + } - DEBUG(8,("\n")); + ret |= dosattr; - return(result); + DEBUG(4,("dosmode for %s is 0x%x\n", path, ret)); + + return ret; } /******************************************************************* @@ -183,65 +145,36 @@ int file_chmod(connection_struct *conn,char *fname,int dosmode,SMB_STRUCT_STAT *st) { SMB_STRUCT_STAT st1; - int mask=0; - mode_t tmp; - mode_t unixmode; int ret = -1; + fstring attr; if (!st) { st = &st1; - if (vfs_stat(conn,fname,st)) - return(-1); + if (vfs_stat(conn,fname,st)) { + return -1; + } } - if (S_ISDIR(st->st_mode)) + if (S_ISDIR(st->st_mode)) { dosmode |= aDIR; - else + } else { dosmode &= ~aDIR; - - if (dos_mode(conn,fname,st) == dosmode) - return(0); - - unixmode = unix_mode(conn,dosmode,fname); - - /* 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 - whilst adding in the new w bits, if the new mode is not rdonly */ - if (!IS_DOS_READONLY(dosmode)) { - unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); + if (dos_mode(conn,fname,st) == dosmode) { + return 0; } - if ((ret = vfs_chmod(conn,fname,unixmode)) == 0) + snprintf(attr, sizeof(attr)-1, "0x%x", dosmode & 0x3F); + + ret = sys_setxattr(fname, XATTR_DOS_ATTRIB, attr, strlen(attr), 0); + if (ret == 0) { return 0; + } + - if((errno != EPERM) && (errno != EACCES)) - return -1; + DEBUG(3,("setxattr failed for %s - %s\n", fname, strerror(errno))); - if(!lp_dos_filemode(SNUM(conn))) - return -1; /* We want DOS semantics, ie allow non owner with write permission to change the bits on a file. Just like file_utime below. @@ -249,24 +182,16 @@ /* Check if we have write access. */ if (CAN_WRITE(conn)) { - /* - * We need to open the file with write access whilst - * still in our current user context. This ensures we - * are not violating security in doing the fchmod. - * This file open does *not* break any oplocks we are - * holding. We need to review this.... may need to - * break batch oplocks open by others. JRA. - */ files_struct *fsp = open_file_fchmod(conn,fname,st); if (!fsp) return -1; become_root(); - ret = conn->vfs_ops.fchmod(fsp, fsp->fd, unixmode); + ret = sys_fsetxattr(fsp->fd, XATTR_DOS_ATTRIB, attr, strlen(attr), 0); unbecome_root(); close_file_fchmod(fsp); } - return( ret ); + return ret; } diff -ur ../samba-2.2.8-grantb-saved/smbd/fileio.c source/smbd/fileio.c --- ../samba-2.2.8-grantb-saved/smbd/fileio.c Fri Mar 14 19:50:37 2003 +++ source/smbd/fileio.c Thu Aug 28 14:59:36 2003 @@ -177,8 +177,9 @@ if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); fsp->size = (SMB_BIG_UINT)st.st_size; - if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) + if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) { file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st); + } /* * If this is the first write and we have an exclusive oplock then setup diff -ur ../samba-2.2.8-grantb-saved/smbd/nttrans.c source/smbd/nttrans.c --- ../samba-2.2.8-grantb-saved/smbd/nttrans.c Fri Mar 14 19:50:37 2003 +++ source/smbd/nttrans.c Thu Aug 28 15:26:50 2003 @@ -902,6 +902,12 @@ END_PROFILE(SMBntcreateX); return ERROR_DOS(ERRDOS,ERRnoaccess); } + + /* files should be initially set as archive */ + if (smb_action == FILE_WAS_CREATED) { + file_chmod(fsp->conn,fsp->fsp_name,fmode | aARCH,&sbuf); + } + /* Save the requested allocation size. */ allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize);