2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 static char *store_file_unix_basic(connection_struct *conn,
40 const SMB_STRUCT_STAT *psbuf);
42 static char *store_file_unix_basic_info2(connection_struct *conn,
45 const SMB_STRUCT_STAT *psbuf);
47 /********************************************************************
48 Roundup a value to the nearest allocation roundup size boundary.
49 Only do this for Windows clients.
50 ********************************************************************/
52 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
54 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
56 /* Only roundup for Windows clients. */
57 enum remote_arch_types ra_type = get_remote_arch();
58 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
59 val = SMB_ROUNDUP(val,rval);
64 /********************************************************************
65 Given a stat buffer return the allocated size on disk, taking into
67 ********************************************************************/
69 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
73 if(S_ISDIR(sbuf->st_mode)) {
77 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
78 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
83 if (fsp && fsp->initial_allocation_size)
84 ret = MAX(ret,fsp->initial_allocation_size);
86 return smb_roundup(conn, ret);
89 /****************************************************************************
90 Utility functions for dealing with extended attributes.
91 ****************************************************************************/
93 /****************************************************************************
94 Refuse to allow clients to overwrite our private xattrs.
95 ****************************************************************************/
97 static BOOL samba_private_attr_name(const char *unix_ea_name)
99 static const char *prohibited_ea_names[] = {
100 SAMBA_POSIX_INHERITANCE_EA_NAME,
101 SAMBA_XATTR_DOS_ATTRIB,
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
114 /****************************************************************************
115 Get one EA value. Fill in a struct ea_struct.
116 ****************************************************************************/
118 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
119 const char *fname, char *ea_name, struct ea_struct *pea)
121 /* Get the value of this xattr. Max size is 64k. */
122 size_t attr_size = 256;
128 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 if (fsp && fsp->fh->fd != -1) {
134 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
139 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
148 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
149 dump_data(10, (uint8 *)val, sizeret);
152 if (strnequal(ea_name, "user.", 5)) {
153 pea->name = &ea_name[5];
157 pea->value.data = (unsigned char *)val;
158 pea->value.length = (size_t)sizeret;
162 /****************************************************************************
163 Return a linked list of the total EA's. Plus the total size
164 ****************************************************************************/
166 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
167 const char *fname, size_t *pea_total_len)
169 /* Get a list of all xattrs. Max namesize is 64k. */
170 size_t ea_namelist_size = 1024;
175 struct ea_list *ea_list_head = NULL;
179 if (!lp_ea_support(SNUM(conn))) {
183 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
184 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
190 if (fsp && fsp->fh->fd != -1) {
191 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
196 if (sizeret == -1 && errno == ERANGE) {
197 ea_namelist_size *= 2;
206 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
209 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
210 struct ea_list *listp;
212 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
215 listp = TALLOC_P(mem_ctx, struct ea_list);
219 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
225 push_ascii_fstring(dos_ea_name, listp->ea.name);
226 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
227 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
228 (unsigned int)*pea_total_len, dos_ea_name,
229 (unsigned int)listp->ea.value.length ));
231 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
233 /* Add on 4 for total length. */
234 if (*pea_total_len) {
239 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
243 /****************************************************************************
244 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246 ****************************************************************************/
248 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
249 connection_struct *conn, struct ea_list *ea_list)
251 unsigned int ret_data_size = 4;
254 SMB_ASSERT(total_data_size >= 4);
256 if (!lp_ea_support(SNUM(conn))) {
261 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
264 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
265 dos_namelen = strlen(dos_ea_name);
266 if (dos_namelen > 255 || dos_namelen == 0) {
269 if (ea_list->ea.value.length > 65535) {
272 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
276 /* We know we have room. */
277 SCVAL(p,0,ea_list->ea.flags);
278 SCVAL(p,1,dos_namelen);
279 SSVAL(p,2,ea_list->ea.value.length);
280 fstrcpy(p+4, dos_ea_name);
281 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
283 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
284 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
287 ret_data_size = PTR_DIFF(p, pdata);
288 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
289 SIVAL(pdata,0,ret_data_size);
290 return ret_data_size;
293 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
295 size_t total_ea_len = 0;
296 TALLOC_CTX *mem_ctx = NULL;
298 if (!lp_ea_support(SNUM(conn))) {
301 mem_ctx = talloc_init("estimate_ea_size");
302 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
303 talloc_destroy(mem_ctx);
307 /****************************************************************************
308 Ensure the EA name is case insensitive by matching any existing EA name.
309 ****************************************************************************/
311 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
314 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
315 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
317 for (; ea_list; ea_list = ea_list->next) {
318 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
319 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
320 &unix_ea_name[5], ea_list->ea.name));
321 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
325 talloc_destroy(mem_ctx);
328 /****************************************************************************
329 Set or delete an extended attribute.
330 ****************************************************************************/
332 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
334 if (!lp_ea_support(SNUM(conn))) {
335 return NT_STATUS_EAS_NOT_SUPPORTED;
338 for (;ea_list; ea_list = ea_list->next) {
340 fstring unix_ea_name;
342 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
343 fstrcat(unix_ea_name, ea_list->ea.name);
345 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
347 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
349 if (samba_private_attr_name(unix_ea_name)) {
350 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
351 return NT_STATUS_ACCESS_DENIED;
354 if (ea_list->ea.value.length == 0) {
355 /* Remove the attribute. */
356 if (fsp && (fsp->fh->fd != -1)) {
357 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
358 unix_ea_name, fsp->fsp_name));
359 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
362 unix_ea_name, fname));
363 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 /* Removing a non existent attribute always succeeds. */
367 if (ret == -1 && errno == ENOATTR) {
368 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
374 if (fsp && (fsp->fh->fd != -1)) {
375 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
376 unix_ea_name, fsp->fsp_name));
377 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
378 ea_list->ea.value.data, ea_list->ea.value.length, 0);
380 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
381 unix_ea_name, fname));
382 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
383 ea_list->ea.value.data, ea_list->ea.value.length, 0);
389 if (errno == ENOTSUP) {
390 return NT_STATUS_EAS_NOT_SUPPORTED;
393 return map_nt_error_from_unix(errno);
399 /****************************************************************************
400 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
401 ****************************************************************************/
403 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
405 struct ea_list *ea_list_head = NULL;
408 while (offset + 2 < data_size) {
409 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
410 unsigned int namelen = CVAL(pdata,offset);
412 offset++; /* Go past the namelen byte. */
414 /* integer wrap paranioa. */
415 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
416 (offset > data_size) || (namelen > data_size) ||
417 (offset + namelen >= data_size)) {
420 /* Ensure the name is null terminated. */
421 if (pdata[offset + namelen] != '\0') {
424 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
429 offset += (namelen + 1); /* Go past the name + terminating zero. */
430 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
431 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
437 /****************************************************************************
438 Read one EA list entry from the buffer.
439 ****************************************************************************/
441 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
443 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 unsigned int namelen;
455 eal->ea.flags = CVAL(pdata,0);
456 namelen = CVAL(pdata,1);
457 val_len = SVAL(pdata,2);
459 if (4 + namelen + 1 + val_len > data_size) {
463 /* Ensure the name is null terminated. */
464 if (pdata[namelen + 4] != '\0') {
467 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
472 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
473 if (!eal->ea.value.data) {
477 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
479 /* Ensure we're null terminated just in case we print the value. */
480 eal->ea.value.data[val_len] = '\0';
481 /* But don't count the null. */
482 eal->ea.value.length--;
485 *pbytes_used = 4 + namelen + 1 + val_len;
488 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
489 dump_data(10, eal->ea.value.data, eal->ea.value.length);
494 /****************************************************************************
495 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
496 ****************************************************************************/
498 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
500 struct ea_list *ea_list_head = NULL;
502 size_t bytes_used = 0;
504 while (offset < data_size) {
505 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
511 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
512 offset += bytes_used;
518 /****************************************************************************
519 Count the total EA size needed.
520 ****************************************************************************/
522 static size_t ea_list_size(struct ea_list *ealist)
525 struct ea_list *listp;
528 for (listp = ealist; listp; listp = listp->next) {
529 push_ascii_fstring(dos_ea_name, listp->ea.name);
530 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
532 /* Add on 4 for total length. */
540 /****************************************************************************
541 Return a union of EA's from a file list and a list of names.
542 The TALLOC context for the two lists *MUST* be identical as we steal
543 memory from one list to add to another. JRA.
544 ****************************************************************************/
546 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
548 struct ea_list *nlistp, *flistp;
550 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
551 for (flistp = file_list; flistp; flistp = flistp->next) {
552 if (strequal(nlistp->ea.name, flistp->ea.name)) {
558 /* Copy the data from this entry. */
559 nlistp->ea.flags = flistp->ea.flags;
560 nlistp->ea.value = flistp->ea.value;
563 nlistp->ea.flags = 0;
564 ZERO_STRUCT(nlistp->ea.value);
568 *total_ea_len = ea_list_size(name_list);
572 /****************************************************************************
573 Send the required number of replies back.
574 We assume all fields other than the data fields are
575 set correctly for the type of call.
576 HACK ! Always assumes smb_setup field is zero.
577 ****************************************************************************/
579 int send_trans2_replies(const char *inbuf,
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(inbuf,outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(inbuf, outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
738 static void send_trans2_replies_new(struct smb_request *req,
745 char *inbuf, *outbuf;
748 if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) {
749 reply_nterror(req, NT_STATUS_NO_MEMORY);
753 reply_post_legacy(req, send_trans2_replies(
754 inbuf, outbuf, bufsize,
760 /****************************************************************************
761 Reply to a TRANSACT2_OPEN.
762 ****************************************************************************/
764 static void call_trans2open(connection_struct *conn,
765 struct smb_request *req,
766 char **pparams, int total_params,
767 char **ppdata, int total_data,
768 unsigned int max_data_bytes)
770 char *params = *pparams;
771 char *pdata = *ppdata;
776 BOOL return_additional_info;
787 SMB_STRUCT_STAT sbuf;
790 struct ea_list *ea_list = NULL;
795 uint32 create_disposition;
796 uint32 create_options = 0;
799 * Ensure we have enough parameters to perform the operation.
802 if (total_params < 29) {
803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
807 flags = SVAL(params, 0);
808 deny_mode = SVAL(params, 2);
809 open_attr = SVAL(params,6);
810 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
811 if (oplock_request) {
812 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
816 return_additional_info = BITSETW(params,0);
817 open_sattr = SVAL(params, 4);
818 open_time = make_unix_date3(params+8);
820 open_ofun = SVAL(params,12);
821 open_size = IVAL(params,14);
825 reply_doserror(req, ERRSRV, ERRaccess);
829 srvstr_get_path(params, req->flags2, fname, pname,
830 sizeof(fname), total_params - 28, STR_TERMINATE,
832 if (!NT_STATUS_IS_OK(status)) {
833 reply_nterror(req, status);
837 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
838 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
839 (unsigned int)open_ofun, open_size));
841 /* XXXX we need to handle passed times, sattr and flags */
843 status = unix_convert(conn, fname, False, NULL, &sbuf);
844 if (!NT_STATUS_IS_OK(status)) {
845 reply_nterror(req, status);
849 status = check_name(conn, fname);
850 if (!NT_STATUS_IS_OK(status)) {
851 reply_nterror(req, status);
855 if (open_ofun == 0) {
856 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
860 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
865 reply_doserror(req, ERRDOS, ERRbadaccess);
869 /* Any data in this call is an EA list. */
870 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
871 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
875 if (total_data != 4) {
876 if (total_data < 10) {
877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
881 if (IVAL(pdata,0) > total_data) {
882 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
883 IVAL(pdata,0), (unsigned int)total_data));
884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
888 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
894 } else if (IVAL(pdata,0) != 4) {
895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
899 status = open_file_ntcreate(conn, req, fname, &sbuf,
908 if (!NT_STATUS_IS_OK(status)) {
909 if (open_was_deferred(req->mid)) {
910 /* We have re-scheduled this call. */
913 reply_nterror(req, status);
917 size = get_file_size(sbuf);
918 fattr = dos_mode(conn,fname,&sbuf);
919 mtime = sbuf.st_mtime;
922 close_file(fsp,ERROR_CLOSE);
923 reply_doserror(req, ERRDOS,ERRnoaccess);
927 /* Save the requested allocation size. */
928 /* Allocate space for the file if a size hint is supplied */
929 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
930 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
931 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
932 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
933 if (fsp->is_directory) {
934 close_file(fsp,ERROR_CLOSE);
935 /* Can't set allocation size on a directory. */
936 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
939 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
940 close_file(fsp,ERROR_CLOSE);
941 reply_nterror(req, NT_STATUS_DISK_FULL);
945 /* Adjust size here to return the right size in the reply.
946 Windows does it this way. */
947 size = fsp->initial_allocation_size;
949 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
953 if (ea_list && smb_action == FILE_WAS_CREATED) {
954 status = set_ea(conn, fsp, fname, ea_list);
955 if (!NT_STATUS_IS_OK(status)) {
956 close_file(fsp,ERROR_CLOSE);
957 reply_nterror(req, status);
962 /* Realloc the size of parameters and data we will return */
963 *pparams = (char *)SMB_REALLOC(*pparams, 30);
964 if(*pparams == NULL ) {
965 reply_nterror(req, NT_STATUS_NO_MEMORY);
970 SSVAL(params,0,fsp->fnum);
971 SSVAL(params,2,fattr);
972 srv_put_dos_date2(params,4, mtime);
973 SIVAL(params,8, (uint32)size);
974 SSVAL(params,12,deny_mode);
975 SSVAL(params,14,0); /* open_type - file or directory. */
976 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
978 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
979 smb_action |= EXTENDED_OPLOCK_GRANTED;
982 SSVAL(params,18,smb_action);
985 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
987 SIVAL(params,20,inode);
988 SSVAL(params,24,0); /* Padding. */
990 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
991 SIVAL(params, 26, ea_size);
993 SIVAL(params, 26, 0);
996 /* Send the required number of replies */
997 send_trans2_replies_new(req, params, 30, *ppdata, 0, max_data_bytes);
1000 /*********************************************************
1001 Routine to check if a given string matches exactly.
1002 as a special case a mask of "." does NOT match. That
1003 is required for correct wildcard semantics
1004 Case can be significant or not.
1005 **********************************************************/
1007 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
1009 if (mask[0] == '.' && mask[1] == 0)
1011 if (conn->case_sensitive)
1012 return strcmp(str,mask)==0;
1013 if (StrCaseCmp(str,mask) != 0) {
1016 if (dptr_has_wild(conn->dirptr)) {
1022 /****************************************************************************
1023 Return the filetype for UNIX extensions.
1024 ****************************************************************************/
1026 static uint32 unix_filetype(mode_t mode)
1029 return UNIX_TYPE_FILE;
1030 else if(S_ISDIR(mode))
1031 return UNIX_TYPE_DIR;
1033 else if(S_ISLNK(mode))
1034 return UNIX_TYPE_SYMLINK;
1037 else if(S_ISCHR(mode))
1038 return UNIX_TYPE_CHARDEV;
1041 else if(S_ISBLK(mode))
1042 return UNIX_TYPE_BLKDEV;
1045 else if(S_ISFIFO(mode))
1046 return UNIX_TYPE_FIFO;
1049 else if(S_ISSOCK(mode))
1050 return UNIX_TYPE_SOCKET;
1053 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1054 return UNIX_TYPE_UNKNOWN;
1057 /****************************************************************************
1058 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1059 ****************************************************************************/
1061 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1063 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1064 SMB_STRUCT_STAT *psbuf,
1066 enum perm_type ptype,
1071 if (perms == SMB_MODE_NO_CHANGE) {
1072 if (!VALID_STAT(*psbuf)) {
1073 return NT_STATUS_INVALID_PARAMETER;
1075 *ret_perms = psbuf->st_mode;
1076 return NT_STATUS_OK;
1080 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1081 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1082 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1083 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1084 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1085 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1086 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1087 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1088 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1090 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1093 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1096 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1101 /* Apply mode mask */
1102 ret &= lp_create_mask(SNUM(conn));
1103 /* Add in force bits */
1104 ret |= lp_force_create_mode(SNUM(conn));
1107 ret &= lp_dir_mask(SNUM(conn));
1108 /* Add in force bits */
1109 ret |= lp_force_dir_mode(SNUM(conn));
1111 case PERM_EXISTING_FILE:
1112 /* Apply mode mask */
1113 ret &= lp_security_mask(SNUM(conn));
1114 /* Add in force bits */
1115 ret |= lp_force_security_mode(SNUM(conn));
1117 case PERM_EXISTING_DIR:
1118 /* Apply mode mask */
1119 ret &= lp_dir_security_mask(SNUM(conn));
1120 /* Add in force bits */
1121 ret |= lp_force_dir_security_mode(SNUM(conn));
1126 return NT_STATUS_OK;
1129 /****************************************************************************
1130 Get a level dependent lanman2 dir entry.
1131 ****************************************************************************/
1133 static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
1134 char *path_mask,uint32 dirtype,int info_level,
1135 int requires_resume_key,
1136 BOOL dont_descend,char **ppdata,
1137 char *base_data, char *end_data,
1138 int space_remaining,
1139 BOOL *out_of_space, BOOL *got_exact_match,
1140 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1144 SMB_STRUCT_STAT sbuf;
1148 char *p, *q, *pdata = *ppdata;
1152 SMB_OFF_T file_size = 0;
1153 SMB_BIG_UINT allocation_size = 0;
1155 struct timespec mdate_ts, adate_ts, create_date_ts;
1156 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1158 char *last_entry_ptr;
1160 uint32 nt_extmode; /* Used for NT connections instead of mode */
1161 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1162 BOOL check_mangled_names = lp_manglednames(conn->params);
1165 *out_of_space = False;
1166 *got_exact_match = False;
1168 ZERO_STRUCT(mdate_ts);
1169 ZERO_STRUCT(adate_ts);
1170 ZERO_STRUCT(create_date_ts);
1175 p = strrchr_m(path_mask,'/');
1178 pstrcpy(mask,"*.*");
1182 pstrcpy(mask, path_mask);
1187 BOOL ms_dfs_link = False;
1189 /* Needed if we run out of space */
1190 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1191 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1194 * Due to bugs in NT client redirectors we are not using
1195 * resume keys any more - set them to zero.
1196 * Check out the related comments in findfirst/findnext.
1202 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1203 (long)conn->dirptr,curr_dirpos));
1210 * fname may get mangled, dname is never mangled.
1211 * Whenever we're accessing the filesystem we use
1212 * pathreal which is composed from dname.
1215 pstrcpy(fname,dname);
1217 /* This will mangle fname if it's an illegal name. */
1218 mangle_map(fname,False,True,conn->params);
1220 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1221 got_match = mask_match(fname, mask, conn->case_sensitive);
1224 if(!got_match && check_mangled_names &&
1225 !mangle_is_8_3(fname, False, conn->params)) {
1226 pstring mangled_name;
1229 * It turns out that NT matches wildcards against
1230 * both long *and* short names. This may explain some
1231 * of the wildcard wierdness from old DOS clients
1232 * that some people have been seeing.... JRA.
1235 pstrcpy(mangled_name, fname);
1237 /* Force the mangling into 8.3. */
1238 mangle_map( mangled_name, True, False, conn->params);
1239 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1240 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1245 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1246 if (dont_descend && !isdots) {
1250 pstrcpy(pathreal,conn->dirpath);
1252 pstrcat(pathreal,"/");
1254 pstrcat(pathreal,dname);
1256 if (INFO_LEVEL_IS_UNIX(info_level)) {
1257 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1258 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1259 pathreal,strerror(errno)));
1262 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1263 pstring link_target;
1265 /* Needed to show the msdfs symlinks as
1268 if(lp_host_msdfs() &&
1269 lp_msdfs_root(SNUM(conn)) &&
1270 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1271 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1274 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1278 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1279 pathreal,strerror(errno)));
1285 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1287 mode = dos_mode(conn,pathreal,&sbuf);
1290 if (!dir_check_ftype(conn,mode,dirtype)) {
1291 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1295 if (!(mode & aDIR)) {
1296 file_size = get_file_size(sbuf);
1298 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1300 mdate_ts = get_mtimespec(&sbuf);
1301 adate_ts = get_atimespec(&sbuf);
1302 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1304 if (lp_dos_filetime_resolution(SNUM(conn))) {
1305 dos_filetime_timespec(&create_date_ts);
1306 dos_filetime_timespec(&mdate_ts);
1307 dos_filetime_timespec(&adate_ts);
1310 create_date = convert_timespec_to_time_t(create_date_ts);
1311 mdate = convert_timespec_to_time_t(mdate_ts);
1312 adate = convert_timespec_to_time_t(adate_ts);
1314 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1318 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1325 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1327 switch (info_level) {
1328 case SMB_FIND_INFO_STANDARD:
1329 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1330 if(requires_resume_key) {
1334 srv_put_dos_date2(p,0,create_date);
1335 srv_put_dos_date2(p,4,adate);
1336 srv_put_dos_date2(p,8,mdate);
1337 SIVAL(p,12,(uint32)file_size);
1338 SIVAL(p,16,(uint32)allocation_size);
1342 p += align_string(pdata, p, 0);
1343 len = srvstr_push(base_data, flags2, p,
1344 fname, PTR_DIFF(end_data, p),
1346 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1348 SCVAL(nameptr, -1, len - 2);
1350 SCVAL(nameptr, -1, 0);
1354 SCVAL(nameptr, -1, len - 1);
1356 SCVAL(nameptr, -1, 0);
1362 case SMB_FIND_EA_SIZE:
1363 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1364 if(requires_resume_key) {
1368 srv_put_dos_date2(p,0,create_date);
1369 srv_put_dos_date2(p,4,adate);
1370 srv_put_dos_date2(p,8,mdate);
1371 SIVAL(p,12,(uint32)file_size);
1372 SIVAL(p,16,(uint32)allocation_size);
1375 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1376 SIVAL(p,22,ea_size); /* Extended attributes */
1380 len = srvstr_push(base_data, flags2,
1381 p, fname, PTR_DIFF(end_data, p),
1382 STR_TERMINATE | STR_NOALIGN);
1383 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1396 SCVAL(nameptr,0,len);
1398 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1401 case SMB_FIND_EA_LIST:
1403 struct ea_list *file_list = NULL;
1406 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1410 if(requires_resume_key) {
1414 srv_put_dos_date2(p,0,create_date);
1415 srv_put_dos_date2(p,4,adate);
1416 srv_put_dos_date2(p,8,mdate);
1417 SIVAL(p,12,(uint32)file_size);
1418 SIVAL(p,16,(uint32)allocation_size);
1420 p += 22; /* p now points to the EA area. */
1422 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1423 name_list = ea_list_union(name_list, file_list, &ea_len);
1425 /* We need to determine if this entry will fit in the space available. */
1426 /* Max string size is 255 bytes. */
1427 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1428 /* Move the dirptr back to prev_dirpos */
1429 dptr_SeekDir(conn->dirptr, prev_dirpos);
1430 *out_of_space = True;
1431 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1432 return False; /* Not finished - just out of space */
1435 /* Push the ea_data followed by the name. */
1436 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1438 len = srvstr_push(base_data, flags2,
1439 p + 1, fname, PTR_DIFF(end_data, p),
1440 STR_TERMINATE | STR_NOALIGN);
1441 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1454 SCVAL(nameptr,0,len);
1456 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1460 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1461 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1462 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1464 SIVAL(p,0,reskey); p += 4;
1465 put_long_date_timespec(p,create_date_ts); p += 8;
1466 put_long_date_timespec(p,adate_ts); p += 8;
1467 put_long_date_timespec(p,mdate_ts); p += 8;
1468 put_long_date_timespec(p,mdate_ts); p += 8;
1469 SOFF_T(p,0,file_size); p += 8;
1470 SOFF_T(p,0,allocation_size); p += 8;
1471 SIVAL(p,0,nt_extmode); p += 4;
1472 q = p; p += 4; /* q is placeholder for name length. */
1474 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1475 SIVAL(p,0,ea_size); /* Extended attributes */
1478 /* Clear the short name buffer. This is
1479 * IMPORTANT as not doing so will trigger
1480 * a Win2k client bug. JRA.
1482 if (!was_8_3 && check_mangled_names) {
1483 pstring mangled_name;
1484 pstrcpy(mangled_name, fname);
1485 mangle_map(mangled_name,True,True,
1487 mangled_name[12] = 0;
1488 len = srvstr_push(base_data, flags2,
1489 p+2, mangled_name, 24,
1490 STR_UPPER|STR_UNICODE);
1492 memset(p + 2 + len,'\0',24 - len);
1499 len = srvstr_push(base_data, flags2, p,
1500 fname, PTR_DIFF(end_data, p),
1501 STR_TERMINATE_ASCII);
1504 SIVAL(p,0,0); /* Ensure any padding is null. */
1505 len = PTR_DIFF(p, pdata);
1506 len = (len + 3) & ~3;
1511 case SMB_FIND_FILE_DIRECTORY_INFO:
1512 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1514 SIVAL(p,0,reskey); p += 4;
1515 put_long_date_timespec(p,create_date_ts); p += 8;
1516 put_long_date_timespec(p,adate_ts); p += 8;
1517 put_long_date_timespec(p,mdate_ts); p += 8;
1518 put_long_date_timespec(p,mdate_ts); p += 8;
1519 SOFF_T(p,0,file_size); p += 8;
1520 SOFF_T(p,0,allocation_size); p += 8;
1521 SIVAL(p,0,nt_extmode); p += 4;
1522 len = srvstr_push(base_data, flags2,
1523 p + 4, fname, PTR_DIFF(end_data, p),
1524 STR_TERMINATE_ASCII);
1527 SIVAL(p,0,0); /* Ensure any padding is null. */
1528 len = PTR_DIFF(p, pdata);
1529 len = (len + 3) & ~3;
1534 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1535 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1537 SIVAL(p,0,reskey); p += 4;
1538 put_long_date_timespec(p,create_date_ts); p += 8;
1539 put_long_date_timespec(p,adate_ts); p += 8;
1540 put_long_date_timespec(p,mdate_ts); p += 8;
1541 put_long_date_timespec(p,mdate_ts); p += 8;
1542 SOFF_T(p,0,file_size); p += 8;
1543 SOFF_T(p,0,allocation_size); p += 8;
1544 SIVAL(p,0,nt_extmode); p += 4;
1545 q = p; p += 4; /* q is placeholder for name length. */
1547 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1548 SIVAL(p,0,ea_size); /* Extended attributes */
1551 len = srvstr_push(base_data, flags2, p,
1552 fname, PTR_DIFF(end_data, p),
1553 STR_TERMINATE_ASCII);
1557 SIVAL(p,0,0); /* Ensure any padding is null. */
1558 len = PTR_DIFF(p, pdata);
1559 len = (len + 3) & ~3;
1564 case SMB_FIND_FILE_NAMES_INFO:
1565 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1567 SIVAL(p,0,reskey); p += 4;
1569 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1570 acl on a dir (tridge) */
1571 len = srvstr_push(base_data, flags2, p,
1572 fname, PTR_DIFF(end_data, p),
1573 STR_TERMINATE_ASCII);
1576 SIVAL(p,0,0); /* Ensure any padding is null. */
1577 len = PTR_DIFF(p, pdata);
1578 len = (len + 3) & ~3;
1583 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1584 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1586 SIVAL(p,0,reskey); p += 4;
1587 put_long_date_timespec(p,create_date_ts); p += 8;
1588 put_long_date_timespec(p,adate_ts); p += 8;
1589 put_long_date_timespec(p,mdate_ts); p += 8;
1590 put_long_date_timespec(p,mdate_ts); p += 8;
1591 SOFF_T(p,0,file_size); p += 8;
1592 SOFF_T(p,0,allocation_size); p += 8;
1593 SIVAL(p,0,nt_extmode); p += 4;
1594 q = p; p += 4; /* q is placeholder for name length. */
1596 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1597 SIVAL(p,0,ea_size); /* Extended attributes */
1600 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1601 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1602 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1603 len = srvstr_push(base_data, flags2, p,
1604 fname, PTR_DIFF(end_data, p),
1605 STR_TERMINATE_ASCII);
1608 SIVAL(p,0,0); /* Ensure any padding is null. */
1609 len = PTR_DIFF(p, pdata);
1610 len = (len + 3) & ~3;
1615 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1616 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1617 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1619 SIVAL(p,0,reskey); p += 4;
1620 put_long_date_timespec(p,create_date_ts); p += 8;
1621 put_long_date_timespec(p,adate_ts); p += 8;
1622 put_long_date_timespec(p,mdate_ts); p += 8;
1623 put_long_date_timespec(p,mdate_ts); p += 8;
1624 SOFF_T(p,0,file_size); p += 8;
1625 SOFF_T(p,0,allocation_size); p += 8;
1626 SIVAL(p,0,nt_extmode); p += 4;
1627 q = p; p += 4; /* q is placeholder for name length */
1629 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1630 SIVAL(p,0,ea_size); /* Extended attributes */
1633 /* Clear the short name buffer. This is
1634 * IMPORTANT as not doing so will trigger
1635 * a Win2k client bug. JRA.
1637 if (!was_8_3 && check_mangled_names) {
1638 pstring mangled_name;
1639 pstrcpy(mangled_name, fname);
1640 mangle_map(mangled_name,True,True,
1642 mangled_name[12] = 0;
1643 len = srvstr_push(base_data, flags2,
1644 p+2, mangled_name, 24,
1645 STR_UPPER|STR_UNICODE);
1648 memset(p + 2 + len,'\0',24 - len);
1655 SSVAL(p,0,0); p += 2; /* Reserved ? */
1656 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1657 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1658 len = srvstr_push(base_data, flags2, p,
1659 fname, PTR_DIFF(end_data, p),
1660 STR_TERMINATE_ASCII);
1663 SIVAL(p,0,0); /* Ensure any padding is null. */
1664 len = PTR_DIFF(p, pdata);
1665 len = (len + 3) & ~3;
1670 /* CIFS UNIX Extension. */
1672 case SMB_FIND_FILE_UNIX:
1673 case SMB_FIND_FILE_UNIX_INFO2:
1675 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1677 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1679 if (info_level == SMB_FIND_FILE_UNIX) {
1680 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1681 p = store_file_unix_basic(conn, p,
1683 len = srvstr_push(base_data, flags2, p,
1684 fname, PTR_DIFF(end_data, p),
1687 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1688 p = store_file_unix_basic_info2(conn, p,
1692 len = srvstr_push(base_data, flags2, p, fname,
1693 PTR_DIFF(end_data, p), 0);
1694 SIVAL(nameptr, 0, len);
1698 SIVAL(p,0,0); /* Ensure any padding is null. */
1700 len = PTR_DIFF(p, pdata);
1701 len = (len + 3) & ~3;
1702 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1704 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1713 if (PTR_DIFF(p,pdata) > space_remaining) {
1714 /* Move the dirptr back to prev_dirpos */
1715 dptr_SeekDir(conn->dirptr, prev_dirpos);
1716 *out_of_space = True;
1717 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1718 return False; /* Not finished - just out of space */
1721 /* Setup the last entry pointer, as an offset from base_data */
1722 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1723 /* Advance the data pointer to the next slot */
1729 /****************************************************************************
1730 Reply to a TRANS2_FINDFIRST.
1731 ****************************************************************************/
1733 static void call_trans2findfirst(connection_struct *conn,
1734 struct smb_request *req,
1735 char **pparams, int total_params,
1736 char **ppdata, int total_data,
1737 unsigned int max_data_bytes)
1739 /* We must be careful here that we don't return more than the
1740 allowed number of data bytes. If this means returning fewer than
1741 maxentries then so be it. We assume that the redirector has
1742 enough room for the fixed number of parameter bytes it has
1744 char *params = *pparams;
1745 char *pdata = *ppdata;
1749 uint16 findfirst_flags;
1750 BOOL close_after_first;
1752 BOOL requires_resume_key;
1757 int last_entry_off=0;
1761 BOOL finished = False;
1762 BOOL dont_descend = False;
1763 BOOL out_of_space = False;
1764 int space_remaining;
1765 BOOL mask_contains_wcard = False;
1766 SMB_STRUCT_STAT sbuf;
1767 TALLOC_CTX *ea_ctx = NULL;
1768 struct ea_list *ea_list = NULL;
1769 NTSTATUS ntstatus = NT_STATUS_OK;
1771 if (total_params < 13) {
1772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1776 dirtype = SVAL(params,0);
1777 maxentries = SVAL(params,2);
1778 findfirst_flags = SVAL(params,4);
1779 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1780 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1781 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1782 info_level = SVAL(params,6);
1784 *directory = *mask = 0;
1786 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1787 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1788 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1789 info_level, max_data_bytes));
1792 /* W2K3 seems to treat zero as 1. */
1796 switch (info_level) {
1797 case SMB_FIND_INFO_STANDARD:
1798 case SMB_FIND_EA_SIZE:
1799 case SMB_FIND_EA_LIST:
1800 case SMB_FIND_FILE_DIRECTORY_INFO:
1801 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1802 case SMB_FIND_FILE_NAMES_INFO:
1803 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1804 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1805 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1807 case SMB_FIND_FILE_UNIX:
1808 case SMB_FIND_FILE_UNIX_INFO2:
1809 if (!lp_unix_extensions()) {
1810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1815 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1819 srvstr_get_path_wcard(params, req->flags2, directory,
1820 params+12, sizeof(directory), total_params - 12,
1821 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1822 if (!NT_STATUS_IS_OK(ntstatus)) {
1823 reply_nterror(req, ntstatus);
1827 ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1828 if (!NT_STATUS_IS_OK(ntstatus)) {
1829 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1830 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1831 ERRSRV, ERRbadpath);
1834 reply_nterror(req, ntstatus);
1838 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1839 if (!NT_STATUS_IS_OK(ntstatus)) {
1840 reply_nterror(req, ntstatus);
1843 ntstatus = check_name(conn, directory);
1844 if (!NT_STATUS_IS_OK(ntstatus)) {
1845 reply_nterror(req, ntstatus);
1849 p = strrchr_m(directory,'/');
1851 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1852 if((directory[0] == '.') && (directory[1] == '\0')) {
1854 mask_contains_wcard = True;
1856 pstrcpy(mask,directory);
1858 pstrcpy(directory,"./");
1864 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1866 if (info_level == SMB_FIND_EA_LIST) {
1869 if (total_data < 4) {
1870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1874 ea_size = IVAL(pdata,0);
1875 if (ea_size != total_data) {
1876 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1877 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1882 if (!lp_ea_support(SNUM(conn))) {
1883 reply_doserror(req, ERRDOS, ERReasnotsupported);
1887 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1888 reply_nterror(req, NT_STATUS_NO_MEMORY);
1892 /* Pull out the list of names. */
1893 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1895 talloc_destroy(ea_ctx);
1896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1901 *ppdata = (char *)SMB_REALLOC(
1902 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1903 if(*ppdata == NULL ) {
1904 talloc_destroy(ea_ctx);
1905 reply_nterror(req, NT_STATUS_NO_MEMORY);
1909 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1911 /* Realloc the params space */
1912 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1913 if (*pparams == NULL) {
1914 talloc_destroy(ea_ctx);
1915 reply_nterror(req, NT_STATUS_NO_MEMORY);
1920 /* Save the wildcard match and attribs we are using on this directory -
1921 needed as lanman2 assumes these are being saved between calls */
1923 ntstatus = dptr_create(conn,
1929 mask_contains_wcard,
1933 if (!NT_STATUS_IS_OK(ntstatus)) {
1934 talloc_destroy(ea_ctx);
1935 reply_nterror(req, ntstatus);
1939 dptr_num = dptr_dnum(conn->dirptr);
1940 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1942 /* We don't need to check for VOL here as this is returned by
1943 a different TRANS2 call. */
1945 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1946 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1947 dont_descend = True;
1950 space_remaining = max_data_bytes;
1951 out_of_space = False;
1953 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1954 BOOL got_exact_match = False;
1956 /* this is a heuristic to avoid seeking the dirptr except when
1957 absolutely necessary. It allows for a filename of about 40 chars */
1958 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1959 out_of_space = True;
1962 finished = !get_lanman2_dir_entry(conn,
1964 mask,dirtype,info_level,
1965 requires_resume_key,dont_descend,
1967 space_remaining, &out_of_space,
1969 &last_entry_off, ea_list, ea_ctx);
1972 if (finished && out_of_space)
1975 if (!finished && !out_of_space)
1979 * As an optimisation if we know we aren't looking
1980 * for a wildcard name (ie. the name matches the wildcard exactly)
1981 * then we can finish on any (first) match.
1982 * This speeds up large directory searches. JRA.
1988 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1991 talloc_destroy(ea_ctx);
1993 /* Check if we can close the dirptr */
1994 if(close_after_first || (finished && close_if_end)) {
1995 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1996 dptr_close(&dptr_num);
2000 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2001 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2002 * the protocol level is less than NT1. Tested with smbclient. JRA.
2003 * This should fix the OS/2 client bug #2335.
2006 if(numentries == 0) {
2007 dptr_close(&dptr_num);
2008 if (Protocol < PROTOCOL_NT1) {
2009 reply_doserror(req, ERRDOS, ERRnofiles);
2012 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2013 ERRDOS, ERRbadfile);
2018 /* At this point pdata points to numentries directory entries. */
2020 /* Set up the return parameter block */
2021 SSVAL(params,0,dptr_num);
2022 SSVAL(params,2,numentries);
2023 SSVAL(params,4,finished);
2024 SSVAL(params,6,0); /* Never an EA error */
2025 SSVAL(params,8,last_entry_off);
2027 send_trans2_replies_new(req, params, 10, pdata, PTR_DIFF(p,pdata),
2030 if ((! *directory) && dptr_path(dptr_num))
2031 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2033 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2034 smb_fn_name(CVAL(req->inbuf,smb_com)),
2035 mask, directory, dirtype, numentries ) );
2038 * Force a name mangle here to ensure that the
2039 * mask as an 8.3 name is top of the mangled cache.
2040 * The reasons for this are subtle. Don't remove
2041 * this code unless you know what you are doing
2042 * (see PR#13758). JRA.
2045 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
2046 mangle_map(mask, True, True, conn->params);
2051 /****************************************************************************
2052 Reply to a TRANS2_FINDNEXT.
2053 ****************************************************************************/
2055 static void call_trans2findnext(connection_struct *conn,
2056 struct smb_request *req,
2057 char **pparams, int total_params,
2058 char **ppdata, int total_data,
2059 unsigned int max_data_bytes)
2061 /* We must be careful here that we don't return more than the
2062 allowed number of data bytes. If this means returning fewer than
2063 maxentries then so be it. We assume that the redirector has
2064 enough room for the fixed number of parameter bytes it has
2066 char *params = *pparams;
2067 char *pdata = *ppdata;
2073 uint16 findnext_flags;
2074 BOOL close_after_request;
2076 BOOL requires_resume_key;
2078 BOOL mask_contains_wcard = False;
2079 pstring resume_name;
2085 int i, last_entry_off=0;
2086 BOOL finished = False;
2087 BOOL dont_descend = False;
2088 BOOL out_of_space = False;
2089 int space_remaining;
2090 TALLOC_CTX *ea_ctx = NULL;
2091 struct ea_list *ea_list = NULL;
2092 NTSTATUS ntstatus = NT_STATUS_OK;
2094 if (total_params < 13) {
2095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2099 dptr_num = SVAL(params,0);
2100 maxentries = SVAL(params,2);
2101 info_level = SVAL(params,4);
2102 resume_key = IVAL(params,6);
2103 findnext_flags = SVAL(params,10);
2104 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2105 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2106 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2107 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2109 *mask = *directory = *resume_name = 0;
2111 srvstr_get_path_wcard(params, req->flags2, resume_name,
2112 params+12, sizeof(resume_name),
2113 total_params - 12, STR_TERMINATE, &ntstatus,
2114 &mask_contains_wcard);
2115 if (!NT_STATUS_IS_OK(ntstatus)) {
2116 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2117 complain (it thinks we're asking for the directory above the shared
2118 path or an invalid name). Catch this as the resume name is only compared, never used in
2119 a file access. JRA. */
2120 srvstr_pull(params, req->flags2,
2121 resume_name, params+12,
2122 sizeof(resume_name), total_params - 12,
2125 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2126 reply_nterror(req, ntstatus);
2131 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2132 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2133 resume_key = %d resume name = %s continue=%d level = %d\n",
2134 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2135 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2138 /* W2K3 seems to treat zero as 1. */
2142 switch (info_level) {
2143 case SMB_FIND_INFO_STANDARD:
2144 case SMB_FIND_EA_SIZE:
2145 case SMB_FIND_EA_LIST:
2146 case SMB_FIND_FILE_DIRECTORY_INFO:
2147 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2148 case SMB_FIND_FILE_NAMES_INFO:
2149 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2150 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2151 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2153 case SMB_FIND_FILE_UNIX:
2154 case SMB_FIND_FILE_UNIX_INFO2:
2155 if (!lp_unix_extensions()) {
2156 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2161 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2165 if (info_level == SMB_FIND_EA_LIST) {
2168 if (total_data < 4) {
2169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2173 ea_size = IVAL(pdata,0);
2174 if (ea_size != total_data) {
2175 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2176 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2181 if (!lp_ea_support(SNUM(conn))) {
2182 reply_doserror(req, ERRDOS, ERReasnotsupported);
2186 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2191 /* Pull out the list of names. */
2192 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2194 talloc_destroy(ea_ctx);
2195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2200 *ppdata = (char *)SMB_REALLOC(
2201 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2202 if(*ppdata == NULL) {
2203 talloc_destroy(ea_ctx);
2204 reply_nterror(req, NT_STATUS_NO_MEMORY);
2209 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2211 /* Realloc the params space */
2212 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2213 if(*pparams == NULL ) {
2214 talloc_destroy(ea_ctx);
2215 reply_nterror(req, NT_STATUS_NO_MEMORY);
2221 /* Check that the dptr is valid */
2222 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2223 talloc_destroy(ea_ctx);
2224 reply_doserror(req, ERRDOS, ERRnofiles);
2228 string_set(&conn->dirpath,dptr_path(dptr_num));
2230 /* Get the wildcard mask from the dptr */
2231 if((p = dptr_wcard(dptr_num))== NULL) {
2232 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2233 talloc_destroy(ea_ctx);
2234 reply_doserror(req, ERRDOS, ERRnofiles);
2239 pstrcpy(directory,conn->dirpath);
2241 /* Get the attr mask from the dptr */
2242 dirtype = dptr_attr(dptr_num);
2244 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2245 dptr_num, mask, dirtype,
2247 dptr_TellDir(conn->dirptr)));
2249 /* We don't need to check for VOL here as this is returned by
2250 a different TRANS2 call. */
2252 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2253 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2254 dont_descend = True;
2257 space_remaining = max_data_bytes;
2258 out_of_space = False;
2261 * Seek to the correct position. We no longer use the resume key but
2262 * depend on the last file name instead.
2265 if(*resume_name && !continue_bit) {
2268 long current_pos = 0;
2270 * Remember, mangle_map is called by
2271 * get_lanman2_dir_entry(), so the resume name
2272 * could be mangled. Ensure we check the unmangled name.
2275 if (mangle_is_mangled(resume_name, conn->params)) {
2276 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2281 * Fix for NT redirector problem triggered by resume key indexes
2282 * changing between directory scans. We now return a resume key of 0
2283 * and instead look for the filename to continue from (also given
2284 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2285 * findfirst/findnext (as is usual) then the directory pointer
2286 * should already be at the correct place.
2289 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2290 } /* end if resume_name && !continue_bit */
2292 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2293 BOOL got_exact_match = False;
2295 /* this is a heuristic to avoid seeking the dirptr except when
2296 absolutely necessary. It allows for a filename of about 40 chars */
2297 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2298 out_of_space = True;
2301 finished = !get_lanman2_dir_entry(conn,
2303 mask,dirtype,info_level,
2304 requires_resume_key,dont_descend,
2306 space_remaining, &out_of_space,
2308 &last_entry_off, ea_list, ea_ctx);
2311 if (finished && out_of_space)
2314 if (!finished && !out_of_space)
2318 * As an optimisation if we know we aren't looking
2319 * for a wildcard name (ie. the name matches the wildcard exactly)
2320 * then we can finish on any (first) match.
2321 * This speeds up large directory searches. JRA.
2327 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2330 talloc_destroy(ea_ctx);
2332 /* Check if we can close the dirptr */
2333 if(close_after_request || (finished && close_if_end)) {
2334 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2335 dptr_close(&dptr_num); /* This frees up the saved mask */
2338 /* Set up the return parameter block */
2339 SSVAL(params,0,numentries);
2340 SSVAL(params,2,finished);
2341 SSVAL(params,4,0); /* Never an EA error */
2342 SSVAL(params,6,last_entry_off);
2344 send_trans2_replies_new(req, params, 8, pdata, PTR_DIFF(p,pdata),
2347 if ((! *directory) && dptr_path(dptr_num))
2348 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2350 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2351 smb_fn_name(CVAL(req->inbuf,smb_com)),
2352 mask, directory, dirtype, numentries ) );
2357 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2359 E_md4hash(lp_servicename(SNUM(conn)),objid);
2363 /****************************************************************************
2364 Reply to a TRANS2_QFSINFO (query filesystem info).
2365 ****************************************************************************/
2367 static void call_trans2qfsinfo(connection_struct *conn,
2368 struct smb_request *req,
2369 char **pparams, int total_params,
2370 char **ppdata, int total_data,
2371 unsigned int max_data_bytes)
2373 char *pdata, *end_data;
2374 char *params = *pparams;
2378 const char *vname = volume_label(SNUM(conn));
2379 int snum = SNUM(conn);
2380 char *fstype = lp_fstype(SNUM(conn));
2383 if (total_params < 2) {
2384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2388 info_level = SVAL(params,0);
2390 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2392 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2393 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2394 reply_doserror(req, ERRSRV, ERRinvdevice);
2398 *ppdata = (char *)SMB_REALLOC(
2399 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2400 if (*ppdata == NULL ) {
2401 reply_nterror(req, NT_STATUS_NO_MEMORY);
2406 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2407 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2409 switch (info_level) {
2410 case SMB_INFO_ALLOCATION:
2412 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2414 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2415 reply_unixerror(req, ERRHRD, ERRgeneral);
2419 block_size = lp_block_size(snum);
2420 if (bsize < block_size) {
2421 SMB_BIG_UINT factor = block_size/bsize;
2426 if (bsize > block_size) {
2427 SMB_BIG_UINT factor = bsize/block_size;
2432 bytes_per_sector = 512;
2433 sectors_per_unit = bsize/bytes_per_sector;
2435 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2436 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2437 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2439 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2440 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2441 SIVAL(pdata,l1_cUnit,dsize);
2442 SIVAL(pdata,l1_cUnitAvail,dfree);
2443 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2447 case SMB_INFO_VOLUME:
2448 /* Return volume name */
2450 * Add volume serial number - hash of a combination of
2451 * the called hostname and the service name.
2453 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2455 * Win2k3 and previous mess this up by sending a name length
2456 * one byte short. I believe only older clients (OS/2 Win9x) use
2457 * this call so try fixing this by adding a terminating null to
2458 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2462 pdata+l2_vol_szVolLabel, vname,
2463 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2464 STR_NOALIGN|STR_TERMINATE);
2465 SCVAL(pdata,l2_vol_cch,len);
2466 data_len = l2_vol_szVolLabel + len;
2467 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2468 (unsigned)st.st_ctime, len, vname));
2471 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2472 case SMB_FS_ATTRIBUTE_INFORMATION:
2475 #if defined(HAVE_SYS_QUOTAS)
2476 quota_flag = FILE_VOLUME_QUOTAS;
2479 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2480 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2481 FILE_SUPPORTS_OBJECT_IDS|
2482 FILE_UNICODE_ON_DISK|
2483 quota_flag); /* FS ATTRIBUTES */
2485 SIVAL(pdata,4,255); /* Max filename component length */
2486 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2487 and will think we can't do long filenames */
2488 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2489 PTR_DIFF(end_data, pdata+12),
2492 data_len = 12 + len;
2495 case SMB_QUERY_FS_LABEL_INFO:
2496 case SMB_FS_LABEL_INFORMATION:
2497 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2498 PTR_DIFF(end_data, pdata+4), 0);
2503 case SMB_QUERY_FS_VOLUME_INFO:
2504 case SMB_FS_VOLUME_INFORMATION:
2507 * Add volume serial number - hash of a combination of
2508 * the called hostname and the service name.
2510 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2511 (str_checksum(get_local_machine_name())<<16));
2513 /* Max label len is 32 characters. */
2514 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2515 PTR_DIFF(end_data, pdata+18),
2517 SIVAL(pdata,12,len);
2520 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2521 (int)strlen(vname),vname, lp_servicename(snum)));
2524 case SMB_QUERY_FS_SIZE_INFO:
2525 case SMB_FS_SIZE_INFORMATION:
2527 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2529 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2530 reply_unixerror(req, ERRHRD, ERRgeneral);
2533 block_size = lp_block_size(snum);
2534 if (bsize < block_size) {
2535 SMB_BIG_UINT factor = block_size/bsize;
2540 if (bsize > block_size) {
2541 SMB_BIG_UINT factor = bsize/block_size;
2546 bytes_per_sector = 512;
2547 sectors_per_unit = bsize/bytes_per_sector;
2548 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2549 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2550 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2551 SBIG_UINT(pdata,0,dsize);
2552 SBIG_UINT(pdata,8,dfree);
2553 SIVAL(pdata,16,sectors_per_unit);
2554 SIVAL(pdata,20,bytes_per_sector);
2558 case SMB_FS_FULL_SIZE_INFORMATION:
2560 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2562 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2563 reply_unixerror(req, ERRHRD, ERRgeneral);
2566 block_size = lp_block_size(snum);
2567 if (bsize < block_size) {
2568 SMB_BIG_UINT factor = block_size/bsize;
2573 if (bsize > block_size) {
2574 SMB_BIG_UINT factor = bsize/block_size;
2579 bytes_per_sector = 512;
2580 sectors_per_unit = bsize/bytes_per_sector;
2581 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2582 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2583 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2584 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2585 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2586 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2587 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2588 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2592 case SMB_QUERY_FS_DEVICE_INFO:
2593 case SMB_FS_DEVICE_INFORMATION:
2595 SIVAL(pdata,0,0); /* dev type */
2596 SIVAL(pdata,4,0); /* characteristics */
2599 #ifdef HAVE_SYS_QUOTAS
2600 case SMB_FS_QUOTA_INFORMATION:
2602 * what we have to send --metze:
2604 * Unknown1: 24 NULL bytes
2605 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2606 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2607 * Quota Flags: 2 byte :
2608 * Unknown3: 6 NULL bytes
2612 * details for Quota Flags:
2614 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2615 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2616 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2617 * 0x0001 Enable Quotas: enable quota for this fs
2621 /* we need to fake up a fsp here,
2622 * because its not send in this call
2625 SMB_NTQUOTA_STRUCT quotas;
2628 ZERO_STRUCT(quotas);
2634 if (current_user.ut.uid != 0) {
2635 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2636 lp_servicename(SNUM(conn)),conn->user));
2637 reply_doserror(req, ERRDOS, ERRnoaccess);
2641 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2642 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2643 reply_doserror(req, ERRSRV, ERRerror);
2649 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2651 /* Unknown1 24 NULL bytes*/
2652 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2653 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2654 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2656 /* Default Soft Quota 8 bytes */
2657 SBIG_UINT(pdata,24,quotas.softlim);
2659 /* Default Hard Quota 8 bytes */
2660 SBIG_UINT(pdata,32,quotas.hardlim);
2662 /* Quota flag 2 bytes */
2663 SSVAL(pdata,40,quotas.qflags);
2665 /* Unknown3 6 NULL bytes */
2671 #endif /* HAVE_SYS_QUOTAS */
2672 case SMB_FS_OBJECTID_INFORMATION:
2674 unsigned char objid[16];
2675 memcpy(pdata,create_volume_objectid(conn, objid),16);
2681 * Query the version and capabilities of the CIFS UNIX extensions
2685 case SMB_QUERY_CIFS_UNIX_INFO:
2686 if (!lp_unix_extensions()) {
2687 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2691 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2692 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2693 /* We have POSIX ACLs, pathname and locking capability. */
2694 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2695 CIFS_UNIX_POSIX_ACLS_CAP|
2696 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2697 CIFS_UNIX_FCNTL_LOCKS_CAP|
2698 CIFS_UNIX_EXTATTR_CAP|
2699 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2700 /* Ensure we don't do this on signed or sealed data. */
2701 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2705 case SMB_QUERY_POSIX_FS_INFO:
2708 vfs_statvfs_struct svfs;
2710 if (!lp_unix_extensions()) {
2711 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2715 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2719 SIVAL(pdata,0,svfs.OptimalTransferSize);
2720 SIVAL(pdata,4,svfs.BlockSize);
2721 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2722 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2723 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2724 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2725 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2726 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2727 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2729 } else if (rc == EOPNOTSUPP) {
2730 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2732 #endif /* EOPNOTSUPP */
2734 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2735 reply_doserror(req, ERRSRV, ERRerror);
2741 case SMB_QUERY_POSIX_WHOAMI:
2747 if (!lp_unix_extensions()) {
2748 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2752 if (max_data_bytes < 40) {
2753 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2757 /* We ARE guest if global_sid_Builtin_Guests is
2758 * in our list of SIDs.
2760 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2761 current_user.nt_user_token)) {
2762 flags |= SMB_WHOAMI_GUEST;
2765 /* We are NOT guest if global_sid_Authenticated_Users
2766 * is in our list of SIDs.
2768 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2769 current_user.nt_user_token)) {
2770 flags &= ~SMB_WHOAMI_GUEST;
2773 /* NOTE: 8 bytes for UID/GID, irrespective of native
2774 * platform size. This matches
2775 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2777 data_len = 4 /* flags */
2784 + 4 /* pad/reserved */
2785 + (current_user.ut.ngroups * 8)
2787 + (current_user.nt_user_token->num_sids *
2791 SIVAL(pdata, 0, flags);
2792 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2793 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2794 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2797 if (data_len >= max_data_bytes) {
2798 /* Potential overflow, skip the GIDs and SIDs. */
2800 SIVAL(pdata, 24, 0); /* num_groups */
2801 SIVAL(pdata, 28, 0); /* num_sids */
2802 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2803 SIVAL(pdata, 36, 0); /* reserved */
2809 SIVAL(pdata, 24, current_user.ut.ngroups);
2811 current_user.nt_user_token->num_sids);
2813 /* We walk the SID list twice, but this call is fairly
2814 * infrequent, and I don't expect that it's performance
2815 * sensitive -- jpeach
2817 for (i = 0, sid_bytes = 0;
2818 i < current_user.nt_user_token->num_sids; ++i) {
2820 sid_size(¤t_user.nt_user_token->user_sids[i]);
2823 /* SID list byte count */
2824 SIVAL(pdata, 32, sid_bytes);
2826 /* 4 bytes pad/reserved - must be zero */
2827 SIVAL(pdata, 36, 0);
2831 for (i = 0; i < current_user.ut.ngroups; ++i) {
2832 SBIG_UINT(pdata, data_len,
2833 (SMB_BIG_UINT)current_user.ut.groups[i]);
2839 i < current_user.nt_user_token->num_sids; ++i) {
2841 sid_size(¤t_user.nt_user_token->user_sids[i]);
2843 sid_linearize(pdata + data_len, sid_len,
2844 ¤t_user.nt_user_token->user_sids[i]);
2845 data_len += sid_len;
2851 case SMB_MAC_QUERY_FS_INFO:
2853 * Thursby MAC extension... ONLY on NTFS filesystems
2854 * once we do streams then we don't need this
2856 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2858 SIVAL(pdata,84,0x100); /* Don't support mac... */
2863 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2868 send_trans2_replies_new(req, params, 0, pdata, data_len,
2871 DEBUG( 4, ( "%s info_level = %d\n",
2872 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2877 /****************************************************************************
2878 Reply to a TRANS2_SETFSINFO (set filesystem info).
2879 ****************************************************************************/
2881 static void call_trans2setfsinfo(connection_struct *conn,
2882 struct smb_request *req,
2883 char **pparams, int total_params,
2884 char **ppdata, int total_data,
2885 unsigned int max_data_bytes)
2887 char *pdata = *ppdata;
2888 char *params = *pparams;
2891 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2894 if (total_params < 4) {
2895 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2901 info_level = SVAL(params,2);
2903 switch(info_level) {
2904 case SMB_SET_CIFS_UNIX_INFO:
2906 uint16 client_unix_major;
2907 uint16 client_unix_minor;
2908 uint32 client_unix_cap_low;
2909 uint32 client_unix_cap_high;
2911 if (!lp_unix_extensions()) {
2913 NT_STATUS_INVALID_LEVEL);
2917 /* There should be 12 bytes of capabilities set. */
2918 if (total_data < 8) {
2921 NT_STATUS_INVALID_PARAMETER);
2924 client_unix_major = SVAL(pdata,0);
2925 client_unix_minor = SVAL(pdata,2);
2926 client_unix_cap_low = IVAL(pdata,4);
2927 client_unix_cap_high = IVAL(pdata,8);
2928 /* Just print these values for now. */
2929 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2930 cap_low = 0x%x, cap_high = 0x%x\n",
2931 (unsigned int)client_unix_major,
2932 (unsigned int)client_unix_minor,
2933 (unsigned int)client_unix_cap_low,
2934 (unsigned int)client_unix_cap_high ));
2936 /* Here is where we must switch to posix pathname processing... */
2937 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2938 lp_set_posix_pathnames();
2939 mangle_change_to_posix();
2942 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2943 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2944 /* Client that knows how to do posix locks,
2945 * but not posix open/mkdir operations. Set a
2946 * default type for read/write checks. */
2948 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2953 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2956 size_t param_len = 0;
2957 size_t data_len = total_data;
2959 if (!lp_unix_extensions()) {
2961 req, NT_STATUS_INVALID_LEVEL);
2965 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2967 status = srv_request_encryption_setup(conn,
2968 (unsigned char **)ppdata,
2970 (unsigned char **)pparams,
2974 if (!NT_STATUS_IS_OK(status)) {
2977 * MORE_PROCESSING_REQUIRED, this used
2978 * to have special handling here.
2980 reply_nterror(req, status);
2984 send_trans2_replies_new(req,
2985 *pparams, param_len,
2989 if (NT_STATUS_IS_OK(status)) {
2990 /* Server-side transport encryption is now *on*. */
2991 status = srv_encryption_start(conn);
2992 if (!NT_STATUS_IS_OK(status)) {
2993 exit_server_cleanly("Failure in setting up encrypted transport");
2998 case SMB_FS_QUOTA_INFORMATION:
3000 files_struct *fsp = NULL;
3001 SMB_NTQUOTA_STRUCT quotas;
3003 ZERO_STRUCT(quotas);
3006 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3007 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3008 lp_servicename(SNUM(conn)),conn->user));
3009 reply_doserror(req, ERRSRV, ERRaccess);
3013 /* note: normaly there're 48 bytes,
3014 * but we didn't use the last 6 bytes for now
3017 fsp = file_fsp(SVAL(params,0));
3018 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3019 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3021 req, NT_STATUS_INVALID_HANDLE);
3025 if (total_data < 42) {
3026 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3030 NT_STATUS_INVALID_PARAMETER);
3034 /* unknown_1 24 NULL bytes in pdata*/
3036 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3037 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3038 #ifdef LARGE_SMB_OFF_T
3039 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3040 #else /* LARGE_SMB_OFF_T */
3041 if ((IVAL(pdata,28) != 0)&&
3042 ((quotas.softlim != 0xFFFFFFFF)||
3043 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3044 /* more than 32 bits? */
3047 NT_STATUS_INVALID_PARAMETER);
3050 #endif /* LARGE_SMB_OFF_T */
3052 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3053 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3054 #ifdef LARGE_SMB_OFF_T
3055 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3056 #else /* LARGE_SMB_OFF_T */
3057 if ((IVAL(pdata,36) != 0)&&
3058 ((quotas.hardlim != 0xFFFFFFFF)||
3059 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3060 /* more than 32 bits? */
3063 NT_STATUS_INVALID_PARAMETER);
3066 #endif /* LARGE_SMB_OFF_T */
3068 /* quota_flags 2 bytes **/
3069 quotas.qflags = SVAL(pdata,40);
3071 /* unknown_2 6 NULL bytes follow*/
3073 /* now set the quotas */
3074 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3075 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3076 reply_doserror(req, ERRSRV, ERRerror);
3083 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3085 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3091 * sending this reply works fine,
3092 * but I'm not sure it's the same
3093 * like windows do...
3096 reply_outbuf(req, 10, 0);
3099 #if defined(HAVE_POSIX_ACLS)
3100 /****************************************************************************
3101 Utility function to count the number of entries in a POSIX acl.
3102 ****************************************************************************/
3104 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3106 unsigned int ace_count = 0;
3107 int entry_id = SMB_ACL_FIRST_ENTRY;
3108 SMB_ACL_ENTRY_T entry;
3110 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3112 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3113 entry_id = SMB_ACL_NEXT_ENTRY;
3120 /****************************************************************************
3121 Utility function to marshall a POSIX acl into wire format.
3122 ****************************************************************************/
3124 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3126 int entry_id = SMB_ACL_FIRST_ENTRY;
3127 SMB_ACL_ENTRY_T entry;
3129 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3130 SMB_ACL_TAG_T tagtype;
3131 SMB_ACL_PERMSET_T permset;
3132 unsigned char perms = 0;
3133 unsigned int own_grp;
3136 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3137 entry_id = SMB_ACL_NEXT_ENTRY;
3140 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3141 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3145 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3146 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3150 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3151 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3152 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3154 SCVAL(pdata,1,perms);
3157 case SMB_ACL_USER_OBJ:
3158 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3159 own_grp = (unsigned int)pst->st_uid;
3160 SIVAL(pdata,2,own_grp);
3165 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3167 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3170 own_grp = (unsigned int)*puid;
3171 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3172 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3173 SIVAL(pdata,2,own_grp);
3177 case SMB_ACL_GROUP_OBJ:
3178 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3179 own_grp = (unsigned int)pst->st_gid;
3180 SIVAL(pdata,2,own_grp);
3185 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3187 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3190 own_grp = (unsigned int)*pgid;
3191 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3192 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3193 SIVAL(pdata,2,own_grp);
3198 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3199 SIVAL(pdata,2,0xFFFFFFFF);
3200 SIVAL(pdata,6,0xFFFFFFFF);
3203 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3204 SIVAL(pdata,2,0xFFFFFFFF);
3205 SIVAL(pdata,6,0xFFFFFFFF);
3208 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3211 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3218 /****************************************************************************
3219 Store the FILE_UNIX_BASIC info.
3220 ****************************************************************************/
3222 static char *store_file_unix_basic(connection_struct *conn,
3225 const SMB_STRUCT_STAT *psbuf)
3227 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3228 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3230 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3233 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3236 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3237 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3238 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3241 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3245 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3249 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3252 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3256 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3260 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3263 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3267 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3274 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3275 * the chflags(2) (or equivalent) flags.
3277 * XXX: this really should be behind the VFS interface. To do this, we would
3278 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3279 * Each VFS module could then implement it's own mapping as appropriate for the
3280 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3282 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3286 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3290 { UF_IMMUTABLE, EXT_IMMUTABLE },
3294 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3298 { UF_HIDDEN, EXT_HIDDEN },
3301 /* Do not remove. We need to guarantee that this array has at least one
3302 * entry to build on HP-UX.
3308 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3309 uint32 *smb_fflags, uint32 *smb_fmask)
3311 #ifdef HAVE_STAT_ST_FLAGS
3314 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3315 *smb_fmask |= info2_flags_map[i].smb_fflag;
3316 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3317 *smb_fflags |= info2_flags_map[i].smb_fflag;
3320 #endif /* HAVE_STAT_ST_FLAGS */
3323 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3324 const uint32 smb_fflags,
3325 const uint32 smb_fmask,
3328 #ifdef HAVE_STAT_ST_FLAGS
3329 uint32 max_fmask = 0;
3332 *stat_fflags = psbuf->st_flags;
3334 /* For each flags requested in smb_fmask, check the state of the
3335 * corresponding flag in smb_fflags and set or clear the matching
3339 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3340 max_fmask |= info2_flags_map[i].smb_fflag;
3341 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3342 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3343 *stat_fflags |= info2_flags_map[i].stat_fflag;
3345 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3350 /* If smb_fmask is asking to set any bits that are not supported by
3351 * our flag mappings, we should fail.
3353 if ((smb_fmask & max_fmask) != smb_fmask) {
3360 #endif /* HAVE_STAT_ST_FLAGS */
3364 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3365 * of file flags and birth (create) time.
3367 static char *store_file_unix_basic_info2(connection_struct *conn,
3370 const SMB_STRUCT_STAT *psbuf)
3372 uint32 file_flags = 0;
3373 uint32 flags_mask = 0;
3375 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3377 /* Create (birth) time 64 bit */
3378 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3381 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3382 SIVAL(pdata, 0, file_flags); /* flags */
3383 SIVAL(pdata, 4, flags_mask); /* mask */
3389 /****************************************************************************
3390 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3391 ****************************************************************************/
3393 static void call_trans2qpipeinfo(connection_struct *conn,
3394 struct smb_request *req,
3395 unsigned int tran_call,
3396 char **pparams, int total_params,
3397 char **ppdata, int total_data,
3398 unsigned int max_data_bytes)
3400 char *params = *pparams;
3401 char *pdata = *ppdata;
3402 unsigned int data_size = 0;
3403 unsigned int param_size = 2;
3405 smb_np_struct *p_pipe = NULL;
3408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3412 if (total_params < 4) {
3413 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3417 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3418 if (p_pipe == NULL) {
3419 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3423 info_level = SVAL(params,2);
3425 *pparams = (char *)SMB_REALLOC(*pparams,2);
3426 if (*pparams == NULL) {
3427 reply_nterror(req, NT_STATUS_NO_MEMORY);
3432 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3433 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3434 if (*ppdata == NULL ) {
3435 reply_nterror(req, NT_STATUS_NO_MEMORY);
3440 switch (info_level) {
3441 case SMB_FILE_STANDARD_INFORMATION:
3443 SOFF_T(pdata,0,4096LL);
3450 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3454 send_trans2_replies_new(req, params, param_size, *ppdata, data_size,
3460 /****************************************************************************
3461 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3462 file name or file id).
3463 ****************************************************************************/
3465 static void call_trans2qfilepathinfo(connection_struct *conn,
3466 struct smb_request *req,
3467 unsigned int tran_call,
3468 char **pparams, int total_params,
3469 char **ppdata, int total_data,
3470 unsigned int max_data_bytes)
3472 char *params = *pparams;
3473 char *pdata = *ppdata;
3474 char *dstart, *dend;
3478 SMB_OFF_T file_size=0;
3479 SMB_BIG_UINT allocation_size=0;
3480 unsigned int data_size = 0;
3481 unsigned int param_size = 2;
3482 SMB_STRUCT_STAT sbuf;
3483 pstring fname, dos_fname;
3488 BOOL delete_pending = False;
3490 time_t create_time, mtime, atime;
3491 struct timespec create_time_ts, mtime_ts, atime_ts;
3492 files_struct *fsp = NULL;
3493 struct file_id fileid;
3494 TALLOC_CTX *data_ctx = NULL;
3495 struct ea_list *ea_list = NULL;
3496 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3497 char *lock_data = NULL;
3500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3506 if (tran_call == TRANSACT2_QFILEINFO) {
3507 if (total_params < 4) {
3508 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3513 call_trans2qpipeinfo(conn, req, tran_call,
3514 pparams, total_params,
3520 fsp = file_fsp(SVAL(params,0));
3521 info_level = SVAL(params,2);
3523 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3525 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3526 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3530 if(fsp && (fsp->fake_file_handle)) {
3532 * This is actually for the QUOTA_FAKE_FILE --metze
3535 pstrcpy(fname, fsp->fsp_name);
3536 /* We know this name is ok, it's already passed the checks. */
3538 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3540 * This is actually a QFILEINFO on a directory
3541 * handle (returned from an NT SMB). NT5.0 seems
3542 * to do this call. JRA.
3544 /* We know this name is ok, it's already passed the checks. */
3545 pstrcpy(fname, fsp->fsp_name);
3547 if (INFO_LEVEL_IS_UNIX(info_level)) {
3548 /* Always do lstat for UNIX calls. */
3549 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3550 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3551 reply_unixerror(req,ERRDOS,ERRbadpath);
3554 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3555 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3556 reply_unixerror(req, ERRDOS, ERRbadpath);
3560 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3561 delete_pending = get_delete_on_close_flag(fileid);
3564 * Original code - this is an open file.
3566 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3570 pstrcpy(fname, fsp->fsp_name);
3571 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3572 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3573 reply_unixerror(req, ERRDOS, ERRbadfid);
3576 pos = fsp->fh->position_information;
3577 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3578 delete_pending = get_delete_on_close_flag(fileid);
3579 access_mask = fsp->access_mask;
3582 NTSTATUS status = NT_STATUS_OK;
3585 if (total_params < 7) {
3586 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3590 info_level = SVAL(params,0);
3592 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3594 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3595 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3599 srvstr_get_path(params, req->flags2, fname, ¶ms[6],
3600 sizeof(fname), total_params - 6,
3601 STR_TERMINATE, &status);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 reply_nterror(req, status);
3607 status = resolve_dfspath(conn,
3608 req->flags2 & FLAGS2_DFS_PATHNAMES,
3610 if (!NT_STATUS_IS_OK(status)) {
3611 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3612 reply_botherror(req,
3613 NT_STATUS_PATH_NOT_COVERED,
3614 ERRSRV, ERRbadpath);
3616 reply_nterror(req, status);
3620 status = unix_convert(conn, fname, False, NULL, &sbuf);
3621 if (!NT_STATUS_IS_OK(status)) {
3622 reply_nterror(req, status);
3625 status = check_name(conn, fname);
3626 if (!NT_STATUS_IS_OK(status)) {
3627 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3628 reply_nterror(req, status);
3632 if (INFO_LEVEL_IS_UNIX(info_level)) {
3633 /* Always do lstat for UNIX calls. */
3634 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3635 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3636 reply_unixerror(req, ERRDOS, ERRbadpath);
3639 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3640 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3641 reply_unixerror(req, ERRDOS, ERRbadpath);
3645 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3646 delete_pending = get_delete_on_close_flag(fileid);
3647 if (delete_pending) {
3648 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3653 nlink = sbuf.st_nlink;
3655 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3656 /* NTFS does not seem to count ".." */
3660 if ((nlink > 0) && delete_pending) {
3664 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3665 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3669 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3670 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3672 p = strrchr_m(fname,'/');
3678 mode = dos_mode(conn,fname,&sbuf);
3680 mode = FILE_ATTRIBUTE_NORMAL;
3682 fullpathname = fname;
3684 file_size = get_file_size(sbuf);
3686 /* Pull out any data sent here before we realloc. */
3687 switch (info_level) {
3688 case SMB_INFO_QUERY_EAS_FROM_LIST:
3690 /* Pull any EA list from the data portion. */
3693 if (total_data < 4) {
3695 req, NT_STATUS_INVALID_PARAMETER);
3698 ea_size = IVAL(pdata,0);
3700 if (total_data > 0 && ea_size != total_data) {
3701 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3702 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3704 req, NT_STATUS_INVALID_PARAMETER);
3708 if (!lp_ea_support(SNUM(conn))) {
3709 reply_doserror(req, ERRDOS,
3710 ERReasnotsupported);
3714 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3715 reply_nterror(req, NT_STATUS_NO_MEMORY);
3719 /* Pull out the list of names. */
3720 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3722 talloc_destroy(data_ctx);
3724 req, NT_STATUS_INVALID_PARAMETER);
3730 case SMB_QUERY_POSIX_LOCK:
3732 if (fsp == NULL || fsp->fh->fd == -1) {
3733 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3737 if (total_data != POSIX_LOCK_DATA_SIZE) {
3739 req, NT_STATUS_INVALID_PARAMETER);
3743 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3744 reply_nterror(req, NT_STATUS_NO_MEMORY);
3748 /* Copy the lock range data. */
3749 lock_data = (char *)TALLOC_MEMDUP(
3750 data_ctx, pdata, total_data);
3752 talloc_destroy(data_ctx);
3753 reply_nterror(req, NT_STATUS_NO_MEMORY);
3761 *pparams = (char *)SMB_REALLOC(*pparams,2);
3762 if (*pparams == NULL) {
3763 talloc_destroy(data_ctx);
3764 reply_nterror(req, NT_STATUS_NO_MEMORY);
3769 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3770 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3771 if (*ppdata == NULL ) {
3772 talloc_destroy(data_ctx);
3773 reply_nterror(req, NT_STATUS_NO_MEMORY);
3778 dend = dstart + data_size - 1;
3780 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3781 mtime_ts = get_mtimespec(&sbuf);
3782 atime_ts = get_atimespec(&sbuf);
3784 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3787 if (!null_timespec(fsp->pending_modtime)) {
3788 /* the pending modtime overrides the current modtime */
3789 mtime_ts = fsp->pending_modtime;
3793 /* Do we have this path open ? */
3794 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3795 fsp1 = file_find_di_first(fileid);
3796 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3797 /* the pending modtime overrides the current modtime */
3798 mtime_ts = fsp1->pending_modtime;
3800 if (fsp1 && fsp1->initial_allocation_size) {
3801 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3805 if (lp_dos_filetime_resolution(SNUM(conn))) {
3806 dos_filetime_timespec(&create_time_ts);
3807 dos_filetime_timespec(&mtime_ts);
3808 dos_filetime_timespec(&atime_ts);
3811 create_time = convert_timespec_to_time_t(create_time_ts);
3812 mtime = convert_timespec_to_time_t(mtime_ts);
3813 atime = convert_timespec_to_time_t(atime_ts);
3815 /* NT expects the name to be in an exact form of the *full*
3816 filename. See the trans2 torture test */
3817 if (strequal(base_name,".")) {
3818 pstrcpy(dos_fname, "\\");
3820 pstr_sprintf(dos_fname, "\\%s", fname);
3821 string_replace(dos_fname, '/', '\\');
3824 switch (info_level) {
3825 case SMB_INFO_STANDARD:
3826 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3828 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3829 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3830 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3831 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3832 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3833 SSVAL(pdata,l1_attrFile,mode);
3836 case SMB_INFO_QUERY_EA_SIZE:
3838 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3839 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3841 srv_put_dos_date2(pdata,0,create_time);
3842 srv_put_dos_date2(pdata,4,atime);
3843 srv_put_dos_date2(pdata,8,mtime); /* write time */
3844 SIVAL(pdata,12,(uint32)file_size);
3845 SIVAL(pdata,16,(uint32)allocation_size);
3846 SSVAL(pdata,20,mode);
3847 SIVAL(pdata,22,ea_size);
3851 case SMB_INFO_IS_NAME_VALID:
3852 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3853 if (tran_call == TRANSACT2_QFILEINFO) {
3854 /* os/2 needs this ? really ?*/
3855 reply_doserror(req, ERRDOS, ERRbadfunc);
3862 case SMB_INFO_QUERY_EAS_FROM_LIST:
3864 size_t total_ea_len = 0;
3865 struct ea_list *ea_file_list = NULL;
3867 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3869 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3870 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3872 if (!ea_list || (total_ea_len > data_size)) {
3873 talloc_destroy(data_ctx);
3875 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3879 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3880 talloc_destroy(data_ctx);
3884 case SMB_INFO_QUERY_ALL_EAS:
3886 /* We have data_size bytes to put EA's into. */
3887 size_t total_ea_len = 0;
3889 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3891 data_ctx = talloc_init("ea_ctx");
3893 reply_nterror(req, NT_STATUS_NO_MEMORY);
3897 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3898 if (!ea_list || (total_ea_len > data_size)) {
3899 talloc_destroy(data_ctx);
3901 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3905 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3906 talloc_destroy(data_ctx);
3910 case SMB_FILE_BASIC_INFORMATION:
3911 case SMB_QUERY_FILE_BASIC_INFO:
3913 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3914 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3915 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3917 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3921 put_long_date_timespec(pdata,create_time_ts);
3922 put_long_date_timespec(pdata+8,atime_ts);
3923 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3924 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3925 SIVAL(pdata,32,mode);
3927 DEBUG(5,("SMB_QFBI - "));
3928 DEBUG(5,("create: %s ", ctime(&create_time)));
3929 DEBUG(5,("access: %s ", ctime(&atime)));
3930 DEBUG(5,("write: %s ", ctime(&mtime)));
3931 DEBUG(5,("change: %s ", ctime(&mtime)));
3932 DEBUG(5,("mode: %x\n", mode));
3935 case SMB_FILE_STANDARD_INFORMATION:
3936 case SMB_QUERY_FILE_STANDARD_INFO:
3938 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3940 SOFF_T(pdata,0,allocation_size);
3941 SOFF_T(pdata,8,file_size);
3942 SIVAL(pdata,16,nlink);
3943 SCVAL(pdata,20,delete_pending?1:0);
3944 SCVAL(pdata,21,(mode&aDIR)?1:0);
3945 SSVAL(pdata,22,0); /* Padding. */
3948 case SMB_FILE_EA_INFORMATION:
3949 case SMB_QUERY_FILE_EA_INFO:
3951 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3952 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3954 SIVAL(pdata,0,ea_size);
3958 /* Get the 8.3 name - used if NT SMB was negotiated. */
3959 case SMB_QUERY_FILE_ALT_NAME_INFO:
3960 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3964 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3965 pstrcpy(short_name,base_name);
3966 /* Mangle if not already 8.3 */
3967 if(!mangle_is_8_3(short_name, True, conn->params)) {
3968 mangle_map(short_name,True,True,conn->params);
3970 len = srvstr_push(dstart, req->flags2,
3971 pdata+4, short_name,
3972 PTR_DIFF(dend, pdata+4),
3974 data_size = 4 + len;
3979 case SMB_QUERY_FILE_NAME_INFO:
3981 this must be *exactly* right for ACLs on mapped drives to work
3983 len = srvstr_push(dstart, req->flags2,
3985 PTR_DIFF(dend, pdata+4),
3987 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3988 data_size = 4 + len;
3992 case SMB_FILE_ALLOCATION_INFORMATION:
3993 case SMB_QUERY_FILE_ALLOCATION_INFO:
3994 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3996 SOFF_T(pdata,0,allocation_size);
3999 case SMB_FILE_END_OF_FILE_INFORMATION:
4000 case SMB_QUERY_FILE_END_OF_FILEINFO:
4001 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4003 SOFF_T(pdata,0,file_size);
4006 case SMB_QUERY_FILE_ALL_INFO:
4007 case SMB_FILE_ALL_INFORMATION:
4009 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4010 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4011 put_long_date_timespec(pdata,create_time_ts);
4012 put_long_date_timespec(pdata+8,atime_ts);
4013 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4014 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4015 SIVAL(pdata,32,mode);
4016 SIVAL(pdata,36,0); /* padding. */
4018 SOFF_T(pdata,0,allocation_size);
4019 SOFF_T(pdata,8,file_size);
4020 SIVAL(pdata,16,nlink);
4021 SCVAL(pdata,20,delete_pending);
4022 SCVAL(pdata,21,(mode&aDIR)?1:0);
4025 SIVAL(pdata,0,ea_size);
4026 pdata += 4; /* EA info */
4027 len = srvstr_push(dstart, req->flags2,
4029 PTR_DIFF(dend, pdata+4),
4033 data_size = PTR_DIFF(pdata,(*ppdata));
4036 case SMB_FILE_INTERNAL_INFORMATION:
4037 /* This should be an index number - looks like
4040 I think this causes us to fail the IFSKIT
4041 BasicFileInformationTest. -tpot */
4043 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4044 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4045 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4049 case SMB_FILE_ACCESS_INFORMATION:
4050 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4051 SIVAL(pdata,0,access_mask);
4055 case SMB_FILE_NAME_INFORMATION:
4056 /* Pathname with leading '\'. */
4059 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4060 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4061 SIVAL(pdata,0,byte_len);
4062 data_size = 4 + byte_len;
4066 case SMB_FILE_DISPOSITION_INFORMATION:
4067 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4069 SCVAL(pdata,0,delete_pending);
4072 case SMB_FILE_POSITION_INFORMATION:
4073 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4075 SOFF_T(pdata,0,pos);
4078 case SMB_FILE_MODE_INFORMATION:
4079 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4080 SIVAL(pdata,0,mode);
4084 case SMB_FILE_ALIGNMENT_INFORMATION:
4085 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4086 SIVAL(pdata,0,0); /* No alignment needed. */
4092 * NT4 server just returns "invalid query" to this - if we try to answer
4093 * it then NTws gets a BSOD! (tridge).
4094 * W2K seems to want this. JRA.
4096 case SMB_QUERY_FILE_STREAM_INFO:
4098 case SMB_FILE_STREAM_INFORMATION:
4099 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4103 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4104 SIVAL(pdata,0,0); /* ??? */
4105 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4106 SOFF_T(pdata,8,file_size);
4107 SOFF_T(pdata,16,allocation_size);
4108 data_size = 24 + byte_len;
4112 case SMB_QUERY_COMPRESSION_INFO:
4113 case SMB_FILE_COMPRESSION_INFORMATION:
4114 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4115 SOFF_T(pdata,0,file_size);
4116 SIVAL(pdata,8,0); /* ??? */
4117 SIVAL(pdata,12,0); /* ??? */
4121 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4122 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4123 put_long_date_timespec(pdata,create_time_ts);
4124 put_long_date_timespec(pdata+8,atime_ts);
4125 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4126 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4127 SOFF_T(pdata,32,allocation_size);
4128 SOFF_T(pdata,40,file_size);
4129 SIVAL(pdata,48,mode);
4130 SIVAL(pdata,52,0); /* ??? */
4134 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4135 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4136 SIVAL(pdata,0,mode);
4142 * CIFS UNIX Extensions.
4145 case SMB_QUERY_FILE_UNIX_BASIC:
4147 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4148 data_size = PTR_DIFF(pdata,(*ppdata));
4152 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4154 for (i=0; i<100; i++)
4155 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4161 case SMB_QUERY_FILE_UNIX_INFO2:
4163 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4164 data_size = PTR_DIFF(pdata,(*ppdata));
4168 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4170 for (i=0; i<100; i++)
4171 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4177 case SMB_QUERY_FILE_UNIX_LINK:
4181 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4183 if(!S_ISLNK(sbuf.st_mode)) {
4184 reply_unixerror(req, ERRSRV,
4189 reply_unixerror(req, ERRDOS, ERRbadlink);
4192 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
4194 reply_unixerror(req, ERRDOS,
4199 len = srvstr_push(dstart, req->flags2,
4201 PTR_DIFF(dend, pdata),
4204 data_size = PTR_DIFF(pdata,(*ppdata));
4209 #if defined(HAVE_POSIX_ACLS)
4210 case SMB_QUERY_POSIX_ACL:
4212 SMB_ACL_T file_acl = NULL;
4213 SMB_ACL_T def_acl = NULL;
4214 uint16 num_file_acls = 0;
4215 uint16 num_def_acls = 0;
4217 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4218 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4220 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4223 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4224 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4228 NT_STATUS_NOT_IMPLEMENTED);
4232 if (S_ISDIR(sbuf.st_mode)) {
4233 if (fsp && fsp->is_directory) {
4234 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4236 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4238 def_acl = free_empty_sys_acl(conn, def_acl);
4241 num_file_acls = count_acl_entries(conn, file_acl);
4242 num_def_acls = count_acl_entries(conn, def_acl);
4244 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4245 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4247 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4248 SMB_POSIX_ACL_HEADER_SIZE) ));
4250 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4253 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4257 NT_STATUS_BUFFER_TOO_SMALL);
4261 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4262 SSVAL(pdata,2,num_file_acls);
4263 SSVAL(pdata,4,num_def_acls);
4264 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4266 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4269 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4272 req, NT_STATUS_INTERNAL_ERROR);
4275 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4277 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4280 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4284 NT_STATUS_INTERNAL_ERROR);
4289 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4292 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4294 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4300 case SMB_QUERY_POSIX_LOCK:
4302 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4304 SMB_BIG_UINT offset;
4306 enum brl_type lock_type;
4308 if (total_data != POSIX_LOCK_DATA_SIZE) {
4310 req, NT_STATUS_INVALID_PARAMETER);
4314 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4315 case POSIX_LOCK_TYPE_READ:
4316 lock_type = READ_LOCK;
4318 case POSIX_LOCK_TYPE_WRITE:
4319 lock_type = WRITE_LOCK;
4321 case POSIX_LOCK_TYPE_UNLOCK:
4323 /* There's no point in asking for an unlock... */
4324 talloc_destroy(data_ctx);
4327 NT_STATUS_INVALID_PARAMETER);
4331 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4332 #if defined(HAVE_LONGLONG)
4333 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4334 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4335 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4336 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4337 #else /* HAVE_LONGLONG */
4338 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4339 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4340 #endif /* HAVE_LONGLONG */
4342 status = query_lock(fsp,
4349 if (ERROR_WAS_LOCK_DENIED(status)) {
4350 /* Here we need to report who has it locked... */
4351 data_size = POSIX_LOCK_DATA_SIZE;
4353 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4354 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4355 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4356 #if defined(HAVE_LONGLONG)
4357 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4358 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4359 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4360 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4361 #else /* HAVE_LONGLONG */
4362 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4363 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4364 #endif /* HAVE_LONGLONG */
4366 } else if (NT_STATUS_IS_OK(status)) {
4367 /* For success we just return a copy of what we sent
4368 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4369 data_size = POSIX_LOCK_DATA_SIZE;
4370 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4371 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4373 reply_nterror(req, status);
4380 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4384 send_trans2_replies_new(req, params, param_size, *ppdata, data_size,
4390 /****************************************************************************
4391 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4393 ****************************************************************************/
4395 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4397 SMB_STRUCT_STAT sbuf1, sbuf2;
4398 pstring last_component_oldname;
4399 pstring last_component_newname;
4400 NTSTATUS status = NT_STATUS_OK;
4405 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4406 if (!NT_STATUS_IS_OK(status)) {
4410 status = check_name(conn, oldname);
4411 if (!NT_STATUS_IS_OK(status)) {
4415 /* source must already exist. */
4416 if (!VALID_STAT(sbuf1)) {
4417 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4420 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4421 if (!NT_STATUS_IS_OK(status)) {
4425 status = check_name(conn, newname);
4426 if (!NT_STATUS_IS_OK(status)) {
4430 /* Disallow if newname already exists. */
4431 if (VALID_STAT(sbuf2)) {
4432 return NT_STATUS_OBJECT_NAME_COLLISION;
4435 /* No links from a directory. */
4436 if (S_ISDIR(sbuf1.st_mode)) {
4437 return NT_STATUS_FILE_IS_A_DIRECTORY;
4440 /* Ensure this is within the share. */
4441 status = check_reduced_name(conn, oldname);
4442 if (!NT_STATUS_IS_OK(status)) {
4446 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4448 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4449 status = map_nt_error_from_unix(errno);
4450 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4451 nt_errstr(status), newname, oldname));
4457 /****************************************************************************
4458 Deal with setting the time from any of the setfilepathinfo functions.
4459 ****************************************************************************/
4461 static NTSTATUS smb_set_file_time(connection_struct *conn,
4464 const SMB_STRUCT_STAT *psbuf,
4465 struct timespec ts[2])
4468 FILE_NOTIFY_CHANGE_LAST_ACCESS
4469 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4472 if (!VALID_STAT(*psbuf)) {
4473 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4476 /* get some defaults (no modifications) if any info is zero or -1. */
4477 if (null_timespec(ts[0])) {
4478 ts[0] = get_atimespec(psbuf);
4479 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4482 if (null_timespec(ts[1])) {
4483 ts[1] = get_mtimespec(psbuf);
4484 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4487 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4488 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4491 * Try and set the times of this file if
4492 * they are different from the current values.
4496 struct timespec mts = get_mtimespec(psbuf);
4497 struct timespec ats = get_atimespec(psbuf);
4498 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4499 return NT_STATUS_OK;
4505 * This was a setfileinfo on an open file.
4506 * NT does this a lot. We also need to
4507 * set the time here, as it can be read by
4508 * FindFirst/FindNext and with the patch for bug #2045
4509 * in smbd/fileio.c it ensures that this timestamp is
4510 * kept sticky even after a write. We save the request
4511 * away and will set it on file close and after a write. JRA.
4514 if (!null_timespec(ts[1])) {
4515 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4516 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4517 fsp_set_pending_modtime(fsp, ts[1]);
4521 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4523 if(file_ntimes(conn, fname, ts)!=0) {
4524 return map_nt_error_from_unix(errno);
4527 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4529 return NT_STATUS_OK;
4532 /****************************************************************************
4533 Deal with setting the dosmode from any of the setfilepathinfo functions.
4534 ****************************************************************************/
4536 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4538 SMB_STRUCT_STAT *psbuf,
4541 if (!VALID_STAT(*psbuf)) {
4542 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4546 if (S_ISDIR(psbuf->st_mode)) {
4553 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4555 /* check the mode isn't different, before changing it */
4556 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4558 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4559 fname, (unsigned int)dosmode ));
4561 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4562 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4563 fname, strerror(errno)));
4564 return map_nt_error_from_unix(errno);
4567 return NT_STATUS_OK;
4570 /****************************************************************************
4571 Deal with setting the size from any of the setfilepathinfo functions.
4572 ****************************************************************************/
4574 static NTSTATUS smb_set_file_size(connection_struct *conn,
4575 struct smb_request *req,
4578 SMB_STRUCT_STAT *psbuf,
4581 NTSTATUS status = NT_STATUS_OK;
4582 files_struct *new_fsp = NULL;
4584 if (!VALID_STAT(*psbuf)) {
4585 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4588 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4590 if (size == get_file_size(*psbuf)) {
4591 return NT_STATUS_OK;
4594 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4595 fname, (double)size ));
4597 if (fsp && fsp->fh->fd != -1) {
4598 /* Handle based call. */
4599 if (vfs_set_filelen(fsp, size) == -1) {
4600 return map_nt_error_from_unix(errno);
4602 return NT_STATUS_OK;
4605 status = open_file_ntcreate(conn, req, fname, psbuf,
4607 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4610 FILE_ATTRIBUTE_NORMAL,
4611 FORCE_OPLOCK_BREAK_TO_NONE,
4614 if (!NT_STATUS_IS_OK(status)) {
4615 /* NB. We check for open_was_deferred in the caller. */
4619 if (vfs_set_filelen(new_fsp, size) == -1) {
4620 status = map_nt_error_from_unix(errno);
4621 close_file(new_fsp,NORMAL_CLOSE);
4625 close_file(new_fsp,NORMAL_CLOSE);
4626 return NT_STATUS_OK;
4629 /****************************************************************************
4630 Deal with SMB_INFO_SET_EA.
4631 ****************************************************************************/
4633 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4639 struct ea_list *ea_list = NULL;
4640 TALLOC_CTX *ctx = NULL;
4641 NTSTATUS status = NT_STATUS_OK;
4643 if (total_data < 10) {
4645 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4646 length. They seem to have no effect. Bug #3212. JRA */
4648 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4649 /* We're done. We only get EA info in this call. */
4650 return NT_STATUS_OK;
4653 return NT_STATUS_INVALID_PARAMETER;
4656 if (IVAL(pdata,0) > total_data) {
4657 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4658 IVAL(pdata,0), (unsigned int)total_data));
4659 return NT_STATUS_INVALID_PARAMETER;
4662 ctx = talloc_init("SMB_INFO_SET_EA");
4664 return NT_STATUS_NO_MEMORY;
4666 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4668 talloc_destroy(ctx);
4669 return NT_STATUS_INVALID_PARAMETER;
4671 status = set_ea(conn, fsp, fname, ea_list);
4672 talloc_destroy(ctx);
4677 /****************************************************************************
4678 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4679 ****************************************************************************/
4681 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4686 SMB_STRUCT_STAT *psbuf)
4688 NTSTATUS status = NT_STATUS_OK;
4689 BOOL delete_on_close;
4692 if (total_data < 1) {
4693 return NT_STATUS_INVALID_PARAMETER;
4697 return NT_STATUS_INVALID_HANDLE;
4700 delete_on_close = (CVAL(pdata,0) ? True : False);
4701 dosmode = dos_mode(conn, fname, psbuf);
4703 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4704 "delete_on_close = %u\n",
4706 (unsigned int)dosmode,
4707 (unsigned int)delete_on_close ));
4709 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4711 if (!NT_STATUS_IS_OK(status)) {
4715 /* The set is across all open files on this dev/inode pair. */
4716 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4717 return NT_STATUS_ACCESS_DENIED;
4719 return NT_STATUS_OK;
4722 /****************************************************************************
4723 Deal with SMB_FILE_POSITION_INFORMATION.
4724 ****************************************************************************/
4726 static NTSTATUS smb_file_position_information(connection_struct *conn,
4731 SMB_BIG_UINT position_information;
4733 if (total_data < 8) {
4734 return NT_STATUS_INVALID_PARAMETER;
4738 /* Ignore on pathname based set. */
4739 return NT_STATUS_OK;
4742 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4743 #ifdef LARGE_SMB_OFF_T
4744 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4745 #else /* LARGE_SMB_OFF_T */
4746 if (IVAL(pdata,4) != 0) {
4747 /* more than 32 bits? */
4748 return NT_STATUS_INVALID_PARAMETER;
4750 #endif /* LARGE_SMB_OFF_T */
4752 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4753 fsp->fsp_name, (double)position_information ));
4754 fsp->fh->position_information = position_information;
4755 return NT_STATUS_OK;
4758 /****************************************************************************
4759 Deal with SMB_FILE_MODE_INFORMATION.
4760 ****************************************************************************/
4762 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4768 if (total_data < 4) {
4769 return NT_STATUS_INVALID_PARAMETER;
4771 mode = IVAL(pdata,0);
4772 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4773 return NT_STATUS_INVALID_PARAMETER;
4775 return NT_STATUS_OK;
4778 /****************************************************************************
4779 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4780 ****************************************************************************/
4782 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4783 struct smb_request *req,
4788 pstring link_target;
4789 const char *newname = fname;
4790 NTSTATUS status = NT_STATUS_OK;
4792 /* Set a symbolic link. */
4793 /* Don't allow this if follow links is false. */
4795 if (total_data == 0) {
4796 return NT_STATUS_INVALID_PARAMETER;
4799 if (!lp_symlinks(SNUM(conn))) {
4800 return NT_STATUS_ACCESS_DENIED;
4803 srvstr_pull(pdata, req->flags2, link_target, pdata,
4804 sizeof(link_target), total_data, STR_TERMINATE);
4806 /* !widelinks forces the target path to be within the share. */
4807 /* This means we can interpret the target as a pathname. */
4808 if (!lp_widelinks(SNUM(conn))) {
4810 char *last_dirp = NULL;
4812 if (*link_target == '/') {
4813 /* No absolute paths allowed. */
4814 return NT_STATUS_ACCESS_DENIED;
4816 pstrcpy(rel_name, newname);
4817 last_dirp = strrchr_m(rel_name, '/');
4819 last_dirp[1] = '\0';
4821 pstrcpy(rel_name, "./");
4823 pstrcat(rel_name, link_target);
4825 status = check_name(conn, rel_name);
4826 if (!NT_STATUS_IS_OK(status)) {
4831 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4832 newname, link_target ));
4834 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4835 return map_nt_error_from_unix(errno);
4838 return NT_STATUS_OK;
4841 /****************************************************************************
4842 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4843 ****************************************************************************/
4845 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4846 struct smb_request *req,
4847 const char *pdata, int total_data,
4851 NTSTATUS status = NT_STATUS_OK;
4853 /* Set a hard link. */
4854 if (total_data == 0) {
4855 return NT_STATUS_INVALID_PARAMETER;
4858 srvstr_get_path(pdata, req->flags2, oldname, pdata,
4859 sizeof(oldname), total_data, STR_TERMINATE, &status);
4860 if (!NT_STATUS_IS_OK(status)) {
4864 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
4866 if (!NT_STATUS_IS_OK(status)) {
4870 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4873 return hardlink_internals(conn, oldname, fname);
4876 /****************************************************************************
4877 Deal with SMB_FILE_RENAME_INFORMATION.
4878 ****************************************************************************/
4880 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4881 struct smb_request *req,
4882 const char *pdata, int total_data,
4883 files_struct *fsp, pstring fname)
4890 BOOL dest_has_wcard = False;
4891 NTSTATUS status = NT_STATUS_OK;
4894 if (total_data < 13) {
4895 return NT_STATUS_INVALID_PARAMETER;
4898 overwrite = (CVAL(pdata,0) ? True : False);
4899 root_fid = IVAL(pdata,4);
4900 len = IVAL(pdata,8);
4902 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4903 return NT_STATUS_INVALID_PARAMETER;
4906 srvstr_get_path_wcard(pdata, req->flags2, newname, &pdata[12],
4907 sizeof(newname), len, 0, &status,
4909 if (!NT_STATUS_IS_OK(status)) {
4913 status = resolve_dfspath_wcard(conn,
4914 req->flags2 & FLAGS2_DFS_PATHNAMES,
4915 newname, &dest_has_wcard);
4916 if (!NT_STATUS_IS_OK(status)) {
4920 /* Check the new name has no '/' characters. */
4921 if (strchr_m(newname, '/')) {
4922 return NT_STATUS_NOT_SUPPORTED;
4925 /* Create the base directory. */
4926 pstrcpy(base_name, fname);
4927 p = strrchr_m(base_name, '/');
4931 pstrcpy(base_name, "./");
4933 /* Append the new name. */
4934 pstrcat(base_name, newname);
4937 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4938 fsp->fnum, fsp->fsp_name, base_name ));
4939 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4941 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4943 status = rename_internals(conn, req, fname, base_name, 0,
4944 overwrite, False, dest_has_wcard);
4950 /****************************************************************************
4951 Deal with SMB_SET_POSIX_ACL.
4952 ****************************************************************************/
4954 #if defined(HAVE_POSIX_ACLS)
4955 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4960 SMB_STRUCT_STAT *psbuf)
4962 uint16 posix_acl_version;
4963 uint16 num_file_acls;
4964 uint16 num_def_acls;
4965 BOOL valid_file_acls = True;
4966 BOOL valid_def_acls = True;
4968 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4969 return NT_STATUS_INVALID_PARAMETER;
4971 posix_acl_version = SVAL(pdata,0);
4972 num_file_acls = SVAL(pdata,2);
4973 num_def_acls = SVAL(pdata,4);
4975 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4976 valid_file_acls = False;
4980 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4981 valid_def_acls = False;
4985 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4986 return NT_STATUS_INVALID_PARAMETER;
4989 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4990 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4991 return NT_STATUS_INVALID_PARAMETER;
4994 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4995 fname ? fname : fsp->fsp_name,
4996 (unsigned int)num_file_acls,
4997 (unsigned int)num_def_acls));
4999 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5000 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5001 return map_nt_error_from_unix(errno);
5004 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5005 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5006 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5007 return map_nt_error_from_unix(errno);
5009 return NT_STATUS_OK;
5013 /****************************************************************************
5014 Deal with SMB_SET_POSIX_LOCK.
5015 ****************************************************************************/
5017 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5025 SMB_BIG_UINT offset;
5027 BOOL blocking_lock = False;
5028 enum brl_type lock_type;
5029 NTSTATUS status = NT_STATUS_OK;
5031 if (fsp == NULL || fsp->fh->fd == -1) {
5032 return NT_STATUS_INVALID_HANDLE;
5035 if (total_data != POSIX_LOCK_DATA_SIZE) {
5036 return NT_STATUS_INVALID_PARAMETER;
5039 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5040 case POSIX_LOCK_TYPE_READ:
5041 lock_type = READ_LOCK;
5043 case POSIX_LOCK_TYPE_WRITE:
5044 /* Return the right POSIX-mappable error code for files opened read-only. */
5045 if (!fsp->can_write) {
5046 return NT_STATUS_INVALID_HANDLE;
5048 lock_type = WRITE_LOCK;
5050 case POSIX_LOCK_TYPE_UNLOCK:
5051 lock_type = UNLOCK_LOCK;
5054 return NT_STATUS_INVALID_PARAMETER;
5057 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5058 blocking_lock = False;
5059 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5060 blocking_lock = True;
5062 return NT_STATUS_INVALID_PARAMETER;
5065 if (!lp_blocking_locks(SNUM(conn))) {
5066 blocking_lock = False;
5069 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5070 #if defined(HAVE_LONGLONG)
5071 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5072 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5073 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5074 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5075 #else /* HAVE_LONGLONG */
5076 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5077 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5078 #endif /* HAVE_LONGLONG */
5080 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5081 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5083 (unsigned int)lock_type,
5084 (unsigned int)lock_pid,
5088 if (lock_type == UNLOCK_LOCK) {
5089 status = do_unlock(smbd_messaging_context(),
5096 uint32 block_smbpid;
5098 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5109 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5111 * A blocking lock was requested. Package up
5112 * this smb into a queued request and push it
5113 * onto the blocking lock queue.
5115 if(push_blocking_lock_request(br_lck,
5116 (char *)inbuf, length,
5118 -1, /* infinite timeout. */
5126 TALLOC_FREE(br_lck);
5130 TALLOC_FREE(br_lck);
5136 /****************************************************************************
5137 Deal with SMB_INFO_STANDARD.
5138 ****************************************************************************/
5140 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5145 const SMB_STRUCT_STAT *psbuf)
5147 struct timespec ts[2];
5149 if (total_data < 12) {
5150 return NT_STATUS_INVALID_PARAMETER;
5154 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5156 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5158 DEBUG(10,("smb_set_info_standard: file %s\n",
5159 fname ? fname : fsp->fsp_name ));
5161 return smb_set_file_time(conn,
5168 /****************************************************************************
5169 Deal with SMB_SET_FILE_BASIC_INFO.
5170 ****************************************************************************/
5172 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5177 SMB_STRUCT_STAT *psbuf)
5179 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5180 struct timespec write_time;
5181 struct timespec changed_time;
5183 struct timespec ts[2];
5184 NTSTATUS status = NT_STATUS_OK;
5186 if (total_data < 36) {
5187 return NT_STATUS_INVALID_PARAMETER;
5190 /* Set the attributes */
5191 dosmode = IVAL(pdata,32);
5192 status = smb_set_file_dosmode(conn,
5196 if (!NT_STATUS_IS_OK(status)) {
5200 /* Ignore create time at offset pdata. */
5203 ts[0] = interpret_long_date(pdata+8);
5205 write_time = interpret_long_date(pdata+16);
5206 changed_time = interpret_long_date(pdata+24);
5209 ts[1] = timespec_min(&write_time, &changed_time);
5211 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5215 /* Prefer a defined time to an undefined one. */
5216 if (null_timespec(ts[1])) {
5217 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5220 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5221 fname ? fname : fsp->fsp_name ));
5223 return smb_set_file_time(conn,
5230 /****************************************************************************
5231 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5232 ****************************************************************************/
5234 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5235 struct smb_request *req,
5240 SMB_STRUCT_STAT *psbuf)
5242 SMB_BIG_UINT allocation_size = 0;
5243 NTSTATUS status = NT_STATUS_OK;
5244 files_struct *new_fsp = NULL;
5246 if (!VALID_STAT(*psbuf)) {
5247 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5250 if (total_data < 8) {
5251 return NT_STATUS_INVALID_PARAMETER;
5254 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5255 #ifdef LARGE_SMB_OFF_T
5256 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5257 #else /* LARGE_SMB_OFF_T */
5258 if (IVAL(pdata,4) != 0) {
5259 /* more than 32 bits? */
5260 return NT_STATUS_INVALID_PARAMETER;
5262 #endif /* LARGE_SMB_OFF_T */
5264 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5265 fname, (double)allocation_size ));
5267 if (allocation_size) {
5268 allocation_size = smb_roundup(conn, allocation_size);
5271 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5272 fname, (double)allocation_size ));
5274 if (fsp && fsp->fh->fd != -1) {
5275 /* Open file handle. */
5276 /* Only change if needed. */
5277 if (allocation_size != get_file_size(*psbuf)) {
5278 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5279 return map_nt_error_from_unix(errno);
5282 /* But always update the time. */
5283 if (null_timespec(fsp->pending_modtime)) {
5285 * This is equivalent to a write. Ensure it's seen immediately
5286 * if there are no pending writes.
5288 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5290 return NT_STATUS_OK;
5293 /* Pathname or stat or directory file. */
5295 status = open_file_ntcreate(conn, req, fname, psbuf,
5297 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5300 FILE_ATTRIBUTE_NORMAL,
5301 FORCE_OPLOCK_BREAK_TO_NONE,
5304 if (!NT_STATUS_IS_OK(status)) {
5305 /* NB. We check for open_was_deferred in the caller. */
5309 /* Only change if needed. */
5310 if (allocation_size != get_file_size(*psbuf)) {
5311 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5312 status = map_nt_error_from_unix(errno);
5313 close_file(new_fsp,NORMAL_CLOSE);
5318 /* Changing the allocation size should set the last mod time. */
5319 /* Don't need to call set_filetime as this will be flushed on
5322 fsp_set_pending_modtime(new_fsp, timespec_current());
5324 close_file(new_fsp,NORMAL_CLOSE);
5325 return NT_STATUS_OK;
5328 /****************************************************************************
5329 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5330 ****************************************************************************/
5332 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5333 struct smb_request *req,
5338 SMB_STRUCT_STAT *psbuf)
5342 if (total_data < 8) {
5343 return NT_STATUS_INVALID_PARAMETER;
5346 size = IVAL(pdata,0);
5347 #ifdef LARGE_SMB_OFF_T
5348 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5349 #else /* LARGE_SMB_OFF_T */
5350 if (IVAL(pdata,4) != 0) {
5351 /* more than 32 bits? */
5352 return NT_STATUS_INVALID_PARAMETER;
5354 #endif /* LARGE_SMB_OFF_T */
5355 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5356 "file %s to %.0f\n", fname, (double)size ));
5358 return smb_set_file_size(conn, req,
5365 /****************************************************************************
5366 Allow a UNIX info mknod.
5367 ****************************************************************************/
5369 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5373 SMB_STRUCT_STAT *psbuf)
5375 uint32 file_type = IVAL(pdata,56);
5376 #if defined(HAVE_MAKEDEV)
5377 uint32 dev_major = IVAL(pdata,60);
5378 uint32 dev_minor = IVAL(pdata,68);
5380 SMB_DEV_T dev = (SMB_DEV_T)0;
5381 uint32 raw_unixmode = IVAL(pdata,84);
5385 if (total_data < 100) {
5386 return NT_STATUS_INVALID_PARAMETER;
5389 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5390 if (!NT_STATUS_IS_OK(status)) {
5394 #if defined(HAVE_MAKEDEV)
5395 dev = makedev(dev_major, dev_minor);
5398 switch (file_type) {
5399 #if defined(S_IFIFO)
5400 case UNIX_TYPE_FIFO:
5401 unixmode |= S_IFIFO;
5404 #if defined(S_IFSOCK)
5405 case UNIX_TYPE_SOCKET:
5406 unixmode |= S_IFSOCK;
5409 #if defined(S_IFCHR)
5410 case UNIX_TYPE_CHARDEV:
5411 unixmode |= S_IFCHR;
5414 #if defined(S_IFBLK)
5415 case UNIX_TYPE_BLKDEV:
5416 unixmode |= S_IFBLK;
5420 return NT_STATUS_INVALID_PARAMETER;
5423 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5424 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5426 /* Ok - do the mknod. */
5427 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5428 return map_nt_error_from_unix(errno);
5431 /* If any of the other "set" calls fail we
5432 * don't want to end up with a half-constructed mknod.
5435 if (lp_inherit_perms(SNUM(conn))) {
5437 conn, parent_dirname(fname),
5441 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5442 status = map_nt_error_from_unix(errno);
5443 SMB_VFS_UNLINK(conn,fname);
5446 return NT_STATUS_OK;
5449 /****************************************************************************
5450 Deal with SMB_SET_FILE_UNIX_BASIC.
5451 ****************************************************************************/
5453 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5454 struct smb_request *req,
5459 SMB_STRUCT_STAT *psbuf)
5461 struct timespec ts[2];
5462 uint32 raw_unixmode;
5465 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5466 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5467 NTSTATUS status = NT_STATUS_OK;
5468 BOOL delete_on_fail = False;
5469 enum perm_type ptype;
5471 if (total_data < 100) {
5472 return NT_STATUS_INVALID_PARAMETER;
5475 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5476 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5477 size=IVAL(pdata,0); /* first 8 Bytes are size */
5478 #ifdef LARGE_SMB_OFF_T
5479 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5480 #else /* LARGE_SMB_OFF_T */
5481 if (IVAL(pdata,4) != 0) {
5482 /* more than 32 bits? */
5483 return NT_STATUS_INVALID_PARAMETER;
5485 #endif /* LARGE_SMB_OFF_T */
5488 ts[0] = interpret_long_date(pdata+24); /* access_time */
5489 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5490 set_owner = (uid_t)IVAL(pdata,40);
5491 set_grp = (gid_t)IVAL(pdata,48);
5492 raw_unixmode = IVAL(pdata,84);
5494 if (VALID_STAT(*psbuf)) {
5495 if (S_ISDIR(psbuf->st_mode)) {
5496 ptype = PERM_EXISTING_DIR;
5498 ptype = PERM_EXISTING_FILE;
5501 ptype = PERM_NEW_FILE;
5504 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5505 if (!NT_STATUS_IS_OK(status)) {
5509 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5510 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5511 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5513 if (!VALID_STAT(*psbuf)) {
5515 * The only valid use of this is to create character and block
5516 * devices, and named pipes. This is deprecated (IMHO) and
5517 * a new info level should be used for mknod. JRA.
5520 status = smb_unix_mknod(conn,
5525 if (!NT_STATUS_IS_OK(status)) {
5529 /* Ensure we don't try and change anything else. */
5530 raw_unixmode = SMB_MODE_NO_CHANGE;
5531 size = get_file_size(*psbuf);
5532 ts[0] = get_atimespec(psbuf);
5533 ts[1] = get_mtimespec(psbuf);
5535 * We continue here as we might want to change the
5538 delete_on_fail = True;
5542 /* Horrible backwards compatibility hack as an old server bug
5543 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5547 size = get_file_size(*psbuf);
5552 * Deal with the UNIX specific mode set.
5555 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5556 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5557 (unsigned int)unixmode, fname ));
5558 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5559 return map_nt_error_from_unix(errno);
5564 * Deal with the UNIX specific uid set.
5567 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5570 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5571 (unsigned int)set_owner, fname ));
5573 if (S_ISLNK(psbuf->st_mode)) {
5574 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5576 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5580 status = map_nt_error_from_unix(errno);
5581 if (delete_on_fail) {
5582 SMB_VFS_UNLINK(conn,fname);
5589 * Deal with the UNIX specific gid set.
5592 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5593 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5594 (unsigned int)set_owner, fname ));
5595 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5596 status = map_nt_error_from_unix(errno);
5597 if (delete_on_fail) {
5598 SMB_VFS_UNLINK(conn,fname);
5604 /* Deal with any size changes. */
5606 status = smb_set_file_size(conn, req,
5611 if (!NT_STATUS_IS_OK(status)) {
5615 /* Deal with any time changes. */
5617 return smb_set_file_time(conn,
5624 /****************************************************************************
5625 Deal with SMB_SET_FILE_UNIX_INFO2.
5626 ****************************************************************************/
5628 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5629 struct smb_request *req,
5634 SMB_STRUCT_STAT *psbuf)
5640 if (total_data < 116) {
5641 return NT_STATUS_INVALID_PARAMETER;
5644 /* Start by setting all the fields that are common between UNIX_BASIC
5647 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5649 if (!NT_STATUS_IS_OK(status)) {
5653 smb_fflags = IVAL(pdata, 108);
5654 smb_fmask = IVAL(pdata, 112);
5656 /* NB: We should only attempt to alter the file flags if the client
5657 * sends a non-zero mask.
5659 if (smb_fmask != 0) {
5660 int stat_fflags = 0;
5662 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5664 /* Client asked to alter a flag we don't understand. */
5665 return NT_STATUS_INVALID_PARAMETER;
5668 if (fsp && fsp->fh->fd != -1) {
5669 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5670 return NT_STATUS_NOT_SUPPORTED;
5672 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5673 return map_nt_error_from_unix(errno);
5678 /* XXX: need to add support for changing the create_time here. You
5679 * can do this for paths on Darwin with setattrlist(2). The right way
5680 * to hook this up is probably by extending the VFS utimes interface.
5683 return NT_STATUS_OK;
5686 /****************************************************************************
5687 Create a directory with POSIX semantics.
5688 ****************************************************************************/
5690 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5691 struct smb_request *req,
5695 SMB_STRUCT_STAT *psbuf,
5696 int *pdata_return_size)
5698 NTSTATUS status = NT_STATUS_OK;
5699 uint32 raw_unixmode = 0;
5700 uint32 mod_unixmode = 0;
5701 mode_t unixmode = (mode_t)0;
5702 files_struct *fsp = NULL;
5703 uint16 info_level_return = 0;
5705 char *pdata = *ppdata;
5707 if (total_data < 18) {
5708 return NT_STATUS_INVALID_PARAMETER;
5711 raw_unixmode = IVAL(pdata,8);
5712 /* Next 4 bytes are not yet defined. */
5714 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5715 if (!NT_STATUS_IS_OK(status)) {
5719 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5721 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5722 fname, (unsigned int)unixmode ));
5724 status = open_directory(conn, req,
5727 FILE_READ_ATTRIBUTES, /* Just a stat open */
5728 FILE_SHARE_NONE, /* Ignored for stat opens */
5735 if (NT_STATUS_IS_OK(status)) {
5736 close_file(fsp, NORMAL_CLOSE);
5739 info_level_return = SVAL(pdata,16);
5741 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5742 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5743 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5744 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5746 *pdata_return_size = 12;
5749 /* Realloc the data size */
5750 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5751 if (*ppdata == NULL) {
5752 *pdata_return_size = 0;
5753 return NT_STATUS_NO_MEMORY;
5757 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5758 SSVAL(pdata,2,0); /* No fnum. */
5759 SIVAL(pdata,4,info); /* Was directory created. */
5761 switch (info_level_return) {
5762 case SMB_QUERY_FILE_UNIX_BASIC:
5763 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5764 SSVAL(pdata,10,0); /* Padding. */
5765 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5767 case SMB_QUERY_FILE_UNIX_INFO2:
5768 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5769 SSVAL(pdata,10,0); /* Padding. */
5770 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5773 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5774 SSVAL(pdata,10,0); /* Padding. */
5781 /****************************************************************************
5782 Open/Create a file with POSIX semantics.
5783 ****************************************************************************/
5785 static NTSTATUS smb_posix_open(connection_struct *conn,
5786 struct smb_request *req,
5790 SMB_STRUCT_STAT *psbuf,
5791 int *pdata_return_size)
5793 BOOL extended_oplock_granted = False;
5794 char *pdata = *ppdata;
5796 uint32 wire_open_mode = 0;
5797 uint32 raw_unixmode = 0;
5798 uint32 mod_unixmode = 0;
5799 uint32 create_disp = 0;
5800 uint32 access_mask = 0;
5801 uint32 create_options = 0;
5802 NTSTATUS status = NT_STATUS_OK;
5803 mode_t unixmode = (mode_t)0;
5804 files_struct *fsp = NULL;
5805 int oplock_request = 0;
5807 uint16 info_level_return = 0;
5809 if (total_data < 18) {
5810 return NT_STATUS_INVALID_PARAMETER;
5813 flags = IVAL(pdata,0);
5814 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5815 if (oplock_request) {
5816 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5819 wire_open_mode = IVAL(pdata,4);
5821 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5822 return smb_posix_mkdir(conn, req,
5830 switch (wire_open_mode & SMB_ACCMODE) {
5832 access_mask = FILE_READ_DATA;
5835 access_mask = FILE_WRITE_DATA;
5838 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5841 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5842 (unsigned int)wire_open_mode ));
5843 return NT_STATUS_INVALID_PARAMETER;
5846 wire_open_mode &= ~SMB_ACCMODE;
5848 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5849 create_disp = FILE_CREATE;
5850 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5851 create_disp = FILE_OVERWRITE_IF;
5852 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5853 create_disp = FILE_OPEN_IF;
5855 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5856 (unsigned int)wire_open_mode ));
5857 return NT_STATUS_INVALID_PARAMETER;
5860 raw_unixmode = IVAL(pdata,8);
5861 /* Next 4 bytes are not yet defined. */
5863 status = unix_perms_from_wire(conn,
5866 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5869 if (!NT_STATUS_IS_OK(status)) {
5873 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5875 if (wire_open_mode & SMB_O_SYNC) {
5876 create_options |= FILE_WRITE_THROUGH;
5878 if (wire_open_mode & SMB_O_APPEND) {
5879 access_mask |= FILE_APPEND_DATA;
5881 if (wire_open_mode & SMB_O_DIRECT) {
5882 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5885 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5887 (unsigned int)wire_open_mode,
5888 (unsigned int)unixmode ));
5890 status = open_file_ntcreate(conn, req,
5894 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5896 0, /* no create options yet. */
5902 if (!NT_STATUS_IS_OK(status)) {
5906 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5907 extended_oplock_granted = True;
5910 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5911 extended_oplock_granted = True;
5914 info_level_return = SVAL(pdata,16);
5916 /* Allocate the correct return size. */
5918 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5919 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5920 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5921 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5923 *pdata_return_size = 12;
5926 /* Realloc the data size */
5927 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5928 if (*ppdata == NULL) {
5929 close_file(fsp,ERROR_CLOSE);
5930 *pdata_return_size = 0;
5931 return NT_STATUS_NO_MEMORY;
5935 if (extended_oplock_granted) {
5936 if (flags & REQUEST_BATCH_OPLOCK) {
5937 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5939 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5941 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5942 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5944 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5947 SSVAL(pdata,2,fsp->fnum);
5948 SIVAL(pdata,4,info); /* Was file created etc. */
5950 switch (info_level_return) {
5951 case SMB_QUERY_FILE_UNIX_BASIC:
5952 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5953 SSVAL(pdata,10,0); /* padding. */
5954 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5956 case SMB_QUERY_FILE_UNIX_INFO2:
5957 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5958 SSVAL(pdata,10,0); /* padding. */
5959 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5962 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5963 SSVAL(pdata,10,0); /* padding. */
5966 return NT_STATUS_OK;
5969 /****************************************************************************
5970 Delete a file with POSIX semantics.
5971 ****************************************************************************/
5973 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5974 struct smb_request *req,
5978 SMB_STRUCT_STAT *psbuf)
5980 NTSTATUS status = NT_STATUS_OK;
5981 files_struct *fsp = NULL;
5986 struct share_mode_lock *lck = NULL;
5988 if (total_data < 2) {
5989 return NT_STATUS_INVALID_PARAMETER;
5992 flags = SVAL(pdata,0);
5994 if (!VALID_STAT(*psbuf)) {
5995 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5998 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5999 !VALID_STAT_OF_DIR(*psbuf)) {
6000 return NT_STATUS_NOT_A_DIRECTORY;
6003 DEBUG(10,("smb_posix_unlink: %s %s\n",
6004 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6007 if (VALID_STAT_OF_DIR(*psbuf)) {
6008 status = open_directory(conn, req,
6012 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6015 FILE_FLAG_POSIX_SEMANTICS|0777,
6020 status = open_file_ntcreate(conn, req,
6024 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6027 FILE_FLAG_POSIX_SEMANTICS|0777,
6028 0, /* No oplock, but break existing ones. */
6033 if (!NT_STATUS_IS_OK(status)) {
6038 * Don't lie to client. If we can't really delete due to
6039 * non-POSIX opens return SHARING_VIOLATION.
6042 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6044 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6045 "lock for file %s\n", fsp->fsp_name));
6046 close_file(fsp, NORMAL_CLOSE);
6047 return NT_STATUS_INVALID_PARAMETER;
6051 * See if others still have the file open. If this is the case, then
6052 * don't delete. If all opens are POSIX delete we can set the delete
6053 * on close disposition.
6055 for (i=0; i<lck->num_share_modes; i++) {
6056 struct share_mode_entry *e = &lck->share_modes[i];
6057 if (is_valid_share_mode_entry(e)) {
6058 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6061 /* Fail with sharing violation. */
6062 close_file(fsp, NORMAL_CLOSE);
6064 return NT_STATUS_SHARING_VIOLATION;
6069 * Set the delete on close.
6071 status = smb_set_file_disposition_info(conn,
6078 if (!NT_STATUS_IS_OK(status)) {
6079 close_file(fsp, NORMAL_CLOSE);
6084 return close_file(fsp, NORMAL_CLOSE);
6087 /****************************************************************************
6088 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6089 ****************************************************************************/
6091 static void call_trans2setfilepathinfo(connection_struct *conn,
6092 struct smb_request *req,
6093 unsigned int tran_call,
6094 char **pparams, int total_params,
6095 char **ppdata, int total_data,
6096 unsigned int max_data_bytes)
6098 char *params = *pparams;
6099 char *pdata = *ppdata;
6101 SMB_STRUCT_STAT sbuf;
6103 files_struct *fsp = NULL;
6104 NTSTATUS status = NT_STATUS_OK;
6105 int data_return_size = 0;
6108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6114 if (tran_call == TRANSACT2_SETFILEINFO) {
6115 if (total_params < 4) {
6116 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6120 fsp = file_fsp(SVAL(params,0));
6121 info_level = SVAL(params,2);
6123 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
6125 * This is actually a SETFILEINFO on a directory
6126 * handle (returned from an NT SMB). NT5.0 seems
6127 * to do this call. JRA.
6129 pstrcpy(fname, fsp->fsp_name);
6130 if (INFO_LEVEL_IS_UNIX(info_level)) {
6131 /* Always do lstat for UNIX calls. */
6132 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6133 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6134 reply_unixerror(req,ERRDOS,ERRbadpath);
6138 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6139 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6140 reply_unixerror(req,ERRDOS,ERRbadpath);
6144 } else if (fsp && fsp->print_file) {
6146 * Doing a DELETE_ON_CLOSE should cancel a print job.
6148 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6149 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6151 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6154 send_trans2_replies_new(req, params, 2,
6160 reply_unixerror(req, ERRDOS, ERRbadpath);
6165 * Original code - this is an open file.
6167 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6171 pstrcpy(fname, fsp->fsp_name);
6173 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6174 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6175 reply_unixerror(req, ERRDOS, ERRbadfid);
6181 if (total_params < 7) {
6182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6186 info_level = SVAL(params,0);
6187 srvstr_get_path(params, req->flags2, fname, ¶ms[6],
6188 sizeof(fname), total_params - 6, STR_TERMINATE,
6190 if (!NT_STATUS_IS_OK(status)) {
6191 reply_nterror(req, status);
6195 status = resolve_dfspath(conn,
6196 req->flags2 & FLAGS2_DFS_PATHNAMES,
6198 if (!NT_STATUS_IS_OK(status)) {
6199 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6200 reply_botherror(req,
6201 NT_STATUS_PATH_NOT_COVERED,
6202 ERRSRV, ERRbadpath);
6205 reply_nterror(req, status);
6209 status = unix_convert(conn, fname, False, NULL, &sbuf);
6210 if (!NT_STATUS_IS_OK(status)) {
6211 reply_nterror(req, status);
6215 status = check_name(conn, fname);
6216 if (!NT_STATUS_IS_OK(status)) {
6217 reply_nterror(req, status);
6221 if (INFO_LEVEL_IS_UNIX(info_level)) {
6223 * For CIFS UNIX extensions the target name may not exist.
6226 /* Always do lstat for UNIX calls. */
6227 SMB_VFS_LSTAT(conn,fname,&sbuf);
6229 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6230 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6231 reply_unixerror(req, ERRDOS, ERRbadpath);
6236 if (!CAN_WRITE(conn)) {
6237 reply_doserror(req, ERRSRV, ERRaccess);
6241 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6242 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6246 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6247 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6249 /* Realloc the parameter size */
6250 *pparams = (char *)SMB_REALLOC(*pparams,2);
6251 if (*pparams == NULL) {
6252 reply_nterror(req, NT_STATUS_NO_MEMORY);
6259 if (fsp && !null_timespec(fsp->pending_modtime)) {
6260 /* the pending modtime overrides the current modtime */
6261 set_mtimespec(&sbuf, fsp->pending_modtime);
6264 switch (info_level) {
6266 case SMB_INFO_STANDARD:
6268 status = smb_set_info_standard(conn,
6277 case SMB_INFO_SET_EA:
6279 status = smb_info_set_ea(conn,
6287 case SMB_SET_FILE_BASIC_INFO:
6288 case SMB_FILE_BASIC_INFORMATION:
6290 status = smb_set_file_basic_info(conn,
6299 case SMB_FILE_ALLOCATION_INFORMATION:
6300 case SMB_SET_FILE_ALLOCATION_INFO:
6302 status = smb_set_file_allocation_info(conn, req,
6311 case SMB_FILE_END_OF_FILE_INFORMATION:
6312 case SMB_SET_FILE_END_OF_FILE_INFO:
6314 status = smb_set_file_end_of_file_info(conn, req,
6323 case SMB_FILE_DISPOSITION_INFORMATION:
6324 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6327 /* JRA - We used to just ignore this on a path ?
6328 * Shouldn't this be invalid level on a pathname
6331 if (tran_call != TRANSACT2_SETFILEINFO) {
6332 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6335 status = smb_set_file_disposition_info(conn,
6344 case SMB_FILE_POSITION_INFORMATION:
6346 status = smb_file_position_information(conn,
6353 /* From tridge Samba4 :
6354 * MODE_INFORMATION in setfileinfo (I have no
6355 * idea what "mode information" on a file is - it takes a value of 0,
6356 * 2, 4 or 6. What could it be?).
6359 case SMB_FILE_MODE_INFORMATION:
6361 status = smb_file_mode_information(conn,
6368 * CIFS UNIX extensions.
6371 case SMB_SET_FILE_UNIX_BASIC:
6373 status = smb_set_file_unix_basic(conn, req,
6382 case SMB_SET_FILE_UNIX_INFO2:
6384 status = smb_set_file_unix_info2(conn, req,
6393 case SMB_SET_FILE_UNIX_LINK:
6395 if (tran_call != TRANSACT2_SETPATHINFO) {
6396 /* We must have a pathname for this. */
6397 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6400 status = smb_set_file_unix_link(conn, req, pdata,
6405 case SMB_SET_FILE_UNIX_HLINK:
6407 if (tran_call != TRANSACT2_SETPATHINFO) {
6408 /* We must have a pathname for this. */
6409 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6412 status = smb_set_file_unix_hlink(conn, req,
6418 case SMB_FILE_RENAME_INFORMATION:
6420 status = smb_file_rename_information(conn, req,
6426 #if defined(HAVE_POSIX_ACLS)
6427 case SMB_SET_POSIX_ACL:
6429 status = smb_set_posix_acl(conn,
6439 case SMB_SET_POSIX_LOCK:
6441 if (tran_call != TRANSACT2_SETFILEINFO) {
6442 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6445 status = smb_set_posix_lock(conn, req->inbuf,
6446 smb_len(req->inbuf) + 4,
6447 pdata, total_data, fsp);
6451 case SMB_POSIX_PATH_OPEN:
6453 if (tran_call != TRANSACT2_SETPATHINFO) {
6454 /* We must have a pathname for this. */
6455 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6459 status = smb_posix_open(conn, req,
6468 case SMB_POSIX_PATH_UNLINK:
6470 if (tran_call != TRANSACT2_SETPATHINFO) {
6471 /* We must have a pathname for this. */
6472 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6476 status = smb_posix_unlink(conn, req,
6485 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6490 if (!NT_STATUS_IS_OK(status)) {
6491 if (open_was_deferred(req->mid)) {
6492 /* We have re-scheduled this call. */
6495 if (blocking_lock_was_deferred(req->mid)) {
6496 /* We have re-scheduled this call. */
6499 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6500 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6501 ERRSRV, ERRbadpath);
6504 reply_nterror(req, status);
6509 send_trans2_replies_new(req, params, 2, *ppdata, data_return_size,
6515 /****************************************************************************
6516 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6517 ****************************************************************************/
6519 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6520 char **pparams, int total_params,
6521 char **ppdata, int total_data,
6522 unsigned int max_data_bytes)
6524 char *params = *pparams;
6525 char *pdata = *ppdata;
6527 SMB_STRUCT_STAT sbuf;
6528 NTSTATUS status = NT_STATUS_OK;
6529 struct ea_list *ea_list = NULL;
6531 if (!CAN_WRITE(conn)) {
6532 reply_doserror(req, ERRSRV, ERRaccess);
6536 if (total_params < 5) {
6537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6541 srvstr_get_path(params, req->flags2, directory, ¶ms[4],
6542 sizeof(directory), total_params - 4, STR_TERMINATE,
6544 if (!NT_STATUS_IS_OK(status)) {
6545 reply_nterror(req, status);
6549 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6551 status = unix_convert(conn, directory, False, NULL, &sbuf);
6552 if (!NT_STATUS_IS_OK(status)) {
6553 reply_nterror(req, status);
6557 status = check_name(conn, directory);
6558 if (!NT_STATUS_IS_OK(status)) {
6559 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6560 reply_nterror(req, status);
6564 /* Any data in this call is an EA list. */
6565 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6566 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6571 * OS/2 workplace shell seems to send SET_EA requests of "null"
6572 * length (4 bytes containing IVAL 4).
6573 * They seem to have no effect. Bug #3212. JRA.
6576 if (total_data != 4) {
6577 if (total_data < 10) {
6578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6582 if (IVAL(pdata,0) > total_data) {
6583 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6584 IVAL(pdata,0), (unsigned int)total_data));
6585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6589 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6595 } else if (IVAL(pdata,0) != 4) {
6596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6600 status = create_directory(conn, directory);
6602 if (!NT_STATUS_IS_OK(status)) {
6603 reply_nterror(req, status);
6607 /* Try and set any given EA. */
6609 status = set_ea(conn, NULL, directory, ea_list);
6610 if (!NT_STATUS_IS_OK(status)) {
6611 reply_nterror(req, status);
6616 /* Realloc the parameter and data sizes */
6617 *pparams = (char *)SMB_REALLOC(*pparams,2);
6618 if(*pparams == NULL) {
6619 reply_nterror(req, NT_STATUS_NO_MEMORY);
6626 send_trans2_replies_new(req, params, 2, *ppdata, 0, max_data_bytes);
6631 /****************************************************************************
6632 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6633 We don't actually do this - we just send a null response.
6634 ****************************************************************************/
6636 static void call_trans2findnotifyfirst(connection_struct *conn,
6637 struct smb_request *req,
6638 char **pparams, int total_params,
6639 char **ppdata, int total_data,
6640 unsigned int max_data_bytes)
6642 static uint16 fnf_handle = 257;
6643 char *params = *pparams;
6646 if (total_params < 6) {
6647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6651 info_level = SVAL(params,4);
6652 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6654 switch (info_level) {
6659 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6663 /* Realloc the parameter and data sizes */
6664 *pparams = (char *)SMB_REALLOC(*pparams,6);
6665 if (*pparams == NULL) {
6666 reply_nterror(req, NT_STATUS_NO_MEMORY);
6671 SSVAL(params,0,fnf_handle);
6672 SSVAL(params,2,0); /* No changes */
6673 SSVAL(params,4,0); /* No EA errors */
6680 send_trans2_replies_new(req, params, 6, *ppdata, 0, max_data_bytes);
6685 /****************************************************************************
6686 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6687 changes). Currently this does nothing.
6688 ****************************************************************************/
6690 static void call_trans2findnotifynext(connection_struct *conn,
6691 struct smb_request *req,
6692 char **pparams, int total_params,
6693 char **ppdata, int total_data,
6694 unsigned int max_data_bytes)
6696 char *params = *pparams;
6698 DEBUG(3,("call_trans2findnotifynext\n"));
6700 /* Realloc the parameter and data sizes */
6701 *pparams = (char *)SMB_REALLOC(*pparams,4);
6702 if (*pparams == NULL) {
6703 reply_nterror(req, NT_STATUS_NO_MEMORY);
6708 SSVAL(params,0,0); /* No changes */
6709 SSVAL(params,2,0); /* No EA errors */
6711 send_trans2_replies_new(req, params, 4, *ppdata, 0, max_data_bytes);
6716 /****************************************************************************
6717 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6718 ****************************************************************************/
6720 static void call_trans2getdfsreferral(connection_struct *conn,
6721 struct smb_request *req,
6722 char **pparams, int total_params,
6723 char **ppdata, int total_data,
6724 unsigned int max_data_bytes)
6726 char *params = *pparams;
6729 int max_referral_level;
6730 NTSTATUS status = NT_STATUS_OK;
6732 DEBUG(10,("call_trans2getdfsreferral\n"));
6734 if (total_params < 3) {
6735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6739 max_referral_level = SVAL(params,0);
6741 if(!lp_host_msdfs()) {
6742 reply_doserror(req, ERRDOS, ERRbadfunc);
6746 srvstr_pull(params, req->flags2, pathname, ¶ms[2],
6747 sizeof(pathname), total_params - 2, STR_TERMINATE);
6748 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6749 ppdata,&status)) < 0) {
6750 reply_nterror(req, status);
6754 SSVAL(req->inbuf, smb_flg2,
6755 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6756 send_trans2_replies_new(req,0,0,*ppdata,reply_size, max_data_bytes);
6761 #define LMCAT_SPL 0x53
6762 #define LMFUNC_GETJOBID 0x60
6764 /****************************************************************************
6765 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6766 ****************************************************************************/
6768 static void call_trans2ioctl(connection_struct *conn,
6769 struct smb_request *req,
6770 char **pparams, int total_params,
6771 char **ppdata, int total_data,
6772 unsigned int max_data_bytes)
6774 char *pdata = *ppdata;
6775 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6777 /* check for an invalid fid before proceeding */
6780 reply_doserror(req, ERRDOS, ERRbadfid);
6784 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6785 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6786 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6787 if (*ppdata == NULL) {
6788 reply_nterror(req, NT_STATUS_NO_MEMORY);
6793 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6794 CAN ACCEPT THIS IN UNICODE. JRA. */
6796 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6797 srvstr_push(pdata, req->flags2, pdata + 2,
6798 global_myname(), 15,
6799 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6800 srvstr_push(pdata, req->flags2, pdata+18,
6801 lp_servicename(SNUM(conn)), 13,
6802 STR_ASCII|STR_TERMINATE); /* Service name */
6803 send_trans2_replies_new(req, *pparams, 0, *ppdata, 32,
6808 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6809 reply_doserror(req, ERRSRV, ERRerror);
6812 /****************************************************************************
6813 Reply to a SMBfindclose (stop trans2 directory search).
6814 ****************************************************************************/
6816 int reply_findclose(connection_struct *conn,
6817 char *inbuf,char *outbuf,int length,int bufsize)
6820 int dptr_num=SVALS(inbuf,smb_vwv0);
6821 START_PROFILE(SMBfindclose);
6823 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6825 dptr_close(&dptr_num);
6827 outsize = set_message(inbuf, outbuf,0,0,False);
6829 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6831 END_PROFILE(SMBfindclose);
6835 /****************************************************************************
6836 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6837 ****************************************************************************/
6839 int reply_findnclose(connection_struct *conn,
6840 char *inbuf,char *outbuf,int length,int bufsize)
6844 START_PROFILE(SMBfindnclose);
6846 dptr_num = SVAL(inbuf,smb_vwv0);
6848 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6850 /* We never give out valid handles for a
6851 findnotifyfirst - so any dptr_num is ok here.
6854 outsize = set_message(inbuf, outbuf,0,0,False);
6856 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6858 END_PROFILE(SMBfindnclose);
6862 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6863 struct trans_state *state,
6864 char *inbuf, char *outbuf, int size, int bufsize)
6868 if (Protocol >= PROTOCOL_NT1) {
6869 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6872 /* Now we must call the relevant TRANS2 function */
6873 switch(state->call) {
6874 case TRANSACT2_OPEN:
6876 START_PROFILE(Trans2_open);
6877 call_trans2open(conn, req,
6878 &state->param, state->total_param,
6879 &state->data, state->total_data,
6880 state->max_data_return);
6881 END_PROFILE(Trans2_open);
6885 case TRANSACT2_FINDFIRST:
6887 START_PROFILE(Trans2_findfirst);
6888 call_trans2findfirst(conn, req,
6889 &state->param, state->total_param,
6890 &state->data, state->total_data,
6891 state->max_data_return);
6892 END_PROFILE(Trans2_findfirst);
6896 case TRANSACT2_FINDNEXT:
6898 START_PROFILE(Trans2_findnext);
6899 call_trans2findnext(conn, req,
6900 &state->param, state->total_param,
6901 &state->data, state->total_data,
6902 state->max_data_return);
6903 END_PROFILE(Trans2_findnext);
6907 case TRANSACT2_QFSINFO:
6909 START_PROFILE(Trans2_qfsinfo);
6910 call_trans2qfsinfo(conn, req,
6911 &state->param, state->total_param,
6912 &state->data, state->total_data,
6913 state->max_data_return);
6914 END_PROFILE(Trans2_qfsinfo);
6918 case TRANSACT2_SETFSINFO:
6920 START_PROFILE(Trans2_setfsinfo);
6921 call_trans2setfsinfo(conn, req,
6922 &state->param, state->total_param,
6923 &state->data, state->total_data,
6924 state->max_data_return);
6925 END_PROFILE(Trans2_setfsinfo);
6929 case TRANSACT2_QPATHINFO:
6930 case TRANSACT2_QFILEINFO:
6932 START_PROFILE(Trans2_qpathinfo);
6933 call_trans2qfilepathinfo(conn, req, state->call,
6934 &state->param, state->total_param,
6935 &state->data, state->total_data,
6936 state->max_data_return);
6937 END_PROFILE(Trans2_qpathinfo);
6941 case TRANSACT2_SETPATHINFO:
6942 case TRANSACT2_SETFILEINFO:
6944 START_PROFILE(Trans2_setpathinfo);
6945 call_trans2setfilepathinfo(conn, req, state->call,
6946 &state->param, state->total_param,
6947 &state->data, state->total_data,
6948 state->max_data_return);
6949 END_PROFILE(Trans2_setpathinfo);
6953 case TRANSACT2_FINDNOTIFYFIRST:
6955 START_PROFILE(Trans2_findnotifyfirst);
6956 call_trans2findnotifyfirst(conn, req,
6957 &state->param, state->total_param,
6958 &state->data, state->total_data,
6959 state->max_data_return);
6960 END_PROFILE(Trans2_findnotifyfirst);
6964 case TRANSACT2_FINDNOTIFYNEXT:
6966 START_PROFILE(Trans2_findnotifynext);
6967 call_trans2findnotifynext(conn, req,
6968 &state->param, state->total_param,
6969 &state->data, state->total_data,
6970 state->max_data_return);
6971 END_PROFILE(Trans2_findnotifynext);
6975 case TRANSACT2_MKDIR:
6977 START_PROFILE(Trans2_mkdir);
6978 call_trans2mkdir(conn, req,
6979 &state->param, state->total_param,
6980 &state->data, state->total_data,
6981 state->max_data_return);
6982 END_PROFILE(Trans2_mkdir);
6986 case TRANSACT2_GET_DFS_REFERRAL:
6988 START_PROFILE(Trans2_get_dfs_referral);
6989 call_trans2getdfsreferral(conn, req,
6990 &state->param, state->total_param,
6991 &state->data, state->total_data,
6992 state->max_data_return);
6993 END_PROFILE(Trans2_get_dfs_referral);
6997 case TRANSACT2_IOCTL:
6999 START_PROFILE(Trans2_ioctl);
7000 call_trans2ioctl(conn, req,
7001 &state->param, state->total_param,
7002 &state->data, state->total_data,
7003 state->max_data_return);
7004 END_PROFILE(Trans2_ioctl);
7009 /* Error in request */
7010 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7011 outsize = ERROR_DOS(ERRSRV,ERRerror);
7017 /****************************************************************************
7018 Reply to a SMBtrans2.
7019 ****************************************************************************/
7021 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
7022 int size, int bufsize)
7025 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
7026 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
7027 unsigned int psoff = SVAL(inbuf, smb_psoff);
7028 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
7029 unsigned int tran_call = SVAL(inbuf, smb_setup0);
7030 struct trans_state *state;
7033 START_PROFILE(SMBtrans2);
7035 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
7036 if (!NT_STATUS_IS_OK(result)) {
7037 DEBUG(2, ("Got invalid trans2 request: %s\n",
7038 nt_errstr(result)));
7039 END_PROFILE(SMBtrans2);
7040 return ERROR_NT(result);
7043 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7044 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7045 && (tran_call != TRANSACT2_QFILEINFO)) {
7046 END_PROFILE(SMBtrans2);
7047 return ERROR_DOS(ERRSRV,ERRaccess);
7050 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7051 DEBUG(0, ("talloc failed\n"));
7052 END_PROFILE(SMBtrans2);
7053 return ERROR_NT(NT_STATUS_NO_MEMORY);
7056 state->cmd = SMBtrans2;
7058 state->mid = SVAL(inbuf, smb_mid);
7059 state->vuid = SVAL(inbuf, smb_uid);
7060 state->setup_count = SVAL(inbuf, smb_suwcnt);
7061 state->setup = NULL;
7062 state->total_param = SVAL(inbuf, smb_tpscnt);
7063 state->param = NULL;
7064 state->total_data = SVAL(inbuf, smb_tdscnt);
7066 state->max_param_return = SVAL(inbuf, smb_mprcnt);
7067 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
7068 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
7069 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
7070 state->one_way = BITSETW(inbuf+smb_vwv5,1);
7072 state->call = tran_call;
7074 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7075 is so as a sanity check */
7076 if (state->setup_count != 1) {
7078 * Need to have rc=0 for ioctl to get job id for OS/2.
7079 * Network printing will fail if function is not successful.
7080 * Similar function in reply.c will be used if protocol
7081 * is LANMAN1.0 instead of LM1.2X002.
7082 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7083 * outbuf doesn't have to be set(only job id is used).
7085 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
7086 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
7087 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7088 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7090 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7091 DEBUG(2,("Transaction is %d\n",tran_call));
7093 END_PROFILE(SMBtrans2);
7094 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7098 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7101 if (state->total_data) {
7102 /* Can't use talloc here, the core routines do realloc on the
7103 * params and data. */
7104 state->data = (char *)SMB_MALLOC(state->total_data);
7105 if (state->data == NULL) {
7106 DEBUG(0,("reply_trans2: data malloc fail for %u "
7107 "bytes !\n", (unsigned int)state->total_data));
7109 END_PROFILE(SMBtrans2);
7110 return(ERROR_DOS(ERRDOS,ERRnomem));
7112 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7114 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
7115 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
7118 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
7121 if (state->total_param) {
7122 /* Can't use talloc here, the core routines do realloc on the
7123 * params and data. */
7124 state->param = (char *)SMB_MALLOC(state->total_param);
7125 if (state->param == NULL) {
7126 DEBUG(0,("reply_trans: param malloc fail for %u "
7127 "bytes !\n", (unsigned int)state->total_param));
7128 SAFE_FREE(state->data);
7130 END_PROFILE(SMBtrans2);
7131 return(ERROR_DOS(ERRDOS,ERRnomem));
7133 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7135 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
7136 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
7139 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
7142 state->received_data = dscnt;
7143 state->received_param = pscnt;
7145 if ((state->received_param == state->total_param) &&
7146 (state->received_data == state->total_data)) {
7148 struct smb_request *req;
7150 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
7151 END_PROFILE(SMBtrans2);
7152 return ERROR_NT(NT_STATUS_NO_MEMORY);
7155 init_smb_request(req, (uint8 *)inbuf);
7157 outsize = handle_trans2(conn, req, state, inbuf, outbuf,
7159 if (req->outbuf != NULL) {
7160 outsize = smb_len(req->outbuf) + 4;
7161 memcpy(outbuf, req->outbuf, outsize);
7164 SAFE_FREE(state->data);
7165 SAFE_FREE(state->param);
7167 END_PROFILE(SMBtrans2);
7171 DLIST_ADD(conn->pending_trans, state);
7173 /* We need to send an interim response then receive the rest
7174 of the parameter/data bytes */
7175 outsize = set_message(inbuf, outbuf,0,0,False);
7177 END_PROFILE(SMBtrans2);
7182 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7183 SAFE_FREE(state->data);
7184 SAFE_FREE(state->param);
7186 END_PROFILE(SMBtrans2);
7187 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7191 /****************************************************************************
7192 Reply to a SMBtranss2
7193 ****************************************************************************/
7195 int reply_transs2(connection_struct *conn,
7196 char *inbuf,char *outbuf,int size,int bufsize)
7199 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7200 struct trans_state *state;
7201 struct smb_request *req;
7203 START_PROFILE(SMBtranss2);
7207 for (state = conn->pending_trans; state != NULL;
7208 state = state->next) {
7209 if (state->mid == SVAL(inbuf,smb_mid)) {
7214 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7215 END_PROFILE(SMBtranss2);
7216 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7219 /* Revise state->total_param and state->total_data in case they have
7220 changed downwards */
7222 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
7223 state->total_param = SVAL(inbuf, smb_tpscnt);
7224 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
7225 state->total_data = SVAL(inbuf, smb_tdscnt);
7227 pcnt = SVAL(inbuf, smb_spscnt);
7228 poff = SVAL(inbuf, smb_spsoff);
7229 pdisp = SVAL(inbuf, smb_spsdisp);
7231 dcnt = SVAL(inbuf, smb_sdscnt);
7232 doff = SVAL(inbuf, smb_sdsoff);
7233 ddisp = SVAL(inbuf, smb_sdsdisp);
7235 state->received_param += pcnt;
7236 state->received_data += dcnt;
7238 if ((state->received_data > state->total_data) ||
7239 (state->received_param > state->total_param))
7243 if (pdisp+pcnt > state->total_param)
7245 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7247 if (pdisp > state->total_param)
7249 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
7250 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
7252 if (state->param + pdisp < state->param)
7255 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
7260 if (ddisp+dcnt > state->total_data)
7262 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7264 if (ddisp > state->total_data)
7266 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
7267 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
7269 if (state->data + ddisp < state->data)
7272 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
7276 if ((state->received_param < state->total_param) ||
7277 (state->received_data < state->total_data)) {
7278 END_PROFILE(SMBtranss2);
7282 /* construct_reply_common has done us the favor to pre-fill the
7283 * command field with SMBtranss2 which is wrong :-)
7285 SCVAL(outbuf,smb_com,SMBtrans2);
7287 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
7288 END_PROFILE(SMBtranss2);
7289 return ERROR_NT(NT_STATUS_NO_MEMORY);
7292 init_smb_request(req, (uint8 *)inbuf);
7294 outsize = handle_trans2(conn, req, state, inbuf, outbuf, size,
7296 if (req->outbuf != NULL) {
7297 outsize = smb_len(req->outbuf) + 4;
7298 memcpy(outbuf, req->outbuf, outsize);
7302 DLIST_REMOVE(conn->pending_trans, state);
7303 SAFE_FREE(state->data);
7304 SAFE_FREE(state->param);
7308 END_PROFILE(SMBtranss2);
7309 return(ERROR_DOS(ERRSRV,ERRnosupport));
7312 END_PROFILE(SMBtranss2);
7317 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7318 DLIST_REMOVE(conn->pending_trans, state);
7319 SAFE_FREE(state->data);
7320 SAFE_FREE(state->param);
7322 END_PROFILE(SMBtranss2);
7323 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);