diff options
-rw-r--r-- | source4/ntvfs/ntvfs_generic.c | 109 | ||||
-rw-r--r-- | source4/smb_server/reply.c | 6 |
2 files changed, 96 insertions, 19 deletions
diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index 274d5caa87..ed41b3d4d2 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -144,6 +144,11 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req, union smb_open *io2, NTSTATUS status) { + time_t write_time = 0; + uint32_t set_size = 0; + union smb_setfileinfo *sf; + uint_t state; + if (!NT_STATUS_IS_OK(status)) { return status; } @@ -171,32 +176,56 @@ static NTSTATUS ntvfs_map_open_finish(struct smbsrv_request *req, /* we need to extend the file to the requested size if it was newly created */ - if (io2->generic.out.create_action == NTCREATEX_ACTION_CREATED && - io->openx.in.size != 0) { - union smb_setfileinfo *sf; - uint_t state; + if (io2->generic.out.create_action == NTCREATEX_ACTION_CREATED) { + set_size = io->openx.in.size; + } + break; - /* doing this secondary request async is more - trouble than its worth */ - state = req->async_states->state; - req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC; + case RAW_OPEN_MKNEW: + case RAW_OPEN_CREATE: + io->mknew.out.fnum = io2->generic.out.fnum; + write_time = io->mknew.in.write_time; + break; - sf = talloc_p(req, union smb_setfileinfo); - sf->generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; - sf->generic.file.fnum = io2->generic.out.fnum; - sf->end_of_file_info.in.size = io->openx.in.size; - status = ntvfs->ops->setfileinfo(ntvfs, req, sf); - if (NT_STATUS_IS_OK(status)) { - io->openx.out.size = io->openx.in.size; - } - req->async_states->state = state; - } + case RAW_OPEN_CTEMP: + io->ctemp.out.fnum = io2->generic.out.fnum; + io->ctemp.out.name = talloc_strdup(req, io2->generic.in.fname + + strlen(io->ctemp.in.directory) + 1); + write_time = io->ctemp.in.write_time; break; default: return NT_STATUS_INVALID_LEVEL; } + /* doing a secondary request async is more trouble than its + worth */ + state = req->async_states->state; + req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC; + + if (write_time != 0) { + sf = talloc_p(req, union smb_setfileinfo); + sf->generic.level = RAW_SFILEINFO_STANDARD; + sf->generic.file.fnum = io2->generic.out.fnum; + sf->standard.in.create_time = 0; + sf->standard.in.write_time = write_time; + sf->standard.in.access_time = 0; + status = ntvfs->ops->setfileinfo(ntvfs, req, sf); + } + + if (set_size != 0) { + sf = talloc_p(req, union smb_setfileinfo); + sf->generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; + sf->generic.file.fnum = io2->generic.out.fnum; + sf->end_of_file_info.in.size = io->openx.in.size; + status = ntvfs->ops->setfileinfo(ntvfs, req, sf); + if (NT_STATUS_IS_OK(status)) { + io->openx.out.size = io->openx.in.size; + } + } + + req->async_states->state = state; + return NT_STATUS_OK; } @@ -386,6 +415,50 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io, status = ntvfs->ops->openfile(ntvfs, req, io2); break; + + case RAW_OPEN_MKNEW: + io2->generic.in.file_attr = io->mknew.in.attrib; + io2->generic.in.fname = io->mknew.in.fname; + io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE; + io2->generic.in.access_mask = + GENERIC_RIGHTS_FILE_READ | + GENERIC_RIGHTS_FILE_WRITE; + io2->generic.in.share_access = + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + status = ntvfs->ops->openfile(ntvfs, req, io2); + break; + + case RAW_OPEN_CREATE: + io2->generic.in.file_attr = io->mknew.in.attrib; + io2->generic.in.fname = io->mknew.in.fname; + io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF; + io2->generic.in.access_mask = + GENERIC_RIGHTS_FILE_READ | + GENERIC_RIGHTS_FILE_WRITE; + io2->generic.in.share_access = + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + status = ntvfs->ops->openfile(ntvfs, req, io2); + break; + + case RAW_OPEN_CTEMP: + io2->generic.in.file_attr = io->ctemp.in.attrib; + io2->generic.in.file_attr = 0; + io2->generic.in.fname = + talloc_asprintf(io2, "%s\\SRV%s", + io->ctemp.in.directory, + generate_random_str_list(io2, 5, "0123456789")); + io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE; + io2->generic.in.access_mask = + GENERIC_RIGHTS_FILE_READ | + GENERIC_RIGHTS_FILE_WRITE; + io2->generic.in.share_access = + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + status = ntvfs->ops->openfile(ntvfs, req, io2); + break; + default: status = NT_STATUS_INVALID_LEVEL; break; diff --git a/source4/smb_server/reply.c b/source4/smb_server/reply.c index 8fd97df44a..b0e5e8a8d8 100644 --- a/source4/smb_server/reply.c +++ b/source4/smb_server/reply.c @@ -556,7 +556,11 @@ void reply_mknew(struct smbsrv_request *req) REQ_CHECK_WCT(req, 3); REQ_TALLOC(oi, sizeof(*oi)); - oi->mknew.level = RAW_OPEN_MKNEW; + if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) { + oi->mknew.level = RAW_OPEN_MKNEW; + } else { + oi->mknew.level = RAW_OPEN_CREATE; + } oi->mknew.in.attrib = SVAL(req->in.vwv, VWV(0)); oi->mknew.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1)); |