#include "includes.h"
+static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
+{
+#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
+ if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
+ return FILE_ATTRIBUTE_SPARSE;
+ }
+#endif
+ return 0;
+}
+
/****************************************************************************
Change a dos mode to a unix mode.
Base permission for files:
- if inheriting
+ if creating file and inheriting
apply read/write bits from parent directory.
else
everybody gets read bit set
}
****************************************************************************/
-mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname)
+mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL creating_file)
{
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. */
result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
}
- if (fname && lp_inherit_perms(SNUM(conn))) {
+ if (fname && creating_file && lp_inherit_perms(SNUM(conn))) {
char *dname;
SMB_STRUCT_STAT sbuf;
Change a unix mode to a dos mode.
****************************************************************************/
-uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf)
+uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
{
int result = 0;
- if ((sbuf->st_mode & S_IWUSR) == 0)
+ if (lp_acl_check_permissions(SNUM(conn))) {
+ if (!can_write_to_file(conn, path, sbuf)) {
+ 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 (S_ISDIR(sbuf->st_mode))
result = aDIR | (result & aRONLY);
-#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
- if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
- result |= FILE_ATTRIBUTE_SPARSE;
- }
-#endif
+ result |= set_sparse_flag(sbuf);
#ifdef S_ISLNK
#if LINKS_READ_ONLY
/* Get the DOS attributes from an EA by preference. */
if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
+ result |= set_sparse_flag(sbuf);
return result;
}
- result = dos_mode_from_sbuf(conn, sbuf);
+ result = dos_mode_from_sbuf(conn, path, sbuf);
/* Now do any modifications that depend on the path name. */
/* hide files with a name starting with a . */
chmod a file - but preserve some bits.
********************************************************************/
-int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st)
+int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st, BOOL creating_file)
{
SMB_STRUCT_STAT st1;
int mask=0;
int ret = -1;
DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
- if (!st) {
+ if (!st || (st && !VALID_STAT(*st))) {
st = &st1;
if (SMB_VFS_STAT(conn,fname,st))
return(-1);
}
- if (!get_acl_group_bits(conn, fname, &st->st_mode)) {
- return(-1);
- }
+ get_acl_group_bits(conn, fname, &st->st_mode);
if (S_ISDIR(st->st_mode))
dosmode |= aDIR;
return 0;
}
- unixmode = unix_mode(conn,dosmode,fname);
+ unixmode = unix_mode(conn,dosmode,fname, creating_file);
/* preserve the s bits */
mask |= (S_ISUID | S_ISGID);
if (!fsp)
return -1;
become_root();
- ret = SMB_VFS_FCHMOD(fsp, fsp->fd, unixmode);
+ ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode);
unbecome_root();
close_file_fchmod(fsp);
}
than POSIX.
*******************************************************************/
-int file_utime(connection_struct *conn, char *fname, struct utimbuf *times)
+int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times)
{
- extern struct current_user current_user;
- SMB_STRUCT_STAT sb;
+ SMB_STRUCT_STAT sbuf;
int ret = -1;
errno = 0;
+ ZERO_STRUCT(sbuf);
if(SMB_VFS_UTIME(conn,fname, times) == 0)
return 0;
(as DOS does).
*/
- if(SMB_VFS_STAT(conn,fname,&sb) != 0)
- return -1;
-
/* Check if we have write access. */
- if (CAN_WRITE(conn)) {
- if (((sb.st_mode & S_IWOTH) || conn->admin_user ||
- ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) ||
- ((sb.st_mode & S_IWGRP) &&
- in_group(sb.st_gid,current_user.gid,
- current_user.ngroups,current_user.groups)))) {
- /* We are allowed to become root and change the filetime. */
- become_root();
- ret = SMB_VFS_UTIME(conn,fname, times);
- unbecome_root();
- }
+ if (can_write_to_file(conn, fname, &sbuf)) {
+ /* We are allowed to become root and change the filetime. */
+ become_root();
+ ret = SMB_VFS_UTIME(conn,fname, times);
+ unbecome_root();
}
return ret;
Change a filetime - possibly allowing DOS semantics.
*******************************************************************/
-BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime)
+BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime)
{
struct utimbuf times;