]> git.samba.org - metze/samba/wip.git/blobdiff - source3/smbd/trans2.c
Extend NTIMES to allow setting create_time
[metze/samba/wip.git] / source3 / smbd / trans2.c
index b9a04e9b4f66c1f301ccc26f3bfaa33c81614864..1b161d533898ac31f1b3c75c368b4e97cd2d989a 100644 (file)
 */
 
 #include "includes.h"
+#include "version.h"
+#include "smbd/globals.h"
 
-extern int max_send;
 extern enum protocol_types Protocol;
-extern uint32 global_client_caps;
 
 #define get_file_size(sbuf) ((sbuf).st_size)
 #define DIR_ENTRY_SAFETY_MARGIN 4096
@@ -94,7 +94,7 @@ uint64_t get_allocation_size(connection_struct *conn, files_struct *fsp, const S
 
 static bool samba_private_attr_name(const char *unix_ea_name)
 {
-       static const char *prohibited_ea_names[] = {
+       static const char * const prohibited_ea_names[] = {
                SAMBA_POSIX_INHERITANCE_EA_NAME,
                SAMBA_XATTR_DOS_ATTRIB,
                NULL
@@ -1011,7 +1011,7 @@ static void call_trans2open(connection_struct *conn,
                req,                                    /* req */
                0,                                      /* root_dir_fid */
                fname,                                  /* fname */
-               true,                                   /* is_dos_path */
+               CFF_DOS_PATH,                           /* create_file_flags */
                access_mask,                            /* access_mask */
                share_mode,                             /* share_access */
                create_disposition,                     /* create_disposition*/
@@ -1095,15 +1095,13 @@ static bool exact_match(connection_struct *conn,
 {
        if (mask[0] == '.' && mask[1] == 0)
                return False;
-       if (conn->case_sensitive)
-               return strcmp(str,mask)==0;
-       if (StrCaseCmp(str,mask) != 0) {
-               return False;
-       }
        if (dptr_has_wild(conn->dirptr)) {
                return False;
        }
-       return True;
+       if (conn->case_sensitive)
+               return strcmp(str,mask)==0;
+       else
+               return StrCaseCmp(str,mask) == 0;
 }
 
 /****************************************************************************
@@ -1432,7 +1430,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
 
                        mdate_ts = get_mtimespec(&sbuf);
                        adate_ts = get_atimespec(&sbuf);
-                       create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+                       create_date_ts = get_create_timespec(&sbuf,
+                           lp_fake_dir_create_times(SNUM(conn)));
 
                        if (ask_sharemode) {
                                struct timespec write_time_ts;
@@ -1455,7 +1454,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
                        mdate = convert_timespec_to_time_t(mdate_ts);
                        adate = convert_timespec_to_time_t(adate_ts);
 
-                       DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
+                       DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
+                               pathreal,fname));
 
                        found = True;
 
@@ -3073,6 +3073,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                             i < conn->server_info->ptok->num_sids; ++i) {
                                sid_bytes += ndr_size_dom_sid(
                                        &conn->server_info->ptok->user_sids[i],
+                                       NULL, 
                                        0);
                        }
 
@@ -3095,6 +3096,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                            i < conn->server_info->ptok->num_sids; ++i) {
                                int sid_len = ndr_size_dom_sid(
                                        &conn->server_info->ptok->user_sids[i],
+                                       NULL,
                                        0);
 
                                sid_linearize(pdata + data_len, sid_len,
@@ -3689,7 +3691,7 @@ static NTSTATUS marshall_stream_info(unsigned int num_streams,
        unsigned int i;
        unsigned int ofs = 0;
 
-       for (i=0; i<num_streams; i++) {
+       for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
                unsigned int next_offset;
                size_t namelen;
                smb_ucs2_t *namebuf;
@@ -3708,11 +3710,6 @@ static NTSTATUS marshall_stream_info(unsigned int num_streams,
 
                namelen -= 2;
 
-               if (ofs + 24 + namelen > max_data_bytes) {
-                       TALLOC_FREE(namebuf);
-                       return NT_STATUS_BUFFER_TOO_SMALL;
-               }
-
                SIVAL(data, ofs+4, namelen);
                SOFF_T(data, ofs+8, streams[i].size);
                SOFF_T(data, ofs+16, streams[i].alloc_size);
@@ -3727,10 +3724,6 @@ static NTSTATUS marshall_stream_info(unsigned int num_streams,
                else {
                        unsigned int align = ndr_align_size(next_offset, 8);
 
-                       if (next_offset + align > max_data_bytes) {
-                               return NT_STATUS_BUFFER_TOO_SMALL;
-                       }
-
                        memset(data+next_offset, 0, align);
                        next_offset += align;
 
@@ -4901,7 +4894,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
                           files_struct *fsp,
                           const char *fname,
                           const SMB_STRUCT_STAT *psbuf,
-                          struct timespec ts[2],
+                          struct smb_file_time *ft,
                           bool setting_write_time)
 {
        uint32 action =
@@ -4913,23 +4906,29 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
        }
 
        /* get some defaults (no modifications) if any info is zero or -1. */
-       if (null_timespec(ts[0])) {
-               ts[0] = get_atimespec(psbuf);
+       if (null_timespec(ft->atime)) {
+               ft->atime= get_atimespec(psbuf);
                action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
        }
 
-       if (null_timespec(ts[1])) {
-               ts[1] = get_mtimespec(psbuf);
+       if (null_timespec(ft->mtime)) {
+               ft->mtime = get_mtimespec(psbuf);
                action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
        }
 
        if (!setting_write_time) {
-               /* ts[1] comes from change time, not write time. */
+               /* ft->mtime comes from change time, not write time. */
                action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
        }
 
-       DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
-       DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+       DEBUG(5,("smb_set_filetime: actime: %s\n ",
+               time_to_asc(convert_timespec_to_time_t(ft->atime))));
+       DEBUG(5,("smb_set_filetime: modtime: %s\n ",
+               time_to_asc(convert_timespec_to_time_t(ft->mtime))));
+       if (!null_timespec(ft->create_time)) {
+               DEBUG(5,("smb_set_file_time: createtime: %s\n ",
+                  time_to_asc(convert_timespec_to_time_t(ft->create_time))));
+       }
 
        /*
         * Try and set the times of this file if
@@ -4939,7 +4938,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
        {
                struct timespec mts = get_mtimespec(psbuf);
                struct timespec ats = get_atimespec(psbuf);
-               if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
+               if ((timespec_compare(&ft->atime, &ats) == 0) &&
+                   (timespec_compare(&ft->mtime, &mts) == 0)) {
                        return NT_STATUS_OK;
                }
        }
@@ -4956,18 +4956,19 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
                 */
 
                DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
-                         time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+                         time_to_asc(convert_timespec_to_time_t(ft->mtime))));
 
                if (fsp != NULL) {
                        if (fsp->base_fsp) {
-                               set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
+                               set_sticky_write_time_fsp(fsp->base_fsp,
+                                                         ft->mtime);
                        } else {
-                               set_sticky_write_time_fsp(fsp, ts[1]);
+                               set_sticky_write_time_fsp(fsp, ft->mtime);
                        }
                } else {
                        set_sticky_write_time_path(conn, fname,
                                            vfs_file_id_from_sbuf(conn, psbuf),
-                                           ts[1]);
+                                           ft->mtime);
                }
        }
 
@@ -4977,7 +4978,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
                fname = fsp->base_fsp->fsp_name;
        }
 
-       if(file_ntimes(conn, fname, ts)!=0) {
+       if(file_ntimes(conn, fname, ft)!=0) {
                return map_nt_error_from_unix(errno);
        }
        notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
@@ -5064,7 +5065,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
                req,                                    /* req */
                0,                                      /* root_dir_fid */
                fname,                                  /* fname */
-               false,                                  /* is_dos_path */
+               0,                                      /* create_file_flags */
                FILE_WRITE_ATTRIBUTES,                  /* access_mask */
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
                    FILE_SHARE_DELETE),
@@ -5374,6 +5375,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        char *newname = NULL;
        char *base_name = NULL;
        bool dest_has_wcard = False;
+       SMB_STRUCT_STAT sbuf;
+       char *newname_last_component = NULL;
        NTSTATUS status = NT_STATUS_OK;
        char *p;
        TALLOC_CTX *ctx = talloc_tos();
@@ -5382,6 +5385,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       ZERO_STRUCT(sbuf);
+
        overwrite = (CVAL(pdata,0) ? True : False);
        root_fid = IVAL(pdata,4);
        len = IVAL(pdata,8);
@@ -5415,6 +5420,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        }
 
        if (fsp && fsp->base_fsp) {
+               /* newname must be a stream name. */
                if (newname[0] != ':') {
                        return NT_STATUS_NOT_SUPPORTED;
                }
@@ -5425,6 +5431,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                        return NT_STATUS_NO_MEMORY;
                }
        } else {
+               /* newname must *not* be a stream name. */
                if (is_ntfs_stream_name(newname)) {
                        return NT_STATUS_NOT_SUPPORTED;
                }
@@ -5450,18 +5457,11 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                if (!base_name) {
                        return NT_STATUS_NO_MEMORY;
                }
-       }
-
-       if (fsp) {
-               SMB_STRUCT_STAT sbuf;
-               char *newname_last_component = NULL;
-
-               ZERO_STRUCT(sbuf);
 
                status = unix_convert(ctx, conn, newname, False,
-                                       &newname,
-                                       &newname_last_component,
-                                       &sbuf);
+                               &newname,
+                               &newname_last_component,
+                               &sbuf);
 
                /* If an error we expect this to be
                 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
@@ -5471,7 +5471,9 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                                        status)) {
                        return status;
                }
+       }
 
+       if (fsp) {
                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
                        fsp->fnum, fsp->fsp_name, base_name ));
                status = rename_internals_fsp(conn, fsp, base_name,
@@ -5685,16 +5687,21 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
                                        const char *fname,
                                        const SMB_STRUCT_STAT *psbuf)
 {
-       struct timespec ts[2];
+       struct smb_file_time ft;
+       ZERO_STRUCT(ft);
 
        if (total_data < 12) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       /* create time */
+       ft.create_time = interpret_long_date(pdata);
+
        /* access time */
-       ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
+       ft.atime = interpret_long_date(pdata + 8);
+
        /* write time */
-       ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
+       ft.mtime = interpret_long_date(pdata + 16);
 
        DEBUG(10,("smb_set_info_standard: file %s\n",
                fname ? fname : fsp->fsp_name ));
@@ -5703,7 +5710,7 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
                                fsp,
                                fname,
                                psbuf,
-                               ts,
+                               &ft,
                                true);
 }
 
@@ -5721,47 +5728,49 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
        /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
        struct timespec write_time;
        struct timespec changed_time;
+       struct smb_file_time ft;
        uint32 dosmode = 0;
-       struct timespec ts[2];
        NTSTATUS status = NT_STATUS_OK;
        bool setting_write_time = true;
 
+       ZERO_STRUCT(ft);
+
        if (total_data < 36) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* Set the attributes */
        dosmode = IVAL(pdata,32);
-       status = smb_set_file_dosmode(conn,
-                                       fname,
-                                       psbuf,
-                                       dosmode);
+       status = smb_set_file_dosmode(conn, fname, psbuf, dosmode);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       /* Ignore create time at offset pdata. */
 
        /* access time */
-       ts[0] = interpret_long_date(pdata+8);
+       ft.atime = interpret_long_date(pdata+8);
 
        write_time = interpret_long_date(pdata+16);
        changed_time = interpret_long_date(pdata+24);
 
        /* mtime */
-       ts[1] = timespec_min(&write_time, &changed_time);
+       ft.mtime = timespec_min(&write_time, &changed_time);
 
-       if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
-               ts[1] = write_time;
+       /* create time */
+       ft.create_time = interpret_long_date(pdata);
+
+       if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
+           !null_timespec(write_time)) {
+               ft.mtime = write_time;
        }
 
        /* Prefer a defined time to an undefined one. */
-       if (null_timespec(ts[1])) {
+       if (null_timespec(ft.mtime)) {
                if (null_timespec(write_time)) {
-                       ts[1] = changed_time;
+                       ft.mtime = changed_time;
                        setting_write_time = false;
                } else {
-                       ts[1] = write_time;
+                       ft.mtime = write_time;
                }
        }
 
@@ -5772,7 +5781,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
                                fsp,
                                fname,
                                psbuf,
-                               ts,
+                               &ft,
                                setting_write_time);
 }
 
@@ -5844,7 +5853,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
                req,                                    /* req */
                0,                                      /* root_dir_fid */
                fname,                                  /* fname */
-               false,                                  /* is_dos_path */
+               0,                                      /* create_file_flags */
                FILE_WRITE_DATA,                        /* access_mask */
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
                    FILE_SHARE_DELETE),
@@ -5992,9 +6001,12 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
         */
 
        if (lp_inherit_perms(SNUM(conn))) {
-               inherit_access_posix_acl(
-                       conn, parent_dirname(fname),
-                       fname, unixmode);
+               char *parent;
+               if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               inherit_access_posix_acl(conn, parent, fname, unixmode);
+               TALLOC_FREE(parent);
        }
 
        if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
@@ -6017,7 +6029,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                                        const char *fname,
                                        SMB_STRUCT_STAT *psbuf)
 {
-       struct timespec ts[2];
+       struct smb_file_time ft;
        uint32 raw_unixmode;
        mode_t unixmode;
        SMB_OFF_T size = 0;
@@ -6027,6 +6039,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
        bool delete_on_fail = False;
        enum perm_type ptype;
 
+       ZERO_STRUCT(ft);
+
        if (total_data < 100) {
                return NT_STATUS_INVALID_PARAMETER;
        }
@@ -6044,8 +6058,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
 #endif /* LARGE_SMB_OFF_T */
        }
 
-       ts[0] = interpret_long_date(pdata+24); /* access_time */
-       ts[1] = interpret_long_date(pdata+32); /* modification_time */
+       ft.atime = interpret_long_date(pdata+24); /* access_time */
+       ft.mtime = interpret_long_date(pdata+32); /* modification_time */
        set_owner = (uid_t)IVAL(pdata,40);
        set_grp = (gid_t)IVAL(pdata,48);
        raw_unixmode = IVAL(pdata,84);
@@ -6088,8 +6102,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                /* Ensure we don't try and change anything else. */
                raw_unixmode = SMB_MODE_NO_CHANGE;
                size = get_file_size(*psbuf);
-               ts[0] = get_atimespec(psbuf);
-               ts[1] = get_mtimespec(psbuf);
+               ft.atime = get_atimespec(psbuf);
+               ft.mtime = get_mtimespec(psbuf);
                /* 
                 * We continue here as we might want to change the 
                 * owner uid/gid.
@@ -6177,7 +6191,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                                fsp,
                                fname,
                                psbuf,
-                               ts,
+                               &ft,
                                true);
 }
 
@@ -6286,7 +6300,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                req,                                    /* req */
                0,                                      /* root_dir_fid */
                fname,                                  /* fname */
-               false,                                  /* is_dos_path */
+               0,                                      /* create_file_flags */
                FILE_READ_ATTRIBUTES,                   /* access_mask */
                FILE_SHARE_NONE,                        /* share_access */
                FILE_CREATE,                            /* create_disposition*/
@@ -6460,7 +6474,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                req,                                    /* req */
                0,                                      /* root_dir_fid */
                fname,                                  /* fname */
-               false,                                  /* is_dos_path */
+               0,                                      /* create_file_flags */
                access_mask,                            /* access_mask */
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
                    FILE_SHARE_DELETE),
@@ -6590,7 +6604,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
                req,                                    /* req */
                0,                                      /* root_dir_fid */
                fname,                                  /* fname */
-               false,                                  /* is_dos_path */
+               0,                                      /* create_file_flags */
                DELETE_ACCESS,                          /* access_mask */
                (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
                    FILE_SHARE_DELETE),
@@ -7225,7 +7239,6 @@ static void call_trans2findnotifyfirst(connection_struct *conn,
                                       char **ppdata, int total_data,
                                       unsigned int max_data_bytes)
 {
-       static uint16 fnf_handle = 257;
        char *params = *pparams;
        uint16 info_level;