r4214: possibly fix the "no-EAs" bug from OS/2
[samba.git] / source4 / smb_server / trans2.c
index 02a7cbff011c94747b637424c262c491bb708703..b75c8eb71a9900d555d94e5c15d04d505f3015ba 100644 (file)
@@ -403,6 +403,108 @@ static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct smb_trans2 *tr
        return NT_STATUS_INVALID_LEVEL;
 }
 
+
+/*
+  trans2 open implementation
+*/
+static NTSTATUS trans2_open(struct smbsrv_request *req, struct smb_trans2 *trans)
+{
+       union smb_open *io;
+       NTSTATUS status;
+
+       /* make sure we got enough parameters */
+       if (trans->in.params.length < 29) {
+               return NT_STATUS_FOOBAR;
+       }
+
+       io = talloc_p(req, union smb_open);
+       if (io == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       io->t2open.level         = RAW_OPEN_T2OPEN;
+       io->t2open.in.flags      = SVAL(trans->in.params.data, VWV(0));
+       io->t2open.in.open_mode  = SVAL(trans->in.params.data, VWV(1));
+       io->t2open.in.file_attrs = SVAL(trans->in.params.data, VWV(3));
+       io->t2open.in.write_time = srv_pull_dos_date(req->smb_conn, 
+                                                   trans->in.params.data + VWV(4));;
+       io->t2open.in.open_func  = SVAL(trans->in.params.data, VWV(6));
+       io->t2open.in.size       = IVAL(trans->in.params.data, VWV(7));
+       io->t2open.in.timeout    = IVAL(trans->in.params.data, VWV(9));
+       io->t2open.in.num_eas    = 0;
+       io->t2open.in.eas        = NULL;
+
+       trans2_pull_blob_string(req, &trans->in.params, 28, &io->t2open.in.fname, 0);
+
+       status = ea_pull_list(&trans->in.data, io, &io->t2open.in.num_eas, &io->t2open.in.eas);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       status = ntvfs_openfile(req, io);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       trans2_setup_reply(req, trans, 30, 0, 0);
+
+       SSVAL(trans->out.params.data, VWV(0), io->t2open.out.fnum);
+       SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib);
+       srv_push_dos_date3(req->smb_conn, trans->out.params.data, 
+                          VWV(2), io->t2open.out.write_time);
+       SIVAL(trans->out.params.data, VWV(4), io->t2open.out.size);
+       SSVAL(trans->out.params.data, VWV(6), io->t2open.out.access);
+       SSVAL(trans->out.params.data, VWV(7), io->t2open.out.ftype);
+       SSVAL(trans->out.params.data, VWV(8), io->t2open.out.devstate);
+       SSVAL(trans->out.params.data, VWV(9), io->t2open.out.action);
+       SIVAL(trans->out.params.data, VWV(10), 0); /* reserved */
+       SSVAL(trans->out.params.data, VWV(12), 0); /* EaErrorOffset */
+       SIVAL(trans->out.params.data, VWV(13), 0); /* EaLength */
+
+       return status;
+}
+
+
+/*
+  trans2 mkdir implementation
+*/
+static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct smb_trans2 *trans)
+{
+       union smb_mkdir *io;
+       NTSTATUS status;
+
+       /* make sure we got enough parameters */
+       if (trans->in.params.length < 5) {
+               return NT_STATUS_FOOBAR;
+       }
+
+       io = talloc_p(req, union smb_mkdir);
+       if (io == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       io->t2mkdir.level = RAW_MKDIR_T2MKDIR;
+       trans2_pull_blob_string(req, &trans->in.params, 4, &io->t2mkdir.in.path, 0);
+
+       status = ea_pull_list(&trans->in.data, io, 
+                             &io->t2mkdir.in.num_eas, 
+                             &io->t2mkdir.in.eas);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       status = ntvfs_mkdir(req, io);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       trans2_setup_reply(req, trans, 2, 0, 0);
+
+       SSVAL(trans->out.params.data, VWV(0), 0);
+
+       return status;
+}
+
 /*
   fill in the reply from a qpathinfo or qfileinfo call
 */
@@ -410,11 +512,13 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
                                     union smb_fileinfo *st)
 {
        uint_t i;
+       uint32_t list_size;
        
        switch (st->generic.level) {
        case RAW_FILEINFO_GENERIC:
        case RAW_FILEINFO_GETATTR:
        case RAW_FILEINFO_GETATTRE:
+       case RAW_FILEINFO_SEC_DESC:
                /* handled elsewhere */
                return NT_STATUS_INVALID_LEVEL;
 
@@ -510,18 +614,12 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
                return NT_STATUS_OK;
 
        case RAW_FILEINFO_ALL_EAS:
-               if (st->all_eas.out.num_eas == 0) {
-                       trans2_setup_reply(req, trans, 2, 4, 0);
-                       SSVAL(trans->out.params.data, 0, 0);
-                       SIVAL(trans->out.data.data,  0, 0);
-               } else {
-                       uint32_t list_size = ea_list_size(st->all_eas.out.num_eas,
+               list_size = ea_list_size(st->all_eas.out.num_eas,
                                                        st->all_eas.out.eas);
                        trans2_setup_reply(req, trans, 2, list_size, 0);
                        SSVAL(trans->out.params.data, 0, 0);
                        ea_put_list(trans->out.data.data, 
                                    st->all_eas.out.num_eas, st->all_eas.out.eas);
-               }
                return NT_STATUS_OK;
 
        case RAW_FILEINFO_ACCESS_INFORMATION:
@@ -604,7 +702,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
 
                for (i=0;i<st->stream_info.out.num_streams;i++) {
                        uint16_t data_size = trans->out.data.length;
-                       char *data;
+                       uint8_t *data;
 
                        trans2_grow_data(req, trans, data_size + 24);
                        data = trans->out.data.data + data_size;
@@ -716,6 +814,7 @@ static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req,
        case RAW_SFILEINFO_GENERIC:
        case RAW_SFILEINFO_SETATTR:
        case RAW_SFILEINFO_SETATTRE:
+       case RAW_SFILEINFO_SEC_DESC:
                /* handled elsewhere */
                return NT_STATUS_INVALID_LEVEL;
 
@@ -894,7 +993,7 @@ static void find_fill_info(struct smbsrv_request *req,
                           struct find_state *state,
                           union smb_search_data *file)
 {
-       char *data;
+       uint8_t *data;
        uint_t ofs = trans->out.data.length;
 
        switch (state->level) {
@@ -1094,7 +1193,7 @@ static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct smb_trans2 *
        union smb_search_first search;
        NTSTATUS status;
        uint16_t level;
-       char *param;
+       uint8_t *param;
        struct find_state state;
 
        /* make sure we got all the parameters */
@@ -1155,7 +1254,7 @@ static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct smb_trans2 *t
        union smb_search_next search;
        NTSTATUS status;
        uint16_t level;
-       char *param;
+       uint8_t *param;
        struct find_state state;
 
        /* make sure we got all the parameters */
@@ -1240,6 +1339,10 @@ static NTSTATUS trans2_backend(struct smbsrv_request *req, struct smb_trans2 *tr
                return trans2_setpathinfo(req, trans);
        case TRANSACT2_QFSINFO:
                return trans2_qfsinfo(req, trans);
+       case TRANSACT2_OPEN:
+               return trans2_open(req, trans);
+       case TRANSACT2_MKDIR:
+               return trans2_mkdir(req, trans);
        }
 
        /* an unknown trans2 command */
@@ -1257,7 +1360,7 @@ void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
        uint16_t param_count, data_count;
        uint16_t params_left, data_left;
        uint16_t param_total, data_total;
-       char *params, *data;
+       uint8_t *params, *data;
        NTSTATUS status;
 
        /* parse request */
@@ -1285,7 +1388,7 @@ void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
        }
 
        /* parse out the setup words */
-       trans.in.setup = talloc(req, trans.in.setup_count * sizeof(uint16_t));
+       trans.in.setup = talloc_array_p(req, uint16_t, trans.in.setup_count);
        if (trans.in.setup_count && !trans.in.setup) {
                req_reply_error(req, NT_STATUS_NO_MEMORY);
                return;