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 void send_trans2_replies(struct smb_request *req,
586 /* As we are using a protocol > LANMAN1 then the max_send
587 variable must have been set in the sessetupX call.
588 This takes precedence over the max_xmit field in the
589 global struct. These different max_xmit variables should
590 be merged as this is now too confusing */
592 int data_to_send = datasize;
593 int params_to_send = paramsize;
595 const char *pp = params;
596 const char *pd = pdata;
597 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
598 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
599 int data_alignment_offset = 0;
600 BOOL overflow = False;
602 /* Modify the data_to_send and datasize and set the error if
603 we're trying to send more than max_data_bytes. We still send
604 the part of the packet(s) that fit. Strange, but needed
607 if (max_data_bytes > 0 && datasize > max_data_bytes) {
608 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
609 max_data_bytes, datasize ));
610 datasize = data_to_send = max_data_bytes;
614 /* If there genuinely are no parameters or data to send just send the empty packet */
616 if(params_to_send == 0 && data_to_send == 0) {
617 reply_outbuf(req, 10, 0);
618 show_msg((char *)req->outbuf);
622 /* When sending params and data ensure that both are nicely aligned */
623 /* Only do this alignment when there is also data to send - else
624 can cause NT redirector problems. */
626 if (((params_to_send % 4) != 0) && (data_to_send != 0))
627 data_alignment_offset = 4 - (params_to_send % 4);
629 /* Space is bufsize minus Netbios over TCP header minus SMB header */
630 /* The alignment_offset is to align the param bytes on an even byte
631 boundary. NT 4.0 Beta needs this to work correctly. */
633 useable_space = max_send - (smb_size
636 + data_alignment_offset);
638 /* useable_space can never be more than max_send minus the alignment offset. */
640 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
642 while (params_to_send || data_to_send) {
643 /* Calculate whether we will totally or partially fill this packet */
645 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
647 /* We can never send more than useable_space */
649 * Note that 'useable_space' does not include the alignment offsets,
650 * but we must include the alignment offsets in the calculation of
651 * the length of the data we send over the wire, as the alignment offsets
652 * are sent here. Fix from Marc_Jacobsen@hp.com.
655 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
657 reply_outbuf(req, 10, total_sent_thistime);
659 /* Set total params and data to be sent */
660 SSVAL(req->outbuf,smb_tprcnt,paramsize);
661 SSVAL(req->outbuf,smb_tdrcnt,datasize);
663 /* Calculate how many parameters and data we can fit into
664 * this packet. Parameters get precedence
667 params_sent_thistime = MIN(params_to_send,useable_space);
668 data_sent_thistime = useable_space - params_sent_thistime;
669 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
671 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
673 /* smb_proff is the offset from the start of the SMB header to the
674 parameter bytes, however the first 4 bytes of outbuf are
675 the Netbios over TCP header. Thus use smb_base() to subtract
676 them from the calculation */
678 SSVAL(req->outbuf,smb_proff,
679 ((smb_buf(req->outbuf)+alignment_offset)
680 - smb_base(req->outbuf)));
682 if(params_sent_thistime == 0)
683 SSVAL(req->outbuf,smb_prdisp,0);
685 /* Absolute displacement of param bytes sent in this packet */
686 SSVAL(req->outbuf,smb_prdisp,pp - params);
688 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
689 if(data_sent_thistime == 0) {
690 SSVAL(req->outbuf,smb_droff,0);
691 SSVAL(req->outbuf,smb_drdisp, 0);
693 /* The offset of the data bytes is the offset of the
694 parameter bytes plus the number of parameters being sent this time */
695 SSVAL(req->outbuf, smb_droff,
696 ((smb_buf(req->outbuf)+alignment_offset)
697 - smb_base(req->outbuf))
698 + params_sent_thistime + data_alignment_offset);
699 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
702 /* Initialize the padding for alignment */
704 if (alignment_offset != 0) {
705 memset(smb_buf(req->outbuf), 0, alignment_offset);
708 /* Copy the param bytes into the packet */
710 if(params_sent_thistime) {
711 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
712 params_sent_thistime);
715 /* Copy in the data bytes */
716 if(data_sent_thistime) {
717 if (data_alignment_offset != 0) {
718 memset((smb_buf(req->outbuf)+alignment_offset+
719 params_sent_thistime), 0,
720 data_alignment_offset);
722 memcpy(smb_buf(req->outbuf)+alignment_offset
723 +params_sent_thistime+data_alignment_offset,
724 pd,data_sent_thistime);
727 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
728 params_sent_thistime, data_sent_thistime, useable_space));
729 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
730 params_to_send, data_to_send, paramsize, datasize));
733 error_packet_set((char *)req->outbuf,
734 ERRDOS,ERRbufferoverflow,
735 STATUS_BUFFER_OVERFLOW,
739 /* Send the packet */
740 show_msg((char *)req->outbuf);
741 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
742 exit_server_cleanly("send_trans2_replies: send_smb failed.");
744 TALLOC_FREE(req->outbuf);
746 pp += params_sent_thistime;
747 pd += data_sent_thistime;
749 params_to_send -= params_sent_thistime;
750 data_to_send -= data_sent_thistime;
753 if(params_to_send < 0 || data_to_send < 0) {
754 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
755 params_to_send, data_to_send));
763 /****************************************************************************
764 Reply to a TRANSACT2_OPEN.
765 ****************************************************************************/
767 static void call_trans2open(connection_struct *conn,
768 struct smb_request *req,
769 char **pparams, int total_params,
770 char **ppdata, int total_data,
771 unsigned int max_data_bytes)
773 char *params = *pparams;
774 char *pdata = *ppdata;
779 BOOL return_additional_info;
791 SMB_STRUCT_STAT sbuf;
794 struct ea_list *ea_list = NULL;
799 uint32 create_disposition;
800 uint32 create_options = 0;
803 * Ensure we have enough parameters to perform the operation.
806 if (total_params < 29) {
807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
811 flags = SVAL(params, 0);
812 deny_mode = SVAL(params, 2);
813 open_attr = SVAL(params,6);
814 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
815 if (oplock_request) {
816 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
820 return_additional_info = BITSETW(params,0);
821 open_sattr = SVAL(params, 4);
822 open_time = make_unix_date3(params+8);
824 open_ofun = SVAL(params,12);
825 open_size = IVAL(params,14);
829 reply_doserror(req, ERRSRV, ERRaccess);
833 srvstr_get_path(params, req->flags2, fname_in, pname,
834 sizeof(fname_in), total_params - 28, STR_TERMINATE,
836 if (!NT_STATUS_IS_OK(status)) {
837 reply_nterror(req, status);
841 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
842 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
843 (unsigned int)open_ofun, open_size));
845 /* XXXX we need to handle passed times, sattr and flags */
847 status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
848 if (!NT_STATUS_IS_OK(status)) {
849 reply_nterror(req, status);
853 status = check_name(conn, fname);
854 if (!NT_STATUS_IS_OK(status)) {
855 reply_nterror(req, status);
859 if (open_ofun == 0) {
860 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
864 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
869 reply_doserror(req, ERRDOS, ERRbadaccess);
873 /* Any data in this call is an EA list. */
874 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
875 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
879 if (total_data != 4) {
880 if (total_data < 10) {
881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
885 if (IVAL(pdata,0) > total_data) {
886 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
887 IVAL(pdata,0), (unsigned int)total_data));
888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
892 ea_list = read_ea_list(talloc_tos(), pdata + 4,
895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
898 } else if (IVAL(pdata,0) != 4) {
899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
903 status = open_file_ntcreate(conn, req, fname, &sbuf,
912 if (!NT_STATUS_IS_OK(status)) {
913 if (open_was_deferred(req->mid)) {
914 /* We have re-scheduled this call. */
917 reply_openerror(req, status);
921 size = get_file_size(sbuf);
922 fattr = dos_mode(conn,fname,&sbuf);
923 mtime = sbuf.st_mtime;
926 close_file(fsp,ERROR_CLOSE);
927 reply_doserror(req, ERRDOS,ERRnoaccess);
931 /* Save the requested allocation size. */
932 /* Allocate space for the file if a size hint is supplied */
933 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
934 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
935 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
936 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
937 if (fsp->is_directory) {
938 close_file(fsp,ERROR_CLOSE);
939 /* Can't set allocation size on a directory. */
940 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
943 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
944 close_file(fsp,ERROR_CLOSE);
945 reply_nterror(req, NT_STATUS_DISK_FULL);
949 /* Adjust size here to return the right size in the reply.
950 Windows does it this way. */
951 size = fsp->initial_allocation_size;
953 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
957 if (ea_list && smb_action == FILE_WAS_CREATED) {
958 status = set_ea(conn, fsp, fname, ea_list);
959 if (!NT_STATUS_IS_OK(status)) {
960 close_file(fsp,ERROR_CLOSE);
961 reply_nterror(req, status);
966 /* Realloc the size of parameters and data we will return */
967 *pparams = (char *)SMB_REALLOC(*pparams, 30);
968 if(*pparams == NULL ) {
969 reply_nterror(req, NT_STATUS_NO_MEMORY);
974 SSVAL(params,0,fsp->fnum);
975 SSVAL(params,2,fattr);
976 srv_put_dos_date2(params,4, mtime);
977 SIVAL(params,8, (uint32)size);
978 SSVAL(params,12,deny_mode);
979 SSVAL(params,14,0); /* open_type - file or directory. */
980 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
982 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
983 smb_action |= EXTENDED_OPLOCK_GRANTED;
986 SSVAL(params,18,smb_action);
989 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
991 SIVAL(params,20,inode);
992 SSVAL(params,24,0); /* Padding. */
994 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
995 SIVAL(params, 26, ea_size);
997 SIVAL(params, 26, 0);
1000 /* Send the required number of replies */
1001 send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1004 /*********************************************************
1005 Routine to check if a given string matches exactly.
1006 as a special case a mask of "." does NOT match. That
1007 is required for correct wildcard semantics
1008 Case can be significant or not.
1009 **********************************************************/
1011 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
1013 if (mask[0] == '.' && mask[1] == 0)
1015 if (conn->case_sensitive)
1016 return strcmp(str,mask)==0;
1017 if (StrCaseCmp(str,mask) != 0) {
1020 if (dptr_has_wild(conn->dirptr)) {
1026 /****************************************************************************
1027 Return the filetype for UNIX extensions.
1028 ****************************************************************************/
1030 static uint32 unix_filetype(mode_t mode)
1033 return UNIX_TYPE_FILE;
1034 else if(S_ISDIR(mode))
1035 return UNIX_TYPE_DIR;
1037 else if(S_ISLNK(mode))
1038 return UNIX_TYPE_SYMLINK;
1041 else if(S_ISCHR(mode))
1042 return UNIX_TYPE_CHARDEV;
1045 else if(S_ISBLK(mode))
1046 return UNIX_TYPE_BLKDEV;
1049 else if(S_ISFIFO(mode))
1050 return UNIX_TYPE_FIFO;
1053 else if(S_ISSOCK(mode))
1054 return UNIX_TYPE_SOCKET;
1057 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1058 return UNIX_TYPE_UNKNOWN;
1061 /****************************************************************************
1062 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1063 ****************************************************************************/
1065 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1067 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1068 SMB_STRUCT_STAT *psbuf,
1070 enum perm_type ptype,
1075 if (perms == SMB_MODE_NO_CHANGE) {
1076 if (!VALID_STAT(*psbuf)) {
1077 return NT_STATUS_INVALID_PARAMETER;
1079 *ret_perms = psbuf->st_mode;
1080 return NT_STATUS_OK;
1084 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1085 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1086 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1087 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1088 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1089 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1090 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1091 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1092 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1094 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1097 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1100 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1105 /* Apply mode mask */
1106 ret &= lp_create_mask(SNUM(conn));
1107 /* Add in force bits */
1108 ret |= lp_force_create_mode(SNUM(conn));
1111 ret &= lp_dir_mask(SNUM(conn));
1112 /* Add in force bits */
1113 ret |= lp_force_dir_mode(SNUM(conn));
1115 case PERM_EXISTING_FILE:
1116 /* Apply mode mask */
1117 ret &= lp_security_mask(SNUM(conn));
1118 /* Add in force bits */
1119 ret |= lp_force_security_mode(SNUM(conn));
1121 case PERM_EXISTING_DIR:
1122 /* Apply mode mask */
1123 ret &= lp_dir_security_mask(SNUM(conn));
1124 /* Add in force bits */
1125 ret |= lp_force_dir_security_mode(SNUM(conn));
1130 return NT_STATUS_OK;
1133 /****************************************************************************
1134 Get a level dependent lanman2 dir entry.
1135 ****************************************************************************/
1137 static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
1138 char *path_mask,uint32 dirtype,int info_level,
1139 int requires_resume_key,
1140 BOOL dont_descend,char **ppdata,
1141 char *base_data, char *end_data,
1142 int space_remaining,
1143 BOOL *out_of_space, BOOL *got_exact_match,
1144 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1148 SMB_STRUCT_STAT sbuf;
1152 char *p, *q, *pdata = *ppdata;
1156 SMB_OFF_T file_size = 0;
1157 SMB_BIG_UINT allocation_size = 0;
1159 struct timespec mdate_ts, adate_ts, create_date_ts;
1160 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1162 char *last_entry_ptr;
1164 uint32 nt_extmode; /* Used for NT connections instead of mode */
1165 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1166 BOOL check_mangled_names = lp_manglednames(conn->params);
1167 char mangled_name[13]; /* mangled 8.3 name. */
1170 *out_of_space = False;
1171 *got_exact_match = False;
1173 ZERO_STRUCT(mdate_ts);
1174 ZERO_STRUCT(adate_ts);
1175 ZERO_STRUCT(create_date_ts);
1180 p = strrchr_m(path_mask,'/');
1183 pstrcpy(mask,"*.*");
1187 pstrcpy(mask, path_mask);
1192 BOOL ms_dfs_link = False;
1194 /* Needed if we run out of space */
1195 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1196 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1199 * Due to bugs in NT client redirectors we are not using
1200 * resume keys any more - set them to zero.
1201 * Check out the related comments in findfirst/findnext.
1207 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1208 (long)conn->dirptr,curr_dirpos));
1215 * fname may get mangled, dname is never mangled.
1216 * Whenever we're accessing the filesystem we use
1217 * pathreal which is composed from dname.
1220 pstrcpy(fname,dname);
1222 /* Mangle fname if it's an illegal name. */
1223 if (mangle_must_mangle(fname,conn->params)) {
1224 if (!name_to_8_3(fname,mangled_name,True,conn->params)) {
1225 continue; /* Error - couldn't mangle. */
1227 pstrcpy(fname,mangled_name);
1230 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1231 got_match = mask_match(fname, mask, conn->case_sensitive);
1234 if(!got_match && check_mangled_names &&
1235 !mangle_is_8_3(fname, False, conn->params)) {
1237 * It turns out that NT matches wildcards against
1238 * both long *and* short names. This may explain some
1239 * of the wildcard wierdness from old DOS clients
1240 * that some people have been seeing.... JRA.
1242 /* Force the mangling into 8.3. */
1243 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1244 continue; /* Error - couldn't mangle. */
1247 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1248 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1253 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1254 if (dont_descend && !isdots) {
1258 pstrcpy(pathreal,conn->dirpath);
1260 pstrcat(pathreal,"/");
1262 pstrcat(pathreal,dname);
1264 if (INFO_LEVEL_IS_UNIX(info_level)) {
1265 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1266 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1267 pathreal,strerror(errno)));
1270 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1271 pstring link_target;
1273 /* Needed to show the msdfs symlinks as
1276 if(lp_host_msdfs() &&
1277 lp_msdfs_root(SNUM(conn)) &&
1278 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1279 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1282 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1286 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1287 pathreal,strerror(errno)));
1293 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1295 mode = dos_mode(conn,pathreal,&sbuf);
1298 if (!dir_check_ftype(conn,mode,dirtype)) {
1299 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1303 if (!(mode & aDIR)) {
1304 file_size = get_file_size(sbuf);
1306 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1308 mdate_ts = get_mtimespec(&sbuf);
1309 adate_ts = get_atimespec(&sbuf);
1310 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1312 if (lp_dos_filetime_resolution(SNUM(conn))) {
1313 dos_filetime_timespec(&create_date_ts);
1314 dos_filetime_timespec(&mdate_ts);
1315 dos_filetime_timespec(&adate_ts);
1318 create_date = convert_timespec_to_time_t(create_date_ts);
1319 mdate = convert_timespec_to_time_t(mdate_ts);
1320 adate = convert_timespec_to_time_t(adate_ts);
1322 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1326 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1333 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1335 switch (info_level) {
1336 case SMB_FIND_INFO_STANDARD:
1337 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1338 if(requires_resume_key) {
1342 srv_put_dos_date2(p,0,create_date);
1343 srv_put_dos_date2(p,4,adate);
1344 srv_put_dos_date2(p,8,mdate);
1345 SIVAL(p,12,(uint32)file_size);
1346 SIVAL(p,16,(uint32)allocation_size);
1350 p += align_string(pdata, p, 0);
1351 len = srvstr_push(base_data, flags2, p,
1352 fname, PTR_DIFF(end_data, p),
1354 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1356 SCVAL(nameptr, -1, len - 2);
1358 SCVAL(nameptr, -1, 0);
1362 SCVAL(nameptr, -1, len - 1);
1364 SCVAL(nameptr, -1, 0);
1370 case SMB_FIND_EA_SIZE:
1371 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1372 if(requires_resume_key) {
1376 srv_put_dos_date2(p,0,create_date);
1377 srv_put_dos_date2(p,4,adate);
1378 srv_put_dos_date2(p,8,mdate);
1379 SIVAL(p,12,(uint32)file_size);
1380 SIVAL(p,16,(uint32)allocation_size);
1383 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1384 SIVAL(p,22,ea_size); /* Extended attributes */
1388 len = srvstr_push(base_data, flags2,
1389 p, fname, PTR_DIFF(end_data, p),
1390 STR_TERMINATE | STR_NOALIGN);
1391 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1404 SCVAL(nameptr,0,len);
1406 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1409 case SMB_FIND_EA_LIST:
1411 struct ea_list *file_list = NULL;
1414 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1418 if(requires_resume_key) {
1422 srv_put_dos_date2(p,0,create_date);
1423 srv_put_dos_date2(p,4,adate);
1424 srv_put_dos_date2(p,8,mdate);
1425 SIVAL(p,12,(uint32)file_size);
1426 SIVAL(p,16,(uint32)allocation_size);
1428 p += 22; /* p now points to the EA area. */
1430 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1431 name_list = ea_list_union(name_list, file_list, &ea_len);
1433 /* We need to determine if this entry will fit in the space available. */
1434 /* Max string size is 255 bytes. */
1435 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1436 /* Move the dirptr back to prev_dirpos */
1437 dptr_SeekDir(conn->dirptr, prev_dirpos);
1438 *out_of_space = True;
1439 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1440 return False; /* Not finished - just out of space */
1443 /* Push the ea_data followed by the name. */
1444 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1446 len = srvstr_push(base_data, flags2,
1447 p + 1, fname, PTR_DIFF(end_data, p),
1448 STR_TERMINATE | STR_NOALIGN);
1449 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1462 SCVAL(nameptr,0,len);
1464 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1468 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1469 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1470 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1472 SIVAL(p,0,reskey); p += 4;
1473 put_long_date_timespec(p,create_date_ts); p += 8;
1474 put_long_date_timespec(p,adate_ts); p += 8;
1475 put_long_date_timespec(p,mdate_ts); p += 8;
1476 put_long_date_timespec(p,mdate_ts); p += 8;
1477 SOFF_T(p,0,file_size); p += 8;
1478 SOFF_T(p,0,allocation_size); p += 8;
1479 SIVAL(p,0,nt_extmode); p += 4;
1480 q = p; p += 4; /* q is placeholder for name length. */
1482 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1483 SIVAL(p,0,ea_size); /* Extended attributes */
1486 /* Clear the short name buffer. This is
1487 * IMPORTANT as not doing so will trigger
1488 * a Win2k client bug. JRA.
1490 if (!was_8_3 && check_mangled_names) {
1491 if (!name_to_8_3(fname,mangled_name,True,
1493 /* Error - mangle failed ! */
1494 memset(mangled_name,'\0',12);
1496 mangled_name[12] = 0;
1497 len = srvstr_push(base_data, flags2,
1498 p+2, mangled_name, 24,
1499 STR_UPPER|STR_UNICODE);
1501 memset(p + 2 + len,'\0',24 - len);
1508 len = srvstr_push(base_data, flags2, p,
1509 fname, PTR_DIFF(end_data, p),
1510 STR_TERMINATE_ASCII);
1513 SIVAL(p,0,0); /* Ensure any padding is null. */
1514 len = PTR_DIFF(p, pdata);
1515 len = (len + 3) & ~3;
1520 case SMB_FIND_FILE_DIRECTORY_INFO:
1521 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1523 SIVAL(p,0,reskey); p += 4;
1524 put_long_date_timespec(p,create_date_ts); p += 8;
1525 put_long_date_timespec(p,adate_ts); p += 8;
1526 put_long_date_timespec(p,mdate_ts); p += 8;
1527 put_long_date_timespec(p,mdate_ts); p += 8;
1528 SOFF_T(p,0,file_size); p += 8;
1529 SOFF_T(p,0,allocation_size); p += 8;
1530 SIVAL(p,0,nt_extmode); p += 4;
1531 len = srvstr_push(base_data, flags2,
1532 p + 4, fname, PTR_DIFF(end_data, p),
1533 STR_TERMINATE_ASCII);
1536 SIVAL(p,0,0); /* Ensure any padding is null. */
1537 len = PTR_DIFF(p, pdata);
1538 len = (len + 3) & ~3;
1543 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1544 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1546 SIVAL(p,0,reskey); p += 4;
1547 put_long_date_timespec(p,create_date_ts); p += 8;
1548 put_long_date_timespec(p,adate_ts); p += 8;
1549 put_long_date_timespec(p,mdate_ts); p += 8;
1550 put_long_date_timespec(p,mdate_ts); p += 8;
1551 SOFF_T(p,0,file_size); p += 8;
1552 SOFF_T(p,0,allocation_size); p += 8;
1553 SIVAL(p,0,nt_extmode); p += 4;
1554 q = p; p += 4; /* q is placeholder for name length. */
1556 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1557 SIVAL(p,0,ea_size); /* Extended attributes */
1560 len = srvstr_push(base_data, flags2, p,
1561 fname, PTR_DIFF(end_data, p),
1562 STR_TERMINATE_ASCII);
1566 SIVAL(p,0,0); /* Ensure any padding is null. */
1567 len = PTR_DIFF(p, pdata);
1568 len = (len + 3) & ~3;
1573 case SMB_FIND_FILE_NAMES_INFO:
1574 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1576 SIVAL(p,0,reskey); p += 4;
1578 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1579 acl on a dir (tridge) */
1580 len = srvstr_push(base_data, flags2, p,
1581 fname, PTR_DIFF(end_data, p),
1582 STR_TERMINATE_ASCII);
1585 SIVAL(p,0,0); /* Ensure any padding is null. */
1586 len = PTR_DIFF(p, pdata);
1587 len = (len + 3) & ~3;
1592 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1593 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1595 SIVAL(p,0,reskey); p += 4;
1596 put_long_date_timespec(p,create_date_ts); p += 8;
1597 put_long_date_timespec(p,adate_ts); p += 8;
1598 put_long_date_timespec(p,mdate_ts); p += 8;
1599 put_long_date_timespec(p,mdate_ts); p += 8;
1600 SOFF_T(p,0,file_size); p += 8;
1601 SOFF_T(p,0,allocation_size); p += 8;
1602 SIVAL(p,0,nt_extmode); p += 4;
1603 q = p; p += 4; /* q is placeholder for name length. */
1605 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1606 SIVAL(p,0,ea_size); /* Extended attributes */
1609 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1610 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1611 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1612 len = srvstr_push(base_data, flags2, p,
1613 fname, PTR_DIFF(end_data, p),
1614 STR_TERMINATE_ASCII);
1617 SIVAL(p,0,0); /* Ensure any padding is null. */
1618 len = PTR_DIFF(p, pdata);
1619 len = (len + 3) & ~3;
1624 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1625 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1626 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1628 SIVAL(p,0,reskey); p += 4;
1629 put_long_date_timespec(p,create_date_ts); p += 8;
1630 put_long_date_timespec(p,adate_ts); p += 8;
1631 put_long_date_timespec(p,mdate_ts); p += 8;
1632 put_long_date_timespec(p,mdate_ts); p += 8;
1633 SOFF_T(p,0,file_size); p += 8;
1634 SOFF_T(p,0,allocation_size); p += 8;
1635 SIVAL(p,0,nt_extmode); p += 4;
1636 q = p; p += 4; /* q is placeholder for name length */
1638 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1639 SIVAL(p,0,ea_size); /* Extended attributes */
1642 /* Clear the short name buffer. This is
1643 * IMPORTANT as not doing so will trigger
1644 * a Win2k client bug. JRA.
1646 if (!was_8_3 && check_mangled_names) {
1647 if (!name_to_8_3(fname,mangled_name,True,
1649 /* Error - mangle failed ! */
1650 memset(mangled_name,'\0',12);
1652 mangled_name[12] = 0;
1653 len = srvstr_push(base_data, flags2,
1654 p+2, mangled_name, 24,
1655 STR_UPPER|STR_UNICODE);
1658 memset(p + 2 + len,'\0',24 - len);
1665 SSVAL(p,0,0); p += 2; /* Reserved ? */
1666 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1667 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1668 len = srvstr_push(base_data, flags2, p,
1669 fname, PTR_DIFF(end_data, p),
1670 STR_TERMINATE_ASCII);
1673 SIVAL(p,0,0); /* Ensure any padding is null. */
1674 len = PTR_DIFF(p, pdata);
1675 len = (len + 3) & ~3;
1680 /* CIFS UNIX Extension. */
1682 case SMB_FIND_FILE_UNIX:
1683 case SMB_FIND_FILE_UNIX_INFO2:
1685 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1687 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1689 if (info_level == SMB_FIND_FILE_UNIX) {
1690 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1691 p = store_file_unix_basic(conn, p,
1693 len = srvstr_push(base_data, flags2, p,
1694 fname, PTR_DIFF(end_data, p),
1697 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1698 p = store_file_unix_basic_info2(conn, p,
1702 len = srvstr_push(base_data, flags2, p, fname,
1703 PTR_DIFF(end_data, p), 0);
1704 SIVAL(nameptr, 0, len);
1708 SIVAL(p,0,0); /* Ensure any padding is null. */
1710 len = PTR_DIFF(p, pdata);
1711 len = (len + 3) & ~3;
1712 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1714 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1723 if (PTR_DIFF(p,pdata) > space_remaining) {
1724 /* Move the dirptr back to prev_dirpos */
1725 dptr_SeekDir(conn->dirptr, prev_dirpos);
1726 *out_of_space = True;
1727 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1728 return False; /* Not finished - just out of space */
1731 /* Setup the last entry pointer, as an offset from base_data */
1732 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1733 /* Advance the data pointer to the next slot */
1739 /****************************************************************************
1740 Reply to a TRANS2_FINDFIRST.
1741 ****************************************************************************/
1743 static void call_trans2findfirst(connection_struct *conn,
1744 struct smb_request *req,
1745 char **pparams, int total_params,
1746 char **ppdata, int total_data,
1747 unsigned int max_data_bytes)
1749 /* We must be careful here that we don't return more than the
1750 allowed number of data bytes. If this means returning fewer than
1751 maxentries then so be it. We assume that the redirector has
1752 enough room for the fixed number of parameter bytes it has
1754 char *params = *pparams;
1755 char *pdata = *ppdata;
1759 uint16 findfirst_flags;
1760 BOOL close_after_first;
1762 BOOL requires_resume_key;
1764 pstring directory_in;
1765 char *directory = NULL;
1768 int last_entry_off=0;
1772 BOOL finished = False;
1773 BOOL dont_descend = False;
1774 BOOL out_of_space = False;
1775 int space_remaining;
1776 BOOL mask_contains_wcard = False;
1777 SMB_STRUCT_STAT sbuf;
1778 TALLOC_CTX *ea_ctx = NULL;
1779 struct ea_list *ea_list = NULL;
1780 NTSTATUS ntstatus = NT_STATUS_OK;
1782 if (total_params < 13) {
1783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1787 dirtype = SVAL(params,0);
1788 maxentries = SVAL(params,2);
1789 findfirst_flags = SVAL(params,4);
1790 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1791 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1792 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1793 info_level = SVAL(params,6);
1795 *directory_in = *mask = 0;
1797 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1798 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1799 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1800 info_level, max_data_bytes));
1803 /* W2K3 seems to treat zero as 1. */
1807 switch (info_level) {
1808 case SMB_FIND_INFO_STANDARD:
1809 case SMB_FIND_EA_SIZE:
1810 case SMB_FIND_EA_LIST:
1811 case SMB_FIND_FILE_DIRECTORY_INFO:
1812 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1813 case SMB_FIND_FILE_NAMES_INFO:
1814 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1815 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1816 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1818 case SMB_FIND_FILE_UNIX:
1819 case SMB_FIND_FILE_UNIX_INFO2:
1820 if (!lp_unix_extensions()) {
1821 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1826 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1830 srvstr_get_path_wcard(params, req->flags2, directory_in,
1831 params+12, sizeof(directory_in), total_params - 12,
1832 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1833 if (!NT_STATUS_IS_OK(ntstatus)) {
1834 reply_nterror(req, ntstatus);
1838 ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory_in, &mask_contains_wcard);
1839 if (!NT_STATUS_IS_OK(ntstatus)) {
1840 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1841 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1842 ERRSRV, ERRbadpath);
1845 reply_nterror(req, ntstatus);
1849 ntstatus = unix_convert(conn, directory_in, True, &directory, NULL, &sbuf);
1850 if (!NT_STATUS_IS_OK(ntstatus)) {
1851 reply_nterror(req, ntstatus);
1855 ntstatus = check_name(conn, directory);
1856 if (!NT_STATUS_IS_OK(ntstatus)) {
1857 reply_nterror(req, ntstatus);
1861 p = strrchr_m(directory,'/');
1863 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1864 if((directory[0] == '.') && (directory[1] == '\0')) {
1866 mask_contains_wcard = True;
1868 pstrcpy(mask,directory);
1870 directory = talloc_strdup(talloc_tos(), "./");
1872 reply_nterror(req, NT_STATUS_NO_MEMORY);
1880 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1882 if (info_level == SMB_FIND_EA_LIST) {
1885 if (total_data < 4) {
1886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1890 ea_size = IVAL(pdata,0);
1891 if (ea_size != total_data) {
1892 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1893 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1898 if (!lp_ea_support(SNUM(conn))) {
1899 reply_doserror(req, ERRDOS, ERReasnotsupported);
1903 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1904 reply_nterror(req, NT_STATUS_NO_MEMORY);
1908 /* Pull out the list of names. */
1909 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1911 talloc_destroy(ea_ctx);
1912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1917 *ppdata = (char *)SMB_REALLOC(
1918 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1919 if(*ppdata == NULL ) {
1920 talloc_destroy(ea_ctx);
1921 reply_nterror(req, NT_STATUS_NO_MEMORY);
1925 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1927 /* Realloc the params space */
1928 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1929 if (*pparams == NULL) {
1930 talloc_destroy(ea_ctx);
1931 reply_nterror(req, NT_STATUS_NO_MEMORY);
1936 /* Save the wildcard match and attribs we are using on this directory -
1937 needed as lanman2 assumes these are being saved between calls */
1939 ntstatus = dptr_create(conn,
1945 mask_contains_wcard,
1949 if (!NT_STATUS_IS_OK(ntstatus)) {
1950 talloc_destroy(ea_ctx);
1951 reply_nterror(req, ntstatus);
1955 dptr_num = dptr_dnum(conn->dirptr);
1956 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1958 /* We don't need to check for VOL here as this is returned by
1959 a different TRANS2 call. */
1961 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1962 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1963 dont_descend = True;
1966 space_remaining = max_data_bytes;
1967 out_of_space = False;
1969 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1970 BOOL got_exact_match = False;
1972 /* this is a heuristic to avoid seeking the dirptr except when
1973 absolutely necessary. It allows for a filename of about 40 chars */
1974 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1975 out_of_space = True;
1978 finished = !get_lanman2_dir_entry(conn,
1980 mask,dirtype,info_level,
1981 requires_resume_key,dont_descend,
1983 space_remaining, &out_of_space,
1985 &last_entry_off, ea_list, ea_ctx);
1988 if (finished && out_of_space)
1991 if (!finished && !out_of_space)
1995 * As an optimisation if we know we aren't looking
1996 * for a wildcard name (ie. the name matches the wildcard exactly)
1997 * then we can finish on any (first) match.
1998 * This speeds up large directory searches. JRA.
2004 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2007 talloc_destroy(ea_ctx);
2009 /* Check if we can close the dirptr */
2010 if(close_after_first || (finished && close_if_end)) {
2011 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2012 dptr_close(&dptr_num);
2016 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2017 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2018 * the protocol level is less than NT1. Tested with smbclient. JRA.
2019 * This should fix the OS/2 client bug #2335.
2022 if(numentries == 0) {
2023 dptr_close(&dptr_num);
2024 if (Protocol < PROTOCOL_NT1) {
2025 reply_doserror(req, ERRDOS, ERRnofiles);
2028 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2029 ERRDOS, ERRbadfile);
2034 /* At this point pdata points to numentries directory entries. */
2036 /* Set up the return parameter block */
2037 SSVAL(params,0,dptr_num);
2038 SSVAL(params,2,numentries);
2039 SSVAL(params,4,finished);
2040 SSVAL(params,6,0); /* Never an EA error */
2041 SSVAL(params,8,last_entry_off);
2043 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2046 if ((! *directory) && dptr_path(dptr_num)) {
2047 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2049 reply_nterror(req, NT_STATUS_NO_MEMORY);
2053 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2054 smb_fn_name(CVAL(req->inbuf,smb_com)),
2055 mask, directory, dirtype, numentries ) );
2058 * Force a name mangle here to ensure that the
2059 * mask as an 8.3 name is top of the mangled cache.
2060 * The reasons for this are subtle. Don't remove
2061 * this code unless you know what you are doing
2062 * (see PR#13758). JRA.
2065 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2066 char mangled_name[13];
2067 name_to_8_3(mask, mangled_name, True, conn->params);
2073 /****************************************************************************
2074 Reply to a TRANS2_FINDNEXT.
2075 ****************************************************************************/
2077 static void call_trans2findnext(connection_struct *conn,
2078 struct smb_request *req,
2079 char **pparams, int total_params,
2080 char **ppdata, int total_data,
2081 unsigned int max_data_bytes)
2083 /* We must be careful here that we don't return more than the
2084 allowed number of data bytes. If this means returning fewer than
2085 maxentries then so be it. We assume that the redirector has
2086 enough room for the fixed number of parameter bytes it has
2088 char *params = *pparams;
2089 char *pdata = *ppdata;
2095 uint16 findnext_flags;
2096 BOOL close_after_request;
2098 BOOL requires_resume_key;
2100 BOOL mask_contains_wcard = False;
2101 pstring resume_name;
2107 int i, last_entry_off=0;
2108 BOOL finished = False;
2109 BOOL dont_descend = False;
2110 BOOL out_of_space = False;
2111 int space_remaining;
2112 TALLOC_CTX *ea_ctx = NULL;
2113 struct ea_list *ea_list = NULL;
2114 NTSTATUS ntstatus = NT_STATUS_OK;
2116 if (total_params < 13) {
2117 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2121 dptr_num = SVAL(params,0);
2122 maxentries = SVAL(params,2);
2123 info_level = SVAL(params,4);
2124 resume_key = IVAL(params,6);
2125 findnext_flags = SVAL(params,10);
2126 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2127 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2128 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2129 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2131 *mask = *directory = *resume_name = 0;
2133 srvstr_get_path_wcard(params, req->flags2, resume_name,
2134 params+12, sizeof(resume_name),
2135 total_params - 12, STR_TERMINATE, &ntstatus,
2136 &mask_contains_wcard);
2137 if (!NT_STATUS_IS_OK(ntstatus)) {
2138 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2139 complain (it thinks we're asking for the directory above the shared
2140 path or an invalid name). Catch this as the resume name is only compared, never used in
2141 a file access. JRA. */
2142 srvstr_pull(params, req->flags2,
2143 resume_name, params+12,
2144 sizeof(resume_name), total_params - 12,
2147 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2148 reply_nterror(req, ntstatus);
2153 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2154 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2155 resume_key = %d resume name = %s continue=%d level = %d\n",
2156 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2157 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2160 /* W2K3 seems to treat zero as 1. */
2164 switch (info_level) {
2165 case SMB_FIND_INFO_STANDARD:
2166 case SMB_FIND_EA_SIZE:
2167 case SMB_FIND_EA_LIST:
2168 case SMB_FIND_FILE_DIRECTORY_INFO:
2169 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2170 case SMB_FIND_FILE_NAMES_INFO:
2171 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2172 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2173 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2175 case SMB_FIND_FILE_UNIX:
2176 case SMB_FIND_FILE_UNIX_INFO2:
2177 if (!lp_unix_extensions()) {
2178 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2183 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2187 if (info_level == SMB_FIND_EA_LIST) {
2190 if (total_data < 4) {
2191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2195 ea_size = IVAL(pdata,0);
2196 if (ea_size != total_data) {
2197 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2198 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2203 if (!lp_ea_support(SNUM(conn))) {
2204 reply_doserror(req, ERRDOS, ERReasnotsupported);
2208 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2209 reply_nterror(req, NT_STATUS_NO_MEMORY);
2213 /* Pull out the list of names. */
2214 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2216 talloc_destroy(ea_ctx);
2217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2222 *ppdata = (char *)SMB_REALLOC(
2223 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2224 if(*ppdata == NULL) {
2225 talloc_destroy(ea_ctx);
2226 reply_nterror(req, NT_STATUS_NO_MEMORY);
2231 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2233 /* Realloc the params space */
2234 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2235 if(*pparams == NULL ) {
2236 talloc_destroy(ea_ctx);
2237 reply_nterror(req, NT_STATUS_NO_MEMORY);
2243 /* Check that the dptr is valid */
2244 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2245 talloc_destroy(ea_ctx);
2246 reply_doserror(req, ERRDOS, ERRnofiles);
2250 string_set(&conn->dirpath,dptr_path(dptr_num));
2252 /* Get the wildcard mask from the dptr */
2253 if((p = dptr_wcard(dptr_num))== NULL) {
2254 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2255 talloc_destroy(ea_ctx);
2256 reply_doserror(req, ERRDOS, ERRnofiles);
2261 pstrcpy(directory,conn->dirpath);
2263 /* Get the attr mask from the dptr */
2264 dirtype = dptr_attr(dptr_num);
2266 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2267 dptr_num, mask, dirtype,
2269 dptr_TellDir(conn->dirptr)));
2271 /* We don't need to check for VOL here as this is returned by
2272 a different TRANS2 call. */
2274 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2275 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2276 dont_descend = True;
2279 space_remaining = max_data_bytes;
2280 out_of_space = False;
2283 * Seek to the correct position. We no longer use the resume key but
2284 * depend on the last file name instead.
2287 if(*resume_name && !continue_bit) {
2290 long current_pos = 0;
2292 * Remember, name_to_8_3 is called by
2293 * get_lanman2_dir_entry(), so the resume name
2294 * could be mangled. Ensure we check the unmangled name.
2297 if (mangle_is_mangled(resume_name, conn->params)) {
2298 char *new_resume_name = NULL;
2299 mangle_lookup_name_from_8_3(talloc_tos(),
2303 if (new_resume_name) {
2304 pstrcpy(resume_name, new_resume_name);
2309 * Fix for NT redirector problem triggered by resume key indexes
2310 * changing between directory scans. We now return a resume key of 0
2311 * and instead look for the filename to continue from (also given
2312 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2313 * findfirst/findnext (as is usual) then the directory pointer
2314 * should already be at the correct place.
2317 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2318 } /* end if resume_name && !continue_bit */
2320 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2321 BOOL got_exact_match = False;
2323 /* this is a heuristic to avoid seeking the dirptr except when
2324 absolutely necessary. It allows for a filename of about 40 chars */
2325 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2326 out_of_space = True;
2329 finished = !get_lanman2_dir_entry(conn,
2331 mask,dirtype,info_level,
2332 requires_resume_key,dont_descend,
2334 space_remaining, &out_of_space,
2336 &last_entry_off, ea_list, ea_ctx);
2339 if (finished && out_of_space)
2342 if (!finished && !out_of_space)
2346 * As an optimisation if we know we aren't looking
2347 * for a wildcard name (ie. the name matches the wildcard exactly)
2348 * then we can finish on any (first) match.
2349 * This speeds up large directory searches. JRA.
2355 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2358 talloc_destroy(ea_ctx);
2360 /* Check if we can close the dirptr */
2361 if(close_after_request || (finished && close_if_end)) {
2362 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2363 dptr_close(&dptr_num); /* This frees up the saved mask */
2366 /* Set up the return parameter block */
2367 SSVAL(params,0,numentries);
2368 SSVAL(params,2,finished);
2369 SSVAL(params,4,0); /* Never an EA error */
2370 SSVAL(params,6,last_entry_off);
2372 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2375 if ((! *directory) && dptr_path(dptr_num))
2376 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2378 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2379 smb_fn_name(CVAL(req->inbuf,smb_com)),
2380 mask, directory, dirtype, numentries ) );
2385 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2387 E_md4hash(lp_servicename(SNUM(conn)),objid);
2391 /****************************************************************************
2392 Reply to a TRANS2_QFSINFO (query filesystem info).
2393 ****************************************************************************/
2395 static void call_trans2qfsinfo(connection_struct *conn,
2396 struct smb_request *req,
2397 char **pparams, int total_params,
2398 char **ppdata, int total_data,
2399 unsigned int max_data_bytes)
2401 char *pdata, *end_data;
2402 char *params = *pparams;
2406 const char *vname = volume_label(SNUM(conn));
2407 int snum = SNUM(conn);
2408 char *fstype = lp_fstype(SNUM(conn));
2411 if (total_params < 2) {
2412 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2416 info_level = SVAL(params,0);
2418 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2420 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2421 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2422 reply_doserror(req, ERRSRV, ERRinvdevice);
2426 *ppdata = (char *)SMB_REALLOC(
2427 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2428 if (*ppdata == NULL ) {
2429 reply_nterror(req, NT_STATUS_NO_MEMORY);
2434 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2435 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2437 switch (info_level) {
2438 case SMB_INFO_ALLOCATION:
2440 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2442 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2443 reply_unixerror(req, ERRHRD, ERRgeneral);
2447 block_size = lp_block_size(snum);
2448 if (bsize < block_size) {
2449 SMB_BIG_UINT factor = block_size/bsize;
2454 if (bsize > block_size) {
2455 SMB_BIG_UINT factor = bsize/block_size;
2460 bytes_per_sector = 512;
2461 sectors_per_unit = bsize/bytes_per_sector;
2463 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2464 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2465 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2467 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2468 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2469 SIVAL(pdata,l1_cUnit,dsize);
2470 SIVAL(pdata,l1_cUnitAvail,dfree);
2471 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2475 case SMB_INFO_VOLUME:
2476 /* Return volume name */
2478 * Add volume serial number - hash of a combination of
2479 * the called hostname and the service name.
2481 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2483 * Win2k3 and previous mess this up by sending a name length
2484 * one byte short. I believe only older clients (OS/2 Win9x) use
2485 * this call so try fixing this by adding a terminating null to
2486 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2490 pdata+l2_vol_szVolLabel, vname,
2491 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2492 STR_NOALIGN|STR_TERMINATE);
2493 SCVAL(pdata,l2_vol_cch,len);
2494 data_len = l2_vol_szVolLabel + len;
2495 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2496 (unsigned)st.st_ctime, len, vname));
2499 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2500 case SMB_FS_ATTRIBUTE_INFORMATION:
2503 #if defined(HAVE_SYS_QUOTAS)
2504 quota_flag = FILE_VOLUME_QUOTAS;
2507 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2508 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2509 FILE_SUPPORTS_OBJECT_IDS|
2510 FILE_UNICODE_ON_DISK|
2511 quota_flag); /* FS ATTRIBUTES */
2513 SIVAL(pdata,4,255); /* Max filename component length */
2514 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2515 and will think we can't do long filenames */
2516 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2517 PTR_DIFF(end_data, pdata+12),
2520 data_len = 12 + len;
2523 case SMB_QUERY_FS_LABEL_INFO:
2524 case SMB_FS_LABEL_INFORMATION:
2525 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2526 PTR_DIFF(end_data, pdata+4), 0);
2531 case SMB_QUERY_FS_VOLUME_INFO:
2532 case SMB_FS_VOLUME_INFORMATION:
2535 * Add volume serial number - hash of a combination of
2536 * the called hostname and the service name.
2538 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2539 (str_checksum(get_local_machine_name())<<16));
2541 /* Max label len is 32 characters. */
2542 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2543 PTR_DIFF(end_data, pdata+18),
2545 SIVAL(pdata,12,len);
2548 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2549 (int)strlen(vname),vname, lp_servicename(snum)));
2552 case SMB_QUERY_FS_SIZE_INFO:
2553 case SMB_FS_SIZE_INFORMATION:
2555 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2557 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2558 reply_unixerror(req, ERRHRD, ERRgeneral);
2561 block_size = lp_block_size(snum);
2562 if (bsize < block_size) {
2563 SMB_BIG_UINT factor = block_size/bsize;
2568 if (bsize > block_size) {
2569 SMB_BIG_UINT factor = bsize/block_size;
2574 bytes_per_sector = 512;
2575 sectors_per_unit = bsize/bytes_per_sector;
2576 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2577 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2578 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2579 SBIG_UINT(pdata,0,dsize);
2580 SBIG_UINT(pdata,8,dfree);
2581 SIVAL(pdata,16,sectors_per_unit);
2582 SIVAL(pdata,20,bytes_per_sector);
2586 case SMB_FS_FULL_SIZE_INFORMATION:
2588 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2590 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2591 reply_unixerror(req, ERRHRD, ERRgeneral);
2594 block_size = lp_block_size(snum);
2595 if (bsize < block_size) {
2596 SMB_BIG_UINT factor = block_size/bsize;
2601 if (bsize > block_size) {
2602 SMB_BIG_UINT factor = bsize/block_size;
2607 bytes_per_sector = 512;
2608 sectors_per_unit = bsize/bytes_per_sector;
2609 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2610 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2611 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2612 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2613 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2614 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2615 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2616 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2620 case SMB_QUERY_FS_DEVICE_INFO:
2621 case SMB_FS_DEVICE_INFORMATION:
2623 SIVAL(pdata,0,0); /* dev type */
2624 SIVAL(pdata,4,0); /* characteristics */
2627 #ifdef HAVE_SYS_QUOTAS
2628 case SMB_FS_QUOTA_INFORMATION:
2630 * what we have to send --metze:
2632 * Unknown1: 24 NULL bytes
2633 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2634 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2635 * Quota Flags: 2 byte :
2636 * Unknown3: 6 NULL bytes
2640 * details for Quota Flags:
2642 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2643 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2644 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2645 * 0x0001 Enable Quotas: enable quota for this fs
2649 /* we need to fake up a fsp here,
2650 * because its not send in this call
2653 SMB_NTQUOTA_STRUCT quotas;
2656 ZERO_STRUCT(quotas);
2662 if (current_user.ut.uid != 0) {
2663 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2664 lp_servicename(SNUM(conn)),conn->user));
2665 reply_doserror(req, ERRDOS, ERRnoaccess);
2669 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2670 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2671 reply_doserror(req, ERRSRV, ERRerror);
2677 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2679 /* Unknown1 24 NULL bytes*/
2680 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2681 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2682 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2684 /* Default Soft Quota 8 bytes */
2685 SBIG_UINT(pdata,24,quotas.softlim);
2687 /* Default Hard Quota 8 bytes */
2688 SBIG_UINT(pdata,32,quotas.hardlim);
2690 /* Quota flag 2 bytes */
2691 SSVAL(pdata,40,quotas.qflags);
2693 /* Unknown3 6 NULL bytes */
2699 #endif /* HAVE_SYS_QUOTAS */
2700 case SMB_FS_OBJECTID_INFORMATION:
2702 unsigned char objid[16];
2703 memcpy(pdata,create_volume_objectid(conn, objid),16);
2709 * Query the version and capabilities of the CIFS UNIX extensions
2713 case SMB_QUERY_CIFS_UNIX_INFO:
2714 if (!lp_unix_extensions()) {
2715 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2719 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2720 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2721 /* We have POSIX ACLs, pathname and locking capability. */
2722 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2723 CIFS_UNIX_POSIX_ACLS_CAP|
2724 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2725 CIFS_UNIX_FCNTL_LOCKS_CAP|
2726 CIFS_UNIX_EXTATTR_CAP|
2727 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2728 /* Ensure we don't do this on signed or sealed data. */
2729 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2733 case SMB_QUERY_POSIX_FS_INFO:
2736 vfs_statvfs_struct svfs;
2738 if (!lp_unix_extensions()) {
2739 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2743 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2747 SIVAL(pdata,0,svfs.OptimalTransferSize);
2748 SIVAL(pdata,4,svfs.BlockSize);
2749 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2750 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2751 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2752 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2753 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2754 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2755 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2757 } else if (rc == EOPNOTSUPP) {
2758 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2760 #endif /* EOPNOTSUPP */
2762 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2763 reply_doserror(req, ERRSRV, ERRerror);
2769 case SMB_QUERY_POSIX_WHOAMI:
2775 if (!lp_unix_extensions()) {
2776 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2780 if (max_data_bytes < 40) {
2781 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2785 /* We ARE guest if global_sid_Builtin_Guests is
2786 * in our list of SIDs.
2788 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2789 current_user.nt_user_token)) {
2790 flags |= SMB_WHOAMI_GUEST;
2793 /* We are NOT guest if global_sid_Authenticated_Users
2794 * is in our list of SIDs.
2796 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2797 current_user.nt_user_token)) {
2798 flags &= ~SMB_WHOAMI_GUEST;
2801 /* NOTE: 8 bytes for UID/GID, irrespective of native
2802 * platform size. This matches
2803 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2805 data_len = 4 /* flags */
2812 + 4 /* pad/reserved */
2813 + (current_user.ut.ngroups * 8)
2815 + (current_user.nt_user_token->num_sids *
2819 SIVAL(pdata, 0, flags);
2820 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2821 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2822 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2825 if (data_len >= max_data_bytes) {
2826 /* Potential overflow, skip the GIDs and SIDs. */
2828 SIVAL(pdata, 24, 0); /* num_groups */
2829 SIVAL(pdata, 28, 0); /* num_sids */
2830 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2831 SIVAL(pdata, 36, 0); /* reserved */
2837 SIVAL(pdata, 24, current_user.ut.ngroups);
2839 current_user.nt_user_token->num_sids);
2841 /* We walk the SID list twice, but this call is fairly
2842 * infrequent, and I don't expect that it's performance
2843 * sensitive -- jpeach
2845 for (i = 0, sid_bytes = 0;
2846 i < current_user.nt_user_token->num_sids; ++i) {
2848 sid_size(¤t_user.nt_user_token->user_sids[i]);
2851 /* SID list byte count */
2852 SIVAL(pdata, 32, sid_bytes);
2854 /* 4 bytes pad/reserved - must be zero */
2855 SIVAL(pdata, 36, 0);
2859 for (i = 0; i < current_user.ut.ngroups; ++i) {
2860 SBIG_UINT(pdata, data_len,
2861 (SMB_BIG_UINT)current_user.ut.groups[i]);
2867 i < current_user.nt_user_token->num_sids; ++i) {
2869 sid_size(¤t_user.nt_user_token->user_sids[i]);
2871 sid_linearize(pdata + data_len, sid_len,
2872 ¤t_user.nt_user_token->user_sids[i]);
2873 data_len += sid_len;
2879 case SMB_MAC_QUERY_FS_INFO:
2881 * Thursby MAC extension... ONLY on NTFS filesystems
2882 * once we do streams then we don't need this
2884 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2886 SIVAL(pdata,84,0x100); /* Don't support mac... */
2891 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2896 send_trans2_replies(req, params, 0, pdata, data_len,
2899 DEBUG( 4, ( "%s info_level = %d\n",
2900 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2905 /****************************************************************************
2906 Reply to a TRANS2_SETFSINFO (set filesystem info).
2907 ****************************************************************************/
2909 static void call_trans2setfsinfo(connection_struct *conn,
2910 struct smb_request *req,
2911 char **pparams, int total_params,
2912 char **ppdata, int total_data,
2913 unsigned int max_data_bytes)
2915 char *pdata = *ppdata;
2916 char *params = *pparams;
2919 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2922 if (total_params < 4) {
2923 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2925 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2929 info_level = SVAL(params,2);
2931 switch(info_level) {
2932 case SMB_SET_CIFS_UNIX_INFO:
2934 uint16 client_unix_major;
2935 uint16 client_unix_minor;
2936 uint32 client_unix_cap_low;
2937 uint32 client_unix_cap_high;
2939 if (!lp_unix_extensions()) {
2941 NT_STATUS_INVALID_LEVEL);
2945 /* There should be 12 bytes of capabilities set. */
2946 if (total_data < 8) {
2949 NT_STATUS_INVALID_PARAMETER);
2952 client_unix_major = SVAL(pdata,0);
2953 client_unix_minor = SVAL(pdata,2);
2954 client_unix_cap_low = IVAL(pdata,4);
2955 client_unix_cap_high = IVAL(pdata,8);
2956 /* Just print these values for now. */
2957 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2958 cap_low = 0x%x, cap_high = 0x%x\n",
2959 (unsigned int)client_unix_major,
2960 (unsigned int)client_unix_minor,
2961 (unsigned int)client_unix_cap_low,
2962 (unsigned int)client_unix_cap_high ));
2964 /* Here is where we must switch to posix pathname processing... */
2965 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2966 lp_set_posix_pathnames();
2967 mangle_change_to_posix();
2970 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2971 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2972 /* Client that knows how to do posix locks,
2973 * but not posix open/mkdir operations. Set a
2974 * default type for read/write checks. */
2976 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2981 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2984 size_t param_len = 0;
2985 size_t data_len = total_data;
2987 if (!lp_unix_extensions()) {
2989 req, NT_STATUS_INVALID_LEVEL);
2993 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2995 status = srv_request_encryption_setup(conn,
2996 (unsigned char **)ppdata,
2998 (unsigned char **)pparams,
3002 if (!NT_STATUS_IS_OK(status)) {
3005 * MORE_PROCESSING_REQUIRED, this used
3006 * to have special handling here.
3008 reply_nterror(req, status);
3012 send_trans2_replies(req,
3013 *pparams, param_len,
3017 if (NT_STATUS_IS_OK(status)) {
3018 /* Server-side transport encryption is now *on*. */
3019 status = srv_encryption_start(conn);
3020 if (!NT_STATUS_IS_OK(status)) {
3021 exit_server_cleanly("Failure in setting up encrypted transport");
3026 case SMB_FS_QUOTA_INFORMATION:
3028 files_struct *fsp = NULL;
3029 SMB_NTQUOTA_STRUCT quotas;
3031 ZERO_STRUCT(quotas);
3034 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3035 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3036 lp_servicename(SNUM(conn)),conn->user));
3037 reply_doserror(req, ERRSRV, ERRaccess);
3041 /* note: normaly there're 48 bytes,
3042 * but we didn't use the last 6 bytes for now
3045 fsp = file_fsp(SVAL(params,0));
3046 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3047 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3049 req, NT_STATUS_INVALID_HANDLE);
3053 if (total_data < 42) {
3054 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3058 NT_STATUS_INVALID_PARAMETER);
3062 /* unknown_1 24 NULL bytes in pdata*/
3064 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3065 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3066 #ifdef LARGE_SMB_OFF_T
3067 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3068 #else /* LARGE_SMB_OFF_T */
3069 if ((IVAL(pdata,28) != 0)&&
3070 ((quotas.softlim != 0xFFFFFFFF)||
3071 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3072 /* more than 32 bits? */
3075 NT_STATUS_INVALID_PARAMETER);
3078 #endif /* LARGE_SMB_OFF_T */
3080 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3081 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3082 #ifdef LARGE_SMB_OFF_T
3083 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3084 #else /* LARGE_SMB_OFF_T */
3085 if ((IVAL(pdata,36) != 0)&&
3086 ((quotas.hardlim != 0xFFFFFFFF)||
3087 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3088 /* more than 32 bits? */
3091 NT_STATUS_INVALID_PARAMETER);
3094 #endif /* LARGE_SMB_OFF_T */
3096 /* quota_flags 2 bytes **/
3097 quotas.qflags = SVAL(pdata,40);
3099 /* unknown_2 6 NULL bytes follow*/
3101 /* now set the quotas */
3102 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3103 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3104 reply_doserror(req, ERRSRV, ERRerror);
3111 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3113 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3119 * sending this reply works fine,
3120 * but I'm not sure it's the same
3121 * like windows do...
3124 reply_outbuf(req, 10, 0);
3127 #if defined(HAVE_POSIX_ACLS)
3128 /****************************************************************************
3129 Utility function to count the number of entries in a POSIX acl.
3130 ****************************************************************************/
3132 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3134 unsigned int ace_count = 0;
3135 int entry_id = SMB_ACL_FIRST_ENTRY;
3136 SMB_ACL_ENTRY_T entry;
3138 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3140 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3141 entry_id = SMB_ACL_NEXT_ENTRY;
3148 /****************************************************************************
3149 Utility function to marshall a POSIX acl into wire format.
3150 ****************************************************************************/
3152 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3154 int entry_id = SMB_ACL_FIRST_ENTRY;
3155 SMB_ACL_ENTRY_T entry;
3157 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3158 SMB_ACL_TAG_T tagtype;
3159 SMB_ACL_PERMSET_T permset;
3160 unsigned char perms = 0;
3161 unsigned int own_grp;
3164 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3165 entry_id = SMB_ACL_NEXT_ENTRY;
3168 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3169 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3173 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3174 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3178 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3179 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3180 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3182 SCVAL(pdata,1,perms);
3185 case SMB_ACL_USER_OBJ:
3186 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3187 own_grp = (unsigned int)pst->st_uid;
3188 SIVAL(pdata,2,own_grp);
3193 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3195 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3198 own_grp = (unsigned int)*puid;
3199 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3200 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3201 SIVAL(pdata,2,own_grp);
3205 case SMB_ACL_GROUP_OBJ:
3206 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3207 own_grp = (unsigned int)pst->st_gid;
3208 SIVAL(pdata,2,own_grp);
3213 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3215 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3218 own_grp = (unsigned int)*pgid;
3219 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3220 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3221 SIVAL(pdata,2,own_grp);
3226 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3227 SIVAL(pdata,2,0xFFFFFFFF);
3228 SIVAL(pdata,6,0xFFFFFFFF);
3231 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3232 SIVAL(pdata,2,0xFFFFFFFF);
3233 SIVAL(pdata,6,0xFFFFFFFF);
3236 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3239 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3246 /****************************************************************************
3247 Store the FILE_UNIX_BASIC info.
3248 ****************************************************************************/
3250 static char *store_file_unix_basic(connection_struct *conn,
3253 const SMB_STRUCT_STAT *psbuf)
3255 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3256 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3258 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3261 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3264 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3265 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3266 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3269 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3273 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3277 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3280 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3284 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3288 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3291 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3295 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3302 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3303 * the chflags(2) (or equivalent) flags.
3305 * XXX: this really should be behind the VFS interface. To do this, we would
3306 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3307 * Each VFS module could then implement it's own mapping as appropriate for the
3308 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3310 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3314 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3318 { UF_IMMUTABLE, EXT_IMMUTABLE },
3322 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3326 { UF_HIDDEN, EXT_HIDDEN },
3329 /* Do not remove. We need to guarantee that this array has at least one
3330 * entry to build on HP-UX.
3336 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3337 uint32 *smb_fflags, uint32 *smb_fmask)
3339 #ifdef HAVE_STAT_ST_FLAGS
3342 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3343 *smb_fmask |= info2_flags_map[i].smb_fflag;
3344 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3345 *smb_fflags |= info2_flags_map[i].smb_fflag;
3348 #endif /* HAVE_STAT_ST_FLAGS */
3351 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3352 const uint32 smb_fflags,
3353 const uint32 smb_fmask,
3356 #ifdef HAVE_STAT_ST_FLAGS
3357 uint32 max_fmask = 0;
3360 *stat_fflags = psbuf->st_flags;
3362 /* For each flags requested in smb_fmask, check the state of the
3363 * corresponding flag in smb_fflags and set or clear the matching
3367 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3368 max_fmask |= info2_flags_map[i].smb_fflag;
3369 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3370 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3371 *stat_fflags |= info2_flags_map[i].stat_fflag;
3373 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3378 /* If smb_fmask is asking to set any bits that are not supported by
3379 * our flag mappings, we should fail.
3381 if ((smb_fmask & max_fmask) != smb_fmask) {
3388 #endif /* HAVE_STAT_ST_FLAGS */
3392 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3393 * of file flags and birth (create) time.
3395 static char *store_file_unix_basic_info2(connection_struct *conn,
3398 const SMB_STRUCT_STAT *psbuf)
3400 uint32 file_flags = 0;
3401 uint32 flags_mask = 0;
3403 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3405 /* Create (birth) time 64 bit */
3406 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3409 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3410 SIVAL(pdata, 0, file_flags); /* flags */
3411 SIVAL(pdata, 4, flags_mask); /* mask */
3417 /****************************************************************************
3418 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3419 ****************************************************************************/
3421 static void call_trans2qpipeinfo(connection_struct *conn,
3422 struct smb_request *req,
3423 unsigned int tran_call,
3424 char **pparams, int total_params,
3425 char **ppdata, int total_data,
3426 unsigned int max_data_bytes)
3428 char *params = *pparams;
3429 char *pdata = *ppdata;
3430 unsigned int data_size = 0;
3431 unsigned int param_size = 2;
3433 smb_np_struct *p_pipe = NULL;
3436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3440 if (total_params < 4) {
3441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3445 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3446 if (p_pipe == NULL) {
3447 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3451 info_level = SVAL(params,2);
3453 *pparams = (char *)SMB_REALLOC(*pparams,2);
3454 if (*pparams == NULL) {
3455 reply_nterror(req, NT_STATUS_NO_MEMORY);
3460 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3461 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3462 if (*ppdata == NULL ) {
3463 reply_nterror(req, NT_STATUS_NO_MEMORY);
3468 switch (info_level) {
3469 case SMB_FILE_STANDARD_INFORMATION:
3471 SOFF_T(pdata,0,4096LL);
3478 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3482 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3488 /****************************************************************************
3489 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3490 file name or file id).
3491 ****************************************************************************/
3493 static void call_trans2qfilepathinfo(connection_struct *conn,
3494 struct smb_request *req,
3495 unsigned int tran_call,
3496 char **pparams, int total_params,
3497 char **ppdata, int total_data,
3498 unsigned int max_data_bytes)
3500 char *params = *pparams;
3501 char *pdata = *ppdata;
3502 char *dstart, *dend;
3506 SMB_OFF_T file_size=0;
3507 SMB_BIG_UINT allocation_size=0;
3508 unsigned int data_size = 0;
3509 unsigned int param_size = 2;
3510 SMB_STRUCT_STAT sbuf;
3517 BOOL delete_pending = False;
3519 time_t create_time, mtime, atime;
3520 struct timespec create_time_ts, mtime_ts, atime_ts;
3521 files_struct *fsp = NULL;
3522 struct file_id fileid;
3523 TALLOC_CTX *data_ctx = NULL;
3524 struct ea_list *ea_list = NULL;
3525 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3526 char *lock_data = NULL;
3529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3535 if (tran_call == TRANSACT2_QFILEINFO) {
3536 if (total_params < 4) {
3537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3542 call_trans2qpipeinfo(conn, req, tran_call,
3543 pparams, total_params,
3549 fsp = file_fsp(SVAL(params,0));
3550 info_level = SVAL(params,2);
3552 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3554 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3555 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3559 /* Initial check for valid fsp ptr. */
3560 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3564 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3566 reply_nterror(req, NT_STATUS_NO_MEMORY);
3570 if(fsp->fake_file_handle) {
3572 * This is actually for the QUOTA_FAKE_FILE --metze
3575 /* We know this name is ok, it's already passed the checks. */
3577 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3579 * This is actually a QFILEINFO on a directory
3580 * handle (returned from an NT SMB). NT5.0 seems
3581 * to do this call. JRA.
3584 if (INFO_LEVEL_IS_UNIX(info_level)) {
3585 /* Always do lstat for UNIX calls. */
3586 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3587 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3588 reply_unixerror(req,ERRDOS,ERRbadpath);
3591 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3592 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3593 reply_unixerror(req, ERRDOS, ERRbadpath);
3597 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3598 delete_pending = get_delete_on_close_flag(fileid);
3601 * Original code - this is an open file.
3603 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3607 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3608 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3609 reply_unixerror(req, ERRDOS, ERRbadfid);
3612 pos = fsp->fh->position_information;
3613 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3614 delete_pending = get_delete_on_close_flag(fileid);
3615 access_mask = fsp->access_mask;
3620 NTSTATUS status = NT_STATUS_OK;
3623 if (total_params < 7) {
3624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3628 info_level = SVAL(params,0);
3630 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3632 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3633 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3637 srvstr_get_path(params, req->flags2, fname_in, ¶ms[6],
3638 sizeof(fname_in), total_params - 6,
3639 STR_TERMINATE, &status);
3640 if (!NT_STATUS_IS_OK(status)) {
3641 reply_nterror(req, status);
3645 status = resolve_dfspath(conn,
3646 req->flags2 & FLAGS2_DFS_PATHNAMES,
3648 if (!NT_STATUS_IS_OK(status)) {
3649 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3650 reply_botherror(req,
3651 NT_STATUS_PATH_NOT_COVERED,
3652 ERRSRV, ERRbadpath);
3654 reply_nterror(req, status);
3658 status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 reply_nterror(req, status);
3663 status = check_name(conn, fname);
3664 if (!NT_STATUS_IS_OK(status)) {
3665 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3666 reply_nterror(req, status);
3670 if (INFO_LEVEL_IS_UNIX(info_level)) {
3671 /* Always do lstat for UNIX calls. */
3672 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3673 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3674 reply_unixerror(req, ERRDOS, ERRbadpath);
3677 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3678 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3679 reply_unixerror(req, ERRDOS, ERRbadpath);
3683 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3684 delete_pending = get_delete_on_close_flag(fileid);
3685 if (delete_pending) {
3686 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3691 nlink = sbuf.st_nlink;
3693 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3694 /* NTFS does not seem to count ".." */
3698 if ((nlink > 0) && delete_pending) {
3702 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3703 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3707 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3708 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3710 p = strrchr_m(fname,'/');
3716 mode = dos_mode(conn,fname,&sbuf);
3718 mode = FILE_ATTRIBUTE_NORMAL;
3720 fullpathname = fname;
3722 file_size = get_file_size(sbuf);
3724 /* Pull out any data sent here before we realloc. */
3725 switch (info_level) {
3726 case SMB_INFO_QUERY_EAS_FROM_LIST:
3728 /* Pull any EA list from the data portion. */
3731 if (total_data < 4) {
3733 req, NT_STATUS_INVALID_PARAMETER);
3736 ea_size = IVAL(pdata,0);
3738 if (total_data > 0 && ea_size != total_data) {
3739 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3740 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3742 req, NT_STATUS_INVALID_PARAMETER);
3746 if (!lp_ea_support(SNUM(conn))) {
3747 reply_doserror(req, ERRDOS,
3748 ERReasnotsupported);
3752 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3753 reply_nterror(req, NT_STATUS_NO_MEMORY);
3757 /* Pull out the list of names. */
3758 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3760 talloc_destroy(data_ctx);
3762 req, NT_STATUS_INVALID_PARAMETER);
3768 case SMB_QUERY_POSIX_LOCK:
3770 if (fsp == NULL || fsp->fh->fd == -1) {
3771 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3775 if (total_data != POSIX_LOCK_DATA_SIZE) {
3777 req, NT_STATUS_INVALID_PARAMETER);
3781 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3782 reply_nterror(req, NT_STATUS_NO_MEMORY);
3786 /* Copy the lock range data. */
3787 lock_data = (char *)TALLOC_MEMDUP(
3788 data_ctx, pdata, total_data);
3790 talloc_destroy(data_ctx);
3791 reply_nterror(req, NT_STATUS_NO_MEMORY);
3799 *pparams = (char *)SMB_REALLOC(*pparams,2);
3800 if (*pparams == NULL) {
3801 talloc_destroy(data_ctx);
3802 reply_nterror(req, NT_STATUS_NO_MEMORY);
3807 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3808 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3809 if (*ppdata == NULL ) {
3810 talloc_destroy(data_ctx);
3811 reply_nterror(req, NT_STATUS_NO_MEMORY);
3816 dend = dstart + data_size - 1;
3818 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3819 mtime_ts = get_mtimespec(&sbuf);
3820 atime_ts = get_atimespec(&sbuf);
3822 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3825 if (!null_timespec(fsp->pending_modtime)) {
3826 /* the pending modtime overrides the current modtime */
3827 mtime_ts = fsp->pending_modtime;
3831 /* Do we have this path open ? */
3832 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3833 fsp1 = file_find_di_first(fileid);
3834 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3835 /* the pending modtime overrides the current modtime */
3836 mtime_ts = fsp1->pending_modtime;
3838 if (fsp1 && fsp1->initial_allocation_size) {
3839 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3843 if (lp_dos_filetime_resolution(SNUM(conn))) {
3844 dos_filetime_timespec(&create_time_ts);
3845 dos_filetime_timespec(&mtime_ts);
3846 dos_filetime_timespec(&atime_ts);
3849 create_time = convert_timespec_to_time_t(create_time_ts);
3850 mtime = convert_timespec_to_time_t(mtime_ts);
3851 atime = convert_timespec_to_time_t(atime_ts);
3853 /* NT expects the name to be in an exact form of the *full*
3854 filename. See the trans2 torture test */
3855 if (strequal(base_name,".")) {
3856 pstrcpy(dos_fname, "\\");
3858 pstr_sprintf(dos_fname, "\\%s", fname);
3859 string_replace(dos_fname, '/', '\\');
3862 switch (info_level) {
3863 case SMB_INFO_STANDARD:
3864 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3866 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3867 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3868 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3869 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3870 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3871 SSVAL(pdata,l1_attrFile,mode);
3874 case SMB_INFO_QUERY_EA_SIZE:
3876 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3877 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3879 srv_put_dos_date2(pdata,0,create_time);
3880 srv_put_dos_date2(pdata,4,atime);
3881 srv_put_dos_date2(pdata,8,mtime); /* write time */
3882 SIVAL(pdata,12,(uint32)file_size);
3883 SIVAL(pdata,16,(uint32)allocation_size);
3884 SSVAL(pdata,20,mode);
3885 SIVAL(pdata,22,ea_size);
3889 case SMB_INFO_IS_NAME_VALID:
3890 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3891 if (tran_call == TRANSACT2_QFILEINFO) {
3892 /* os/2 needs this ? really ?*/
3893 reply_doserror(req, ERRDOS, ERRbadfunc);
3900 case SMB_INFO_QUERY_EAS_FROM_LIST:
3902 size_t total_ea_len = 0;
3903 struct ea_list *ea_file_list = NULL;
3905 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3907 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3908 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3910 if (!ea_list || (total_ea_len > data_size)) {
3911 talloc_destroy(data_ctx);
3913 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3917 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3918 talloc_destroy(data_ctx);
3922 case SMB_INFO_QUERY_ALL_EAS:
3924 /* We have data_size bytes to put EA's into. */
3925 size_t total_ea_len = 0;
3927 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3929 data_ctx = talloc_init("ea_ctx");
3931 reply_nterror(req, NT_STATUS_NO_MEMORY);
3935 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3936 if (!ea_list || (total_ea_len > data_size)) {
3937 talloc_destroy(data_ctx);
3939 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3943 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3944 talloc_destroy(data_ctx);
3948 case SMB_FILE_BASIC_INFORMATION:
3949 case SMB_QUERY_FILE_BASIC_INFO:
3951 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3952 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3953 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3955 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3959 put_long_date_timespec(pdata,create_time_ts);
3960 put_long_date_timespec(pdata+8,atime_ts);
3961 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3962 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3963 SIVAL(pdata,32,mode);
3965 DEBUG(5,("SMB_QFBI - "));
3966 DEBUG(5,("create: %s ", ctime(&create_time)));
3967 DEBUG(5,("access: %s ", ctime(&atime)));
3968 DEBUG(5,("write: %s ", ctime(&mtime)));
3969 DEBUG(5,("change: %s ", ctime(&mtime)));
3970 DEBUG(5,("mode: %x\n", mode));
3973 case SMB_FILE_STANDARD_INFORMATION:
3974 case SMB_QUERY_FILE_STANDARD_INFO:
3976 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3978 SOFF_T(pdata,0,allocation_size);
3979 SOFF_T(pdata,8,file_size);
3980 SIVAL(pdata,16,nlink);
3981 SCVAL(pdata,20,delete_pending?1:0);
3982 SCVAL(pdata,21,(mode&aDIR)?1:0);
3983 SSVAL(pdata,22,0); /* Padding. */
3986 case SMB_FILE_EA_INFORMATION:
3987 case SMB_QUERY_FILE_EA_INFO:
3989 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3990 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3992 SIVAL(pdata,0,ea_size);
3996 /* Get the 8.3 name - used if NT SMB was negotiated. */
3997 case SMB_QUERY_FILE_ALT_NAME_INFO:
3998 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4000 char mangled_name[13];
4001 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4002 if (!name_to_8_3(base_name,mangled_name,
4003 True,conn->params)) {
4006 NT_STATUS_NO_MEMORY);
4008 len = srvstr_push(dstart, req->flags2,
4009 pdata+4, mangled_name,
4010 PTR_DIFF(dend, pdata+4),
4012 data_size = 4 + len;
4017 case SMB_QUERY_FILE_NAME_INFO:
4019 this must be *exactly* right for ACLs on mapped drives to work
4021 len = srvstr_push(dstart, req->flags2,
4023 PTR_DIFF(dend, pdata+4),
4025 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4026 data_size = 4 + len;
4030 case SMB_FILE_ALLOCATION_INFORMATION:
4031 case SMB_QUERY_FILE_ALLOCATION_INFO:
4032 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4034 SOFF_T(pdata,0,allocation_size);
4037 case SMB_FILE_END_OF_FILE_INFORMATION:
4038 case SMB_QUERY_FILE_END_OF_FILEINFO:
4039 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4041 SOFF_T(pdata,0,file_size);
4044 case SMB_QUERY_FILE_ALL_INFO:
4045 case SMB_FILE_ALL_INFORMATION:
4047 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4048 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4049 put_long_date_timespec(pdata,create_time_ts);
4050 put_long_date_timespec(pdata+8,atime_ts);
4051 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4052 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4053 SIVAL(pdata,32,mode);
4054 SIVAL(pdata,36,0); /* padding. */
4056 SOFF_T(pdata,0,allocation_size);
4057 SOFF_T(pdata,8,file_size);
4058 SIVAL(pdata,16,nlink);
4059 SCVAL(pdata,20,delete_pending);
4060 SCVAL(pdata,21,(mode&aDIR)?1:0);
4063 SIVAL(pdata,0,ea_size);
4064 pdata += 4; /* EA info */
4065 len = srvstr_push(dstart, req->flags2,
4067 PTR_DIFF(dend, pdata+4),
4071 data_size = PTR_DIFF(pdata,(*ppdata));
4074 case SMB_FILE_INTERNAL_INFORMATION:
4075 /* This should be an index number - looks like
4078 I think this causes us to fail the IFSKIT
4079 BasicFileInformationTest. -tpot */
4081 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4082 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4083 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4087 case SMB_FILE_ACCESS_INFORMATION:
4088 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4089 SIVAL(pdata,0,access_mask);
4093 case SMB_FILE_NAME_INFORMATION:
4094 /* Pathname with leading '\'. */
4097 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4098 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4099 SIVAL(pdata,0,byte_len);
4100 data_size = 4 + byte_len;
4104 case SMB_FILE_DISPOSITION_INFORMATION:
4105 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4107 SCVAL(pdata,0,delete_pending);
4110 case SMB_FILE_POSITION_INFORMATION:
4111 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4113 SOFF_T(pdata,0,pos);
4116 case SMB_FILE_MODE_INFORMATION:
4117 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4118 SIVAL(pdata,0,mode);
4122 case SMB_FILE_ALIGNMENT_INFORMATION:
4123 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4124 SIVAL(pdata,0,0); /* No alignment needed. */
4130 * NT4 server just returns "invalid query" to this - if we try to answer
4131 * it then NTws gets a BSOD! (tridge).
4132 * W2K seems to want this. JRA.
4134 case SMB_QUERY_FILE_STREAM_INFO:
4136 case SMB_FILE_STREAM_INFORMATION:
4137 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4141 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4142 SIVAL(pdata,0,0); /* ??? */
4143 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4144 SOFF_T(pdata,8,file_size);
4145 SOFF_T(pdata,16,allocation_size);
4146 data_size = 24 + byte_len;
4150 case SMB_QUERY_COMPRESSION_INFO:
4151 case SMB_FILE_COMPRESSION_INFORMATION:
4152 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4153 SOFF_T(pdata,0,file_size);
4154 SIVAL(pdata,8,0); /* ??? */
4155 SIVAL(pdata,12,0); /* ??? */
4159 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4160 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4161 put_long_date_timespec(pdata,create_time_ts);
4162 put_long_date_timespec(pdata+8,atime_ts);
4163 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4164 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4165 SOFF_T(pdata,32,allocation_size);
4166 SOFF_T(pdata,40,file_size);
4167 SIVAL(pdata,48,mode);
4168 SIVAL(pdata,52,0); /* ??? */
4172 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4173 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4174 SIVAL(pdata,0,mode);
4180 * CIFS UNIX Extensions.
4183 case SMB_QUERY_FILE_UNIX_BASIC:
4185 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4186 data_size = PTR_DIFF(pdata,(*ppdata));
4190 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4192 for (i=0; i<100; i++)
4193 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4199 case SMB_QUERY_FILE_UNIX_INFO2:
4201 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4202 data_size = PTR_DIFF(pdata,(*ppdata));
4206 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4208 for (i=0; i<100; i++)
4209 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4215 case SMB_QUERY_FILE_UNIX_LINK:
4219 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4221 if(!S_ISLNK(sbuf.st_mode)) {
4222 reply_unixerror(req, ERRSRV,
4227 reply_unixerror(req, ERRDOS, ERRbadlink);
4230 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
4232 reply_unixerror(req, ERRDOS,
4237 len = srvstr_push(dstart, req->flags2,
4239 PTR_DIFF(dend, pdata),
4242 data_size = PTR_DIFF(pdata,(*ppdata));
4247 #if defined(HAVE_POSIX_ACLS)
4248 case SMB_QUERY_POSIX_ACL:
4250 SMB_ACL_T file_acl = NULL;
4251 SMB_ACL_T def_acl = NULL;
4252 uint16 num_file_acls = 0;
4253 uint16 num_def_acls = 0;
4255 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4256 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4258 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4261 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4262 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4266 NT_STATUS_NOT_IMPLEMENTED);
4270 if (S_ISDIR(sbuf.st_mode)) {
4271 if (fsp && fsp->is_directory) {
4272 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4274 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4276 def_acl = free_empty_sys_acl(conn, def_acl);
4279 num_file_acls = count_acl_entries(conn, file_acl);
4280 num_def_acls = count_acl_entries(conn, def_acl);
4282 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4283 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4285 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4286 SMB_POSIX_ACL_HEADER_SIZE) ));
4288 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4291 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4295 NT_STATUS_BUFFER_TOO_SMALL);
4299 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4300 SSVAL(pdata,2,num_file_acls);
4301 SSVAL(pdata,4,num_def_acls);
4302 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4304 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4307 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4310 req, NT_STATUS_INTERNAL_ERROR);
4313 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4315 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4318 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4322 NT_STATUS_INTERNAL_ERROR);
4327 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4330 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4332 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4338 case SMB_QUERY_POSIX_LOCK:
4340 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4342 SMB_BIG_UINT offset;
4344 enum brl_type lock_type;
4346 if (total_data != POSIX_LOCK_DATA_SIZE) {
4348 req, NT_STATUS_INVALID_PARAMETER);
4352 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4353 case POSIX_LOCK_TYPE_READ:
4354 lock_type = READ_LOCK;
4356 case POSIX_LOCK_TYPE_WRITE:
4357 lock_type = WRITE_LOCK;
4359 case POSIX_LOCK_TYPE_UNLOCK:
4361 /* There's no point in asking for an unlock... */
4362 talloc_destroy(data_ctx);
4365 NT_STATUS_INVALID_PARAMETER);
4369 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4370 #if defined(HAVE_LONGLONG)
4371 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4372 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4373 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4374 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4375 #else /* HAVE_LONGLONG */
4376 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4377 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4378 #endif /* HAVE_LONGLONG */
4380 status = query_lock(fsp,
4387 if (ERROR_WAS_LOCK_DENIED(status)) {
4388 /* Here we need to report who has it locked... */
4389 data_size = POSIX_LOCK_DATA_SIZE;
4391 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4392 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4393 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4394 #if defined(HAVE_LONGLONG)
4395 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4396 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4397 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4398 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4399 #else /* HAVE_LONGLONG */
4400 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4401 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4402 #endif /* HAVE_LONGLONG */
4404 } else if (NT_STATUS_IS_OK(status)) {
4405 /* For success we just return a copy of what we sent
4406 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4407 data_size = POSIX_LOCK_DATA_SIZE;
4408 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4409 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4411 reply_nterror(req, status);
4418 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4422 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4428 /****************************************************************************
4429 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4431 ****************************************************************************/
4433 NTSTATUS hardlink_internals(connection_struct *conn,
4437 SMB_STRUCT_STAT sbuf1, sbuf2;
4438 char *last_component_oldname = NULL;
4439 char *last_component_newname = NULL;
4440 char *oldname = NULL;
4441 char *newname = NULL;
4442 NTSTATUS status = NT_STATUS_OK;
4447 status = unix_convert(conn, oldname_in, False, &oldname,
4448 &last_component_oldname, &sbuf1);
4449 if (!NT_STATUS_IS_OK(status)) {
4453 status = check_name(conn, oldname);
4454 if (!NT_STATUS_IS_OK(status)) {
4458 /* source must already exist. */
4459 if (!VALID_STAT(sbuf1)) {
4460 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4463 status = unix_convert(conn, newname_in, False, &newname,
4464 &last_component_newname, &sbuf2);
4465 if (!NT_STATUS_IS_OK(status)) {
4469 status = check_name(conn, newname);
4470 if (!NT_STATUS_IS_OK(status)) {
4474 /* Disallow if newname already exists. */
4475 if (VALID_STAT(sbuf2)) {
4476 return NT_STATUS_OBJECT_NAME_COLLISION;
4479 /* No links from a directory. */
4480 if (S_ISDIR(sbuf1.st_mode)) {
4481 return NT_STATUS_FILE_IS_A_DIRECTORY;
4484 /* Ensure this is within the share. */
4485 status = check_reduced_name(conn, oldname);
4486 if (!NT_STATUS_IS_OK(status)) {
4490 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4492 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4493 status = map_nt_error_from_unix(errno);
4494 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4495 nt_errstr(status), newname, oldname));
4501 /****************************************************************************
4502 Deal with setting the time from any of the setfilepathinfo functions.
4503 ****************************************************************************/
4505 static NTSTATUS smb_set_file_time(connection_struct *conn,
4508 const SMB_STRUCT_STAT *psbuf,
4509 struct timespec ts[2])
4512 FILE_NOTIFY_CHANGE_LAST_ACCESS
4513 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4516 if (!VALID_STAT(*psbuf)) {
4517 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4520 /* get some defaults (no modifications) if any info is zero or -1. */
4521 if (null_timespec(ts[0])) {
4522 ts[0] = get_atimespec(psbuf);
4523 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4526 if (null_timespec(ts[1])) {
4527 ts[1] = get_mtimespec(psbuf);
4528 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4531 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4532 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4535 * Try and set the times of this file if
4536 * they are different from the current values.
4540 struct timespec mts = get_mtimespec(psbuf);
4541 struct timespec ats = get_atimespec(psbuf);
4542 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4543 return NT_STATUS_OK;
4549 * This was a setfileinfo on an open file.
4550 * NT does this a lot. We also need to
4551 * set the time here, as it can be read by
4552 * FindFirst/FindNext and with the patch for bug #2045
4553 * in smbd/fileio.c it ensures that this timestamp is
4554 * kept sticky even after a write. We save the request
4555 * away and will set it on file close and after a write. JRA.
4558 if (!null_timespec(ts[1])) {
4559 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4560 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4561 fsp_set_pending_modtime(fsp, ts[1]);
4565 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4567 if(file_ntimes(conn, fname, ts)!=0) {
4568 return map_nt_error_from_unix(errno);
4571 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4573 return NT_STATUS_OK;
4576 /****************************************************************************
4577 Deal with setting the dosmode from any of the setfilepathinfo functions.
4578 ****************************************************************************/
4580 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4582 SMB_STRUCT_STAT *psbuf,
4585 if (!VALID_STAT(*psbuf)) {
4586 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4590 if (S_ISDIR(psbuf->st_mode)) {
4597 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4599 /* check the mode isn't different, before changing it */
4600 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4602 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4603 fname, (unsigned int)dosmode ));
4605 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4606 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4607 fname, strerror(errno)));
4608 return map_nt_error_from_unix(errno);
4611 return NT_STATUS_OK;
4614 /****************************************************************************
4615 Deal with setting the size from any of the setfilepathinfo functions.
4616 ****************************************************************************/
4618 static NTSTATUS smb_set_file_size(connection_struct *conn,
4619 struct smb_request *req,
4622 SMB_STRUCT_STAT *psbuf,
4625 NTSTATUS status = NT_STATUS_OK;
4626 files_struct *new_fsp = NULL;
4628 if (!VALID_STAT(*psbuf)) {
4629 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4632 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4634 if (size == get_file_size(*psbuf)) {
4635 return NT_STATUS_OK;
4638 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4639 fname, (double)size ));
4641 if (fsp && fsp->fh->fd != -1) {
4642 /* Handle based call. */
4643 if (vfs_set_filelen(fsp, size) == -1) {
4644 return map_nt_error_from_unix(errno);
4646 return NT_STATUS_OK;
4649 status = open_file_ntcreate(conn, req, fname, psbuf,
4651 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4654 FILE_ATTRIBUTE_NORMAL,
4655 FORCE_OPLOCK_BREAK_TO_NONE,
4658 if (!NT_STATUS_IS_OK(status)) {
4659 /* NB. We check for open_was_deferred in the caller. */
4663 if (vfs_set_filelen(new_fsp, size) == -1) {
4664 status = map_nt_error_from_unix(errno);
4665 close_file(new_fsp,NORMAL_CLOSE);
4669 close_file(new_fsp,NORMAL_CLOSE);
4670 return NT_STATUS_OK;
4673 /****************************************************************************
4674 Deal with SMB_INFO_SET_EA.
4675 ****************************************************************************/
4677 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4683 struct ea_list *ea_list = NULL;
4684 TALLOC_CTX *ctx = NULL;
4685 NTSTATUS status = NT_STATUS_OK;
4687 if (total_data < 10) {
4689 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4690 length. They seem to have no effect. Bug #3212. JRA */
4692 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4693 /* We're done. We only get EA info in this call. */
4694 return NT_STATUS_OK;
4697 return NT_STATUS_INVALID_PARAMETER;
4700 if (IVAL(pdata,0) > total_data) {
4701 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4702 IVAL(pdata,0), (unsigned int)total_data));
4703 return NT_STATUS_INVALID_PARAMETER;
4706 ctx = talloc_init("SMB_INFO_SET_EA");
4708 return NT_STATUS_NO_MEMORY;
4710 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4712 talloc_destroy(ctx);
4713 return NT_STATUS_INVALID_PARAMETER;
4715 status = set_ea(conn, fsp, fname, ea_list);
4716 talloc_destroy(ctx);
4721 /****************************************************************************
4722 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4723 ****************************************************************************/
4725 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4730 SMB_STRUCT_STAT *psbuf)
4732 NTSTATUS status = NT_STATUS_OK;
4733 BOOL delete_on_close;
4736 if (total_data < 1) {
4737 return NT_STATUS_INVALID_PARAMETER;
4741 return NT_STATUS_INVALID_HANDLE;
4744 delete_on_close = (CVAL(pdata,0) ? True : False);
4745 dosmode = dos_mode(conn, fname, psbuf);
4747 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4748 "delete_on_close = %u\n",
4750 (unsigned int)dosmode,
4751 (unsigned int)delete_on_close ));
4753 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4755 if (!NT_STATUS_IS_OK(status)) {
4759 /* The set is across all open files on this dev/inode pair. */
4760 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4761 return NT_STATUS_ACCESS_DENIED;
4763 return NT_STATUS_OK;
4766 /****************************************************************************
4767 Deal with SMB_FILE_POSITION_INFORMATION.
4768 ****************************************************************************/
4770 static NTSTATUS smb_file_position_information(connection_struct *conn,
4775 SMB_BIG_UINT position_information;
4777 if (total_data < 8) {
4778 return NT_STATUS_INVALID_PARAMETER;
4782 /* Ignore on pathname based set. */
4783 return NT_STATUS_OK;
4786 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4787 #ifdef LARGE_SMB_OFF_T
4788 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4789 #else /* LARGE_SMB_OFF_T */
4790 if (IVAL(pdata,4) != 0) {
4791 /* more than 32 bits? */
4792 return NT_STATUS_INVALID_PARAMETER;
4794 #endif /* LARGE_SMB_OFF_T */
4796 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4797 fsp->fsp_name, (double)position_information ));
4798 fsp->fh->position_information = position_information;
4799 return NT_STATUS_OK;
4802 /****************************************************************************
4803 Deal with SMB_FILE_MODE_INFORMATION.
4804 ****************************************************************************/
4806 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4812 if (total_data < 4) {
4813 return NT_STATUS_INVALID_PARAMETER;
4815 mode = IVAL(pdata,0);
4816 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4817 return NT_STATUS_INVALID_PARAMETER;
4819 return NT_STATUS_OK;
4822 /****************************************************************************
4823 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4824 ****************************************************************************/
4826 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4827 struct smb_request *req,
4832 pstring link_target;
4833 const char *newname = fname;
4834 NTSTATUS status = NT_STATUS_OK;
4836 /* Set a symbolic link. */
4837 /* Don't allow this if follow links is false. */
4839 if (total_data == 0) {
4840 return NT_STATUS_INVALID_PARAMETER;
4843 if (!lp_symlinks(SNUM(conn))) {
4844 return NT_STATUS_ACCESS_DENIED;
4847 srvstr_pull(pdata, req->flags2, link_target, pdata,
4848 sizeof(link_target), total_data, STR_TERMINATE);
4850 /* !widelinks forces the target path to be within the share. */
4851 /* This means we can interpret the target as a pathname. */
4852 if (!lp_widelinks(SNUM(conn))) {
4854 char *last_dirp = NULL;
4856 if (*link_target == '/') {
4857 /* No absolute paths allowed. */
4858 return NT_STATUS_ACCESS_DENIED;
4860 pstrcpy(rel_name, newname);
4861 last_dirp = strrchr_m(rel_name, '/');
4863 last_dirp[1] = '\0';
4865 pstrcpy(rel_name, "./");
4867 pstrcat(rel_name, link_target);
4869 status = check_name(conn, rel_name);
4870 if (!NT_STATUS_IS_OK(status)) {
4875 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4876 newname, link_target ));
4878 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4879 return map_nt_error_from_unix(errno);
4882 return NT_STATUS_OK;
4885 /****************************************************************************
4886 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4887 ****************************************************************************/
4889 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4890 struct smb_request *req,
4891 const char *pdata, int total_data,
4895 NTSTATUS status = NT_STATUS_OK;
4897 /* Set a hard link. */
4898 if (total_data == 0) {
4899 return NT_STATUS_INVALID_PARAMETER;
4902 srvstr_get_path(pdata, req->flags2, oldname, pdata,
4903 sizeof(oldname), total_data, STR_TERMINATE, &status);
4904 if (!NT_STATUS_IS_OK(status)) {
4908 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
4910 if (!NT_STATUS_IS_OK(status)) {
4914 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4917 return hardlink_internals(conn, oldname, fname);
4920 /****************************************************************************
4921 Deal with SMB_FILE_RENAME_INFORMATION.
4922 ****************************************************************************/
4924 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4925 struct smb_request *req,
4936 BOOL dest_has_wcard = False;
4937 NTSTATUS status = NT_STATUS_OK;
4940 if (total_data < 13) {
4941 return NT_STATUS_INVALID_PARAMETER;
4944 overwrite = (CVAL(pdata,0) ? True : False);
4945 root_fid = IVAL(pdata,4);
4946 len = IVAL(pdata,8);
4948 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4949 return NT_STATUS_INVALID_PARAMETER;
4952 srvstr_get_path_wcard(pdata, req->flags2, newname_in, &pdata[12],
4953 sizeof(newname_in), len, 0, &status,
4955 if (!NT_STATUS_IS_OK(status)) {
4959 status = resolve_dfspath_wcard(conn,
4960 req->flags2 & FLAGS2_DFS_PATHNAMES,
4961 newname_in, &dest_has_wcard);
4962 if (!NT_STATUS_IS_OK(status)) {
4966 /* Check the new name has no '/' characters. */
4967 if (strchr_m(newname_in, '/')) {
4968 return NT_STATUS_NOT_SUPPORTED;
4971 /* Create the base directory. */
4972 pstrcpy(base_name, fname);
4973 p = strrchr_m(base_name, '/');
4977 pstrcpy(base_name, "./");
4979 /* Append the new name. */
4980 pstrcat(base_name, newname_in);
4983 SMB_STRUCT_STAT sbuf;
4984 char *newname = NULL;
4985 char *newname_last_component = NULL;
4989 status = unix_convert(conn, newname_in, False,
4991 &newname_last_component,
4994 /* If an error we expect this to be
4995 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
4997 if (!NT_STATUS_IS_OK(status)
4998 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5003 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5004 fsp->fnum, fsp->fsp_name, base_name ));
5005 status = rename_internals_fsp(conn, fsp, base_name,
5006 newname_last_component, 0,
5009 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5010 fname, base_name ));
5011 status = rename_internals(conn, req, fname, base_name, 0,
5012 overwrite, False, dest_has_wcard);
5018 /****************************************************************************
5019 Deal with SMB_SET_POSIX_ACL.
5020 ****************************************************************************/
5022 #if defined(HAVE_POSIX_ACLS)
5023 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5028 SMB_STRUCT_STAT *psbuf)
5030 uint16 posix_acl_version;
5031 uint16 num_file_acls;
5032 uint16 num_def_acls;
5033 BOOL valid_file_acls = True;
5034 BOOL valid_def_acls = True;
5036 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5037 return NT_STATUS_INVALID_PARAMETER;
5039 posix_acl_version = SVAL(pdata,0);
5040 num_file_acls = SVAL(pdata,2);
5041 num_def_acls = SVAL(pdata,4);
5043 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5044 valid_file_acls = False;
5048 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5049 valid_def_acls = False;
5053 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5054 return NT_STATUS_INVALID_PARAMETER;
5057 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5058 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5059 return NT_STATUS_INVALID_PARAMETER;
5062 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5063 fname ? fname : fsp->fsp_name,
5064 (unsigned int)num_file_acls,
5065 (unsigned int)num_def_acls));
5067 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5068 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5069 return map_nt_error_from_unix(errno);
5072 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5073 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5074 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5075 return map_nt_error_from_unix(errno);
5077 return NT_STATUS_OK;
5081 /****************************************************************************
5082 Deal with SMB_SET_POSIX_LOCK.
5083 ****************************************************************************/
5085 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5093 SMB_BIG_UINT offset;
5095 BOOL blocking_lock = False;
5096 enum brl_type lock_type;
5097 NTSTATUS status = NT_STATUS_OK;
5099 if (fsp == NULL || fsp->fh->fd == -1) {
5100 return NT_STATUS_INVALID_HANDLE;
5103 if (total_data != POSIX_LOCK_DATA_SIZE) {
5104 return NT_STATUS_INVALID_PARAMETER;
5107 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5108 case POSIX_LOCK_TYPE_READ:
5109 lock_type = READ_LOCK;
5111 case POSIX_LOCK_TYPE_WRITE:
5112 /* Return the right POSIX-mappable error code for files opened read-only. */
5113 if (!fsp->can_write) {
5114 return NT_STATUS_INVALID_HANDLE;
5116 lock_type = WRITE_LOCK;
5118 case POSIX_LOCK_TYPE_UNLOCK:
5119 lock_type = UNLOCK_LOCK;
5122 return NT_STATUS_INVALID_PARAMETER;
5125 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5126 blocking_lock = False;
5127 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5128 blocking_lock = True;
5130 return NT_STATUS_INVALID_PARAMETER;
5133 if (!lp_blocking_locks(SNUM(conn))) {
5134 blocking_lock = False;
5137 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5138 #if defined(HAVE_LONGLONG)
5139 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5140 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5141 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5142 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5143 #else /* HAVE_LONGLONG */
5144 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5145 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5146 #endif /* HAVE_LONGLONG */
5148 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5149 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5151 (unsigned int)lock_type,
5152 (unsigned int)lock_pid,
5156 if (lock_type == UNLOCK_LOCK) {
5157 status = do_unlock(smbd_messaging_context(),
5164 uint32 block_smbpid;
5166 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5177 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5179 * A blocking lock was requested. Package up
5180 * this smb into a queued request and push it
5181 * onto the blocking lock queue.
5183 if(push_blocking_lock_request(br_lck,
5184 (char *)inbuf, length,
5186 -1, /* infinite timeout. */
5194 TALLOC_FREE(br_lck);
5198 TALLOC_FREE(br_lck);
5204 /****************************************************************************
5205 Deal with SMB_INFO_STANDARD.
5206 ****************************************************************************/
5208 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5213 const SMB_STRUCT_STAT *psbuf)
5215 struct timespec ts[2];
5217 if (total_data < 12) {
5218 return NT_STATUS_INVALID_PARAMETER;
5222 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5224 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5226 DEBUG(10,("smb_set_info_standard: file %s\n",
5227 fname ? fname : fsp->fsp_name ));
5229 return smb_set_file_time(conn,
5236 /****************************************************************************
5237 Deal with SMB_SET_FILE_BASIC_INFO.
5238 ****************************************************************************/
5240 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5245 SMB_STRUCT_STAT *psbuf)
5247 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5248 struct timespec write_time;
5249 struct timespec changed_time;
5251 struct timespec ts[2];
5252 NTSTATUS status = NT_STATUS_OK;
5254 if (total_data < 36) {
5255 return NT_STATUS_INVALID_PARAMETER;
5258 /* Set the attributes */
5259 dosmode = IVAL(pdata,32);
5260 status = smb_set_file_dosmode(conn,
5264 if (!NT_STATUS_IS_OK(status)) {
5268 /* Ignore create time at offset pdata. */
5271 ts[0] = interpret_long_date(pdata+8);
5273 write_time = interpret_long_date(pdata+16);
5274 changed_time = interpret_long_date(pdata+24);
5277 ts[1] = timespec_min(&write_time, &changed_time);
5279 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5283 /* Prefer a defined time to an undefined one. */
5284 if (null_timespec(ts[1])) {
5285 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5288 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5289 fname ? fname : fsp->fsp_name ));
5291 return smb_set_file_time(conn,
5298 /****************************************************************************
5299 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5300 ****************************************************************************/
5302 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5303 struct smb_request *req,
5308 SMB_STRUCT_STAT *psbuf)
5310 SMB_BIG_UINT allocation_size = 0;
5311 NTSTATUS status = NT_STATUS_OK;
5312 files_struct *new_fsp = NULL;
5314 if (!VALID_STAT(*psbuf)) {
5315 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5318 if (total_data < 8) {
5319 return NT_STATUS_INVALID_PARAMETER;
5322 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5323 #ifdef LARGE_SMB_OFF_T
5324 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5325 #else /* LARGE_SMB_OFF_T */
5326 if (IVAL(pdata,4) != 0) {
5327 /* more than 32 bits? */
5328 return NT_STATUS_INVALID_PARAMETER;
5330 #endif /* LARGE_SMB_OFF_T */
5332 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5333 fname, (double)allocation_size ));
5335 if (allocation_size) {
5336 allocation_size = smb_roundup(conn, allocation_size);
5339 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5340 fname, (double)allocation_size ));
5342 if (fsp && fsp->fh->fd != -1) {
5343 /* Open file handle. */
5344 /* Only change if needed. */
5345 if (allocation_size != get_file_size(*psbuf)) {
5346 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5347 return map_nt_error_from_unix(errno);
5350 /* But always update the time. */
5351 if (null_timespec(fsp->pending_modtime)) {
5353 * This is equivalent to a write. Ensure it's seen immediately
5354 * if there are no pending writes.
5356 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5358 return NT_STATUS_OK;
5361 /* Pathname or stat or directory file. */
5363 status = open_file_ntcreate(conn, req, fname, psbuf,
5365 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5368 FILE_ATTRIBUTE_NORMAL,
5369 FORCE_OPLOCK_BREAK_TO_NONE,
5372 if (!NT_STATUS_IS_OK(status)) {
5373 /* NB. We check for open_was_deferred in the caller. */
5377 /* Only change if needed. */
5378 if (allocation_size != get_file_size(*psbuf)) {
5379 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5380 status = map_nt_error_from_unix(errno);
5381 close_file(new_fsp,NORMAL_CLOSE);
5386 /* Changing the allocation size should set the last mod time. */
5387 /* Don't need to call set_filetime as this will be flushed on
5390 fsp_set_pending_modtime(new_fsp, timespec_current());
5392 close_file(new_fsp,NORMAL_CLOSE);
5393 return NT_STATUS_OK;
5396 /****************************************************************************
5397 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5398 ****************************************************************************/
5400 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5401 struct smb_request *req,
5406 SMB_STRUCT_STAT *psbuf)
5410 if (total_data < 8) {
5411 return NT_STATUS_INVALID_PARAMETER;
5414 size = IVAL(pdata,0);
5415 #ifdef LARGE_SMB_OFF_T
5416 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5417 #else /* LARGE_SMB_OFF_T */
5418 if (IVAL(pdata,4) != 0) {
5419 /* more than 32 bits? */
5420 return NT_STATUS_INVALID_PARAMETER;
5422 #endif /* LARGE_SMB_OFF_T */
5423 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5424 "file %s to %.0f\n", fname, (double)size ));
5426 return smb_set_file_size(conn, req,
5433 /****************************************************************************
5434 Allow a UNIX info mknod.
5435 ****************************************************************************/
5437 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5441 SMB_STRUCT_STAT *psbuf)
5443 uint32 file_type = IVAL(pdata,56);
5444 #if defined(HAVE_MAKEDEV)
5445 uint32 dev_major = IVAL(pdata,60);
5446 uint32 dev_minor = IVAL(pdata,68);
5448 SMB_DEV_T dev = (SMB_DEV_T)0;
5449 uint32 raw_unixmode = IVAL(pdata,84);
5453 if (total_data < 100) {
5454 return NT_STATUS_INVALID_PARAMETER;
5457 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5458 if (!NT_STATUS_IS_OK(status)) {
5462 #if defined(HAVE_MAKEDEV)
5463 dev = makedev(dev_major, dev_minor);
5466 switch (file_type) {
5467 #if defined(S_IFIFO)
5468 case UNIX_TYPE_FIFO:
5469 unixmode |= S_IFIFO;
5472 #if defined(S_IFSOCK)
5473 case UNIX_TYPE_SOCKET:
5474 unixmode |= S_IFSOCK;
5477 #if defined(S_IFCHR)
5478 case UNIX_TYPE_CHARDEV:
5479 unixmode |= S_IFCHR;
5482 #if defined(S_IFBLK)
5483 case UNIX_TYPE_BLKDEV:
5484 unixmode |= S_IFBLK;
5488 return NT_STATUS_INVALID_PARAMETER;
5491 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5492 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5494 /* Ok - do the mknod. */
5495 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5496 return map_nt_error_from_unix(errno);
5499 /* If any of the other "set" calls fail we
5500 * don't want to end up with a half-constructed mknod.
5503 if (lp_inherit_perms(SNUM(conn))) {
5505 conn, parent_dirname(fname),
5509 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5510 status = map_nt_error_from_unix(errno);
5511 SMB_VFS_UNLINK(conn,fname);
5514 return NT_STATUS_OK;
5517 /****************************************************************************
5518 Deal with SMB_SET_FILE_UNIX_BASIC.
5519 ****************************************************************************/
5521 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5522 struct smb_request *req,
5527 SMB_STRUCT_STAT *psbuf)
5529 struct timespec ts[2];
5530 uint32 raw_unixmode;
5533 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5534 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5535 NTSTATUS status = NT_STATUS_OK;
5536 BOOL delete_on_fail = False;
5537 enum perm_type ptype;
5539 if (total_data < 100) {
5540 return NT_STATUS_INVALID_PARAMETER;
5543 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5544 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5545 size=IVAL(pdata,0); /* first 8 Bytes are size */
5546 #ifdef LARGE_SMB_OFF_T
5547 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5548 #else /* LARGE_SMB_OFF_T */
5549 if (IVAL(pdata,4) != 0) {
5550 /* more than 32 bits? */
5551 return NT_STATUS_INVALID_PARAMETER;
5553 #endif /* LARGE_SMB_OFF_T */
5556 ts[0] = interpret_long_date(pdata+24); /* access_time */
5557 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5558 set_owner = (uid_t)IVAL(pdata,40);
5559 set_grp = (gid_t)IVAL(pdata,48);
5560 raw_unixmode = IVAL(pdata,84);
5562 if (VALID_STAT(*psbuf)) {
5563 if (S_ISDIR(psbuf->st_mode)) {
5564 ptype = PERM_EXISTING_DIR;
5566 ptype = PERM_EXISTING_FILE;
5569 ptype = PERM_NEW_FILE;
5572 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5573 if (!NT_STATUS_IS_OK(status)) {
5577 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5578 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5579 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5581 if (!VALID_STAT(*psbuf)) {
5583 * The only valid use of this is to create character and block
5584 * devices, and named pipes. This is deprecated (IMHO) and
5585 * a new info level should be used for mknod. JRA.
5588 status = smb_unix_mknod(conn,
5593 if (!NT_STATUS_IS_OK(status)) {
5597 /* Ensure we don't try and change anything else. */
5598 raw_unixmode = SMB_MODE_NO_CHANGE;
5599 size = get_file_size(*psbuf);
5600 ts[0] = get_atimespec(psbuf);
5601 ts[1] = get_mtimespec(psbuf);
5603 * We continue here as we might want to change the
5606 delete_on_fail = True;
5610 /* Horrible backwards compatibility hack as an old server bug
5611 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5615 size = get_file_size(*psbuf);
5620 * Deal with the UNIX specific mode set.
5623 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5624 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5625 (unsigned int)unixmode, fname ));
5626 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5627 return map_nt_error_from_unix(errno);
5632 * Deal with the UNIX specific uid set.
5635 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5638 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5639 (unsigned int)set_owner, fname ));
5641 if (S_ISLNK(psbuf->st_mode)) {
5642 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5644 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5648 status = map_nt_error_from_unix(errno);
5649 if (delete_on_fail) {
5650 SMB_VFS_UNLINK(conn,fname);
5657 * Deal with the UNIX specific gid set.
5660 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5661 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5662 (unsigned int)set_owner, fname ));
5663 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5664 status = map_nt_error_from_unix(errno);
5665 if (delete_on_fail) {
5666 SMB_VFS_UNLINK(conn,fname);
5672 /* Deal with any size changes. */
5674 status = smb_set_file_size(conn, req,
5679 if (!NT_STATUS_IS_OK(status)) {
5683 /* Deal with any time changes. */
5685 return smb_set_file_time(conn,
5692 /****************************************************************************
5693 Deal with SMB_SET_FILE_UNIX_INFO2.
5694 ****************************************************************************/
5696 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5697 struct smb_request *req,
5702 SMB_STRUCT_STAT *psbuf)
5708 if (total_data < 116) {
5709 return NT_STATUS_INVALID_PARAMETER;
5712 /* Start by setting all the fields that are common between UNIX_BASIC
5715 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5717 if (!NT_STATUS_IS_OK(status)) {
5721 smb_fflags = IVAL(pdata, 108);
5722 smb_fmask = IVAL(pdata, 112);
5724 /* NB: We should only attempt to alter the file flags if the client
5725 * sends a non-zero mask.
5727 if (smb_fmask != 0) {
5728 int stat_fflags = 0;
5730 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5732 /* Client asked to alter a flag we don't understand. */
5733 return NT_STATUS_INVALID_PARAMETER;
5736 if (fsp && fsp->fh->fd != -1) {
5737 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5738 return NT_STATUS_NOT_SUPPORTED;
5740 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5741 return map_nt_error_from_unix(errno);
5746 /* XXX: need to add support for changing the create_time here. You
5747 * can do this for paths on Darwin with setattrlist(2). The right way
5748 * to hook this up is probably by extending the VFS utimes interface.
5751 return NT_STATUS_OK;
5754 /****************************************************************************
5755 Create a directory with POSIX semantics.
5756 ****************************************************************************/
5758 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5759 struct smb_request *req,
5763 SMB_STRUCT_STAT *psbuf,
5764 int *pdata_return_size)
5766 NTSTATUS status = NT_STATUS_OK;
5767 uint32 raw_unixmode = 0;
5768 uint32 mod_unixmode = 0;
5769 mode_t unixmode = (mode_t)0;
5770 files_struct *fsp = NULL;
5771 uint16 info_level_return = 0;
5773 char *pdata = *ppdata;
5775 if (total_data < 18) {
5776 return NT_STATUS_INVALID_PARAMETER;
5779 raw_unixmode = IVAL(pdata,8);
5780 /* Next 4 bytes are not yet defined. */
5782 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5783 if (!NT_STATUS_IS_OK(status)) {
5787 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5789 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5790 fname, (unsigned int)unixmode ));
5792 status = open_directory(conn, req,
5795 FILE_READ_ATTRIBUTES, /* Just a stat open */
5796 FILE_SHARE_NONE, /* Ignored for stat opens */
5803 if (NT_STATUS_IS_OK(status)) {
5804 close_file(fsp, NORMAL_CLOSE);
5807 info_level_return = SVAL(pdata,16);
5809 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5810 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5811 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5812 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5814 *pdata_return_size = 12;
5817 /* Realloc the data size */
5818 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5819 if (*ppdata == NULL) {
5820 *pdata_return_size = 0;
5821 return NT_STATUS_NO_MEMORY;
5825 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5826 SSVAL(pdata,2,0); /* No fnum. */
5827 SIVAL(pdata,4,info); /* Was directory created. */
5829 switch (info_level_return) {
5830 case SMB_QUERY_FILE_UNIX_BASIC:
5831 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5832 SSVAL(pdata,10,0); /* Padding. */
5833 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5835 case SMB_QUERY_FILE_UNIX_INFO2:
5836 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5837 SSVAL(pdata,10,0); /* Padding. */
5838 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5841 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5842 SSVAL(pdata,10,0); /* Padding. */
5849 /****************************************************************************
5850 Open/Create a file with POSIX semantics.
5851 ****************************************************************************/
5853 static NTSTATUS smb_posix_open(connection_struct *conn,
5854 struct smb_request *req,
5858 SMB_STRUCT_STAT *psbuf,
5859 int *pdata_return_size)
5861 BOOL extended_oplock_granted = False;
5862 char *pdata = *ppdata;
5864 uint32 wire_open_mode = 0;
5865 uint32 raw_unixmode = 0;
5866 uint32 mod_unixmode = 0;
5867 uint32 create_disp = 0;
5868 uint32 access_mask = 0;
5869 uint32 create_options = 0;
5870 NTSTATUS status = NT_STATUS_OK;
5871 mode_t unixmode = (mode_t)0;
5872 files_struct *fsp = NULL;
5873 int oplock_request = 0;
5875 uint16 info_level_return = 0;
5877 if (total_data < 18) {
5878 return NT_STATUS_INVALID_PARAMETER;
5881 flags = IVAL(pdata,0);
5882 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5883 if (oplock_request) {
5884 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5887 wire_open_mode = IVAL(pdata,4);
5889 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5890 return smb_posix_mkdir(conn, req,
5898 switch (wire_open_mode & SMB_ACCMODE) {
5900 access_mask = FILE_READ_DATA;
5903 access_mask = FILE_WRITE_DATA;
5906 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5909 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5910 (unsigned int)wire_open_mode ));
5911 return NT_STATUS_INVALID_PARAMETER;
5914 wire_open_mode &= ~SMB_ACCMODE;
5916 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5917 create_disp = FILE_CREATE;
5918 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5919 create_disp = FILE_OVERWRITE_IF;
5920 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5921 create_disp = FILE_OPEN_IF;
5923 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5924 (unsigned int)wire_open_mode ));
5925 return NT_STATUS_INVALID_PARAMETER;
5928 raw_unixmode = IVAL(pdata,8);
5929 /* Next 4 bytes are not yet defined. */
5931 status = unix_perms_from_wire(conn,
5934 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5937 if (!NT_STATUS_IS_OK(status)) {
5941 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5943 if (wire_open_mode & SMB_O_SYNC) {
5944 create_options |= FILE_WRITE_THROUGH;
5946 if (wire_open_mode & SMB_O_APPEND) {
5947 access_mask |= FILE_APPEND_DATA;
5949 if (wire_open_mode & SMB_O_DIRECT) {
5950 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5953 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5955 (unsigned int)wire_open_mode,
5956 (unsigned int)unixmode ));
5958 status = open_file_ntcreate(conn, req,
5962 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5964 0, /* no create options yet. */
5970 if (!NT_STATUS_IS_OK(status)) {
5974 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5975 extended_oplock_granted = True;
5978 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5979 extended_oplock_granted = True;
5982 info_level_return = SVAL(pdata,16);
5984 /* Allocate the correct return size. */
5986 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5987 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5988 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5989 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5991 *pdata_return_size = 12;
5994 /* Realloc the data size */
5995 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5996 if (*ppdata == NULL) {
5997 close_file(fsp,ERROR_CLOSE);
5998 *pdata_return_size = 0;
5999 return NT_STATUS_NO_MEMORY;
6003 if (extended_oplock_granted) {
6004 if (flags & REQUEST_BATCH_OPLOCK) {
6005 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6007 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6009 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6010 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6012 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6015 SSVAL(pdata,2,fsp->fnum);
6016 SIVAL(pdata,4,info); /* Was file created etc. */
6018 switch (info_level_return) {
6019 case SMB_QUERY_FILE_UNIX_BASIC:
6020 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6021 SSVAL(pdata,10,0); /* padding. */
6022 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6024 case SMB_QUERY_FILE_UNIX_INFO2:
6025 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6026 SSVAL(pdata,10,0); /* padding. */
6027 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6030 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6031 SSVAL(pdata,10,0); /* padding. */
6034 return NT_STATUS_OK;
6037 /****************************************************************************
6038 Delete a file with POSIX semantics.
6039 ****************************************************************************/
6041 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6042 struct smb_request *req,
6046 SMB_STRUCT_STAT *psbuf)
6048 NTSTATUS status = NT_STATUS_OK;
6049 files_struct *fsp = NULL;
6054 struct share_mode_lock *lck = NULL;
6056 if (total_data < 2) {
6057 return NT_STATUS_INVALID_PARAMETER;
6060 flags = SVAL(pdata,0);
6062 if (!VALID_STAT(*psbuf)) {
6063 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6066 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6067 !VALID_STAT_OF_DIR(*psbuf)) {
6068 return NT_STATUS_NOT_A_DIRECTORY;
6071 DEBUG(10,("smb_posix_unlink: %s %s\n",
6072 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6075 if (VALID_STAT_OF_DIR(*psbuf)) {
6076 status = open_directory(conn, req,
6080 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6083 FILE_FLAG_POSIX_SEMANTICS|0777,
6088 status = open_file_ntcreate(conn, req,
6092 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6095 FILE_FLAG_POSIX_SEMANTICS|0777,
6096 0, /* No oplock, but break existing ones. */
6101 if (!NT_STATUS_IS_OK(status)) {
6106 * Don't lie to client. If we can't really delete due to
6107 * non-POSIX opens return SHARING_VIOLATION.
6110 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6112 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6113 "lock for file %s\n", fsp->fsp_name));
6114 close_file(fsp, NORMAL_CLOSE);
6115 return NT_STATUS_INVALID_PARAMETER;
6119 * See if others still have the file open. If this is the case, then
6120 * don't delete. If all opens are POSIX delete we can set the delete
6121 * on close disposition.
6123 for (i=0; i<lck->num_share_modes; i++) {
6124 struct share_mode_entry *e = &lck->share_modes[i];
6125 if (is_valid_share_mode_entry(e)) {
6126 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6129 /* Fail with sharing violation. */
6130 close_file(fsp, NORMAL_CLOSE);
6132 return NT_STATUS_SHARING_VIOLATION;
6137 * Set the delete on close.
6139 status = smb_set_file_disposition_info(conn,
6146 if (!NT_STATUS_IS_OK(status)) {
6147 close_file(fsp, NORMAL_CLOSE);
6152 return close_file(fsp, NORMAL_CLOSE);
6155 /****************************************************************************
6156 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6157 ****************************************************************************/
6159 static void call_trans2setfilepathinfo(connection_struct *conn,
6160 struct smb_request *req,
6161 unsigned int tran_call,
6162 char **pparams, int total_params,
6163 char **ppdata, int total_data,
6164 unsigned int max_data_bytes)
6166 char *params = *pparams;
6167 char *pdata = *ppdata;
6169 SMB_STRUCT_STAT sbuf;
6171 files_struct *fsp = NULL;
6172 NTSTATUS status = NT_STATUS_OK;
6173 int data_return_size = 0;
6176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6182 if (tran_call == TRANSACT2_SETFILEINFO) {
6183 if (total_params < 4) {
6184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6188 fsp = file_fsp(SVAL(params,0));
6189 /* Basic check for non-null fsp. */
6190 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6193 info_level = SVAL(params,2);
6195 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6197 reply_nterror(req, NT_STATUS_NO_MEMORY);
6201 if(fsp->is_directory || fsp->fh->fd == -1) {
6203 * This is actually a SETFILEINFO on a directory
6204 * handle (returned from an NT SMB). NT5.0 seems
6205 * to do this call. JRA.
6207 if (INFO_LEVEL_IS_UNIX(info_level)) {
6208 /* Always do lstat for UNIX calls. */
6209 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6210 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6211 reply_unixerror(req,ERRDOS,ERRbadpath);
6215 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6216 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6217 reply_unixerror(req,ERRDOS,ERRbadpath);
6221 } else if (fsp->print_file) {
6223 * Doing a DELETE_ON_CLOSE should cancel a print job.
6225 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6226 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6228 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6231 send_trans2_replies(req, params, 2,
6236 reply_unixerror(req, ERRDOS, ERRbadpath);
6241 * Original code - this is an open file.
6243 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6247 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6248 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6249 reply_unixerror(req, ERRDOS, ERRbadfid);
6257 if (total_params < 7) {
6258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6262 info_level = SVAL(params,0);
6263 srvstr_get_path(params, req->flags2, fname_in, ¶ms[6],
6264 sizeof(fname_in), total_params - 6, STR_TERMINATE,
6266 if (!NT_STATUS_IS_OK(status)) {
6267 reply_nterror(req, status);
6271 status = resolve_dfspath(conn,
6272 req->flags2 & FLAGS2_DFS_PATHNAMES,
6274 if (!NT_STATUS_IS_OK(status)) {
6275 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6276 reply_botherror(req,
6277 NT_STATUS_PATH_NOT_COVERED,
6278 ERRSRV, ERRbadpath);
6281 reply_nterror(req, status);
6285 status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
6286 if (!NT_STATUS_IS_OK(status)) {
6287 reply_nterror(req, status);
6291 status = check_name(conn, fname);
6292 if (!NT_STATUS_IS_OK(status)) {
6293 reply_nterror(req, status);
6297 if (INFO_LEVEL_IS_UNIX(info_level)) {
6299 * For CIFS UNIX extensions the target name may not exist.
6302 /* Always do lstat for UNIX calls. */
6303 SMB_VFS_LSTAT(conn,fname,&sbuf);
6305 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6306 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6307 reply_unixerror(req, ERRDOS, ERRbadpath);
6312 if (!CAN_WRITE(conn)) {
6313 reply_doserror(req, ERRSRV, ERRaccess);
6317 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6322 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6323 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6325 /* Realloc the parameter size */
6326 *pparams = (char *)SMB_REALLOC(*pparams,2);
6327 if (*pparams == NULL) {
6328 reply_nterror(req, NT_STATUS_NO_MEMORY);
6335 if (fsp && !null_timespec(fsp->pending_modtime)) {
6336 /* the pending modtime overrides the current modtime */
6337 set_mtimespec(&sbuf, fsp->pending_modtime);
6340 switch (info_level) {
6342 case SMB_INFO_STANDARD:
6344 status = smb_set_info_standard(conn,
6353 case SMB_INFO_SET_EA:
6355 status = smb_info_set_ea(conn,
6363 case SMB_SET_FILE_BASIC_INFO:
6364 case SMB_FILE_BASIC_INFORMATION:
6366 status = smb_set_file_basic_info(conn,
6375 case SMB_FILE_ALLOCATION_INFORMATION:
6376 case SMB_SET_FILE_ALLOCATION_INFO:
6378 status = smb_set_file_allocation_info(conn, req,
6387 case SMB_FILE_END_OF_FILE_INFORMATION:
6388 case SMB_SET_FILE_END_OF_FILE_INFO:
6390 status = smb_set_file_end_of_file_info(conn, req,
6399 case SMB_FILE_DISPOSITION_INFORMATION:
6400 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6403 /* JRA - We used to just ignore this on a path ?
6404 * Shouldn't this be invalid level on a pathname
6407 if (tran_call != TRANSACT2_SETFILEINFO) {
6408 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6411 status = smb_set_file_disposition_info(conn,
6420 case SMB_FILE_POSITION_INFORMATION:
6422 status = smb_file_position_information(conn,
6429 /* From tridge Samba4 :
6430 * MODE_INFORMATION in setfileinfo (I have no
6431 * idea what "mode information" on a file is - it takes a value of 0,
6432 * 2, 4 or 6. What could it be?).
6435 case SMB_FILE_MODE_INFORMATION:
6437 status = smb_file_mode_information(conn,
6444 * CIFS UNIX extensions.
6447 case SMB_SET_FILE_UNIX_BASIC:
6449 status = smb_set_file_unix_basic(conn, req,
6458 case SMB_SET_FILE_UNIX_INFO2:
6460 status = smb_set_file_unix_info2(conn, req,
6469 case SMB_SET_FILE_UNIX_LINK:
6471 if (tran_call != TRANSACT2_SETPATHINFO) {
6472 /* We must have a pathname for this. */
6473 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6476 status = smb_set_file_unix_link(conn, req, pdata,
6481 case SMB_SET_FILE_UNIX_HLINK:
6483 if (tran_call != TRANSACT2_SETPATHINFO) {
6484 /* We must have a pathname for this. */
6485 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6488 status = smb_set_file_unix_hlink(conn, req,
6494 case SMB_FILE_RENAME_INFORMATION:
6496 status = smb_file_rename_information(conn, req,
6502 #if defined(HAVE_POSIX_ACLS)
6503 case SMB_SET_POSIX_ACL:
6505 status = smb_set_posix_acl(conn,
6515 case SMB_SET_POSIX_LOCK:
6517 if (tran_call != TRANSACT2_SETFILEINFO) {
6518 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6521 status = smb_set_posix_lock(conn, req->inbuf,
6522 smb_len(req->inbuf) + 4,
6523 pdata, total_data, fsp);
6527 case SMB_POSIX_PATH_OPEN:
6529 if (tran_call != TRANSACT2_SETPATHINFO) {
6530 /* We must have a pathname for this. */
6531 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6535 status = smb_posix_open(conn, req,
6544 case SMB_POSIX_PATH_UNLINK:
6546 if (tran_call != TRANSACT2_SETPATHINFO) {
6547 /* We must have a pathname for this. */
6548 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6552 status = smb_posix_unlink(conn, req,
6561 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6566 if (!NT_STATUS_IS_OK(status)) {
6567 if (open_was_deferred(req->mid)) {
6568 /* We have re-scheduled this call. */
6571 if (blocking_lock_was_deferred(req->mid)) {
6572 /* We have re-scheduled this call. */
6575 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6576 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6577 ERRSRV, ERRbadpath);
6580 if (info_level == SMB_POSIX_PATH_OPEN) {
6581 reply_openerror(req, status);
6585 reply_nterror(req, status);
6590 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6596 /****************************************************************************
6597 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6598 ****************************************************************************/
6600 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6601 char **pparams, int total_params,
6602 char **ppdata, int total_data,
6603 unsigned int max_data_bytes)
6605 char *params = *pparams;
6606 char *pdata = *ppdata;
6607 pstring directory_in;
6608 char *directory = NULL;
6609 SMB_STRUCT_STAT sbuf;
6610 NTSTATUS status = NT_STATUS_OK;
6611 struct ea_list *ea_list = NULL;
6613 if (!CAN_WRITE(conn)) {
6614 reply_doserror(req, ERRSRV, ERRaccess);
6618 if (total_params < 5) {
6619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6623 srvstr_get_path(params, req->flags2, directory_in, ¶ms[4],
6624 sizeof(directory_in), total_params - 4, STR_TERMINATE,
6626 if (!NT_STATUS_IS_OK(status)) {
6627 reply_nterror(req, status);
6631 DEBUG(3,("call_trans2mkdir : name = %s\n", directory_in));
6633 status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf);
6634 if (!NT_STATUS_IS_OK(status)) {
6635 reply_nterror(req, status);
6639 status = check_name(conn, directory);
6640 if (!NT_STATUS_IS_OK(status)) {
6641 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6642 reply_nterror(req, status);
6646 /* Any data in this call is an EA list. */
6647 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6648 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6653 * OS/2 workplace shell seems to send SET_EA requests of "null"
6654 * length (4 bytes containing IVAL 4).
6655 * They seem to have no effect. Bug #3212. JRA.
6658 if (total_data != 4) {
6659 if (total_data < 10) {
6660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6664 if (IVAL(pdata,0) > total_data) {
6665 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6666 IVAL(pdata,0), (unsigned int)total_data));
6667 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6671 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6677 } else if (IVAL(pdata,0) != 4) {
6678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6682 status = create_directory(conn, directory);
6684 if (!NT_STATUS_IS_OK(status)) {
6685 reply_nterror(req, status);
6689 /* Try and set any given EA. */
6691 status = set_ea(conn, NULL, directory, ea_list);
6692 if (!NT_STATUS_IS_OK(status)) {
6693 reply_nterror(req, status);
6698 /* Realloc the parameter and data sizes */
6699 *pparams = (char *)SMB_REALLOC(*pparams,2);
6700 if(*pparams == NULL) {
6701 reply_nterror(req, NT_STATUS_NO_MEMORY);
6708 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6713 /****************************************************************************
6714 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6715 We don't actually do this - we just send a null response.
6716 ****************************************************************************/
6718 static void call_trans2findnotifyfirst(connection_struct *conn,
6719 struct smb_request *req,
6720 char **pparams, int total_params,
6721 char **ppdata, int total_data,
6722 unsigned int max_data_bytes)
6724 static uint16 fnf_handle = 257;
6725 char *params = *pparams;
6728 if (total_params < 6) {
6729 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6733 info_level = SVAL(params,4);
6734 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6736 switch (info_level) {
6741 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6745 /* Realloc the parameter and data sizes */
6746 *pparams = (char *)SMB_REALLOC(*pparams,6);
6747 if (*pparams == NULL) {
6748 reply_nterror(req, NT_STATUS_NO_MEMORY);
6753 SSVAL(params,0,fnf_handle);
6754 SSVAL(params,2,0); /* No changes */
6755 SSVAL(params,4,0); /* No EA errors */
6762 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6767 /****************************************************************************
6768 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6769 changes). Currently this does nothing.
6770 ****************************************************************************/
6772 static void call_trans2findnotifynext(connection_struct *conn,
6773 struct smb_request *req,
6774 char **pparams, int total_params,
6775 char **ppdata, int total_data,
6776 unsigned int max_data_bytes)
6778 char *params = *pparams;
6780 DEBUG(3,("call_trans2findnotifynext\n"));
6782 /* Realloc the parameter and data sizes */
6783 *pparams = (char *)SMB_REALLOC(*pparams,4);
6784 if (*pparams == NULL) {
6785 reply_nterror(req, NT_STATUS_NO_MEMORY);
6790 SSVAL(params,0,0); /* No changes */
6791 SSVAL(params,2,0); /* No EA errors */
6793 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6798 /****************************************************************************
6799 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6800 ****************************************************************************/
6802 static void call_trans2getdfsreferral(connection_struct *conn,
6803 struct smb_request *req,
6804 char **pparams, int total_params,
6805 char **ppdata, int total_data,
6806 unsigned int max_data_bytes)
6808 char *params = *pparams;
6811 int max_referral_level;
6812 NTSTATUS status = NT_STATUS_OK;
6814 DEBUG(10,("call_trans2getdfsreferral\n"));
6816 if (total_params < 3) {
6817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6821 max_referral_level = SVAL(params,0);
6823 if(!lp_host_msdfs()) {
6824 reply_doserror(req, ERRDOS, ERRbadfunc);
6828 srvstr_pull(params, req->flags2, pathname, ¶ms[2],
6829 sizeof(pathname), total_params - 2, STR_TERMINATE);
6830 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6831 ppdata,&status)) < 0) {
6832 reply_nterror(req, status);
6836 SSVAL(req->inbuf, smb_flg2,
6837 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6838 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6843 #define LMCAT_SPL 0x53
6844 #define LMFUNC_GETJOBID 0x60
6846 /****************************************************************************
6847 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6848 ****************************************************************************/
6850 static void call_trans2ioctl(connection_struct *conn,
6851 struct smb_request *req,
6852 char **pparams, int total_params,
6853 char **ppdata, int total_data,
6854 unsigned int max_data_bytes)
6856 char *pdata = *ppdata;
6857 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6859 /* check for an invalid fid before proceeding */
6862 reply_doserror(req, ERRDOS, ERRbadfid);
6866 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6867 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6868 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6869 if (*ppdata == NULL) {
6870 reply_nterror(req, NT_STATUS_NO_MEMORY);
6875 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6876 CAN ACCEPT THIS IN UNICODE. JRA. */
6878 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6879 srvstr_push(pdata, req->flags2, pdata + 2,
6880 global_myname(), 15,
6881 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6882 srvstr_push(pdata, req->flags2, pdata+18,
6883 lp_servicename(SNUM(conn)), 13,
6884 STR_ASCII|STR_TERMINATE); /* Service name */
6885 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6890 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6891 reply_doserror(req, ERRSRV, ERRerror);
6894 /****************************************************************************
6895 Reply to a SMBfindclose (stop trans2 directory search).
6896 ****************************************************************************/
6898 void reply_findclose(connection_struct *conn, struct smb_request *req)
6902 START_PROFILE(SMBfindclose);
6905 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6906 END_PROFILE(SMBfindclose);
6910 dptr_num = SVALS(req->inbuf,smb_vwv0);
6912 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6914 dptr_close(&dptr_num);
6916 reply_outbuf(req, 0, 0);
6918 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6920 END_PROFILE(SMBfindclose);
6924 /****************************************************************************
6925 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6926 ****************************************************************************/
6928 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6932 START_PROFILE(SMBfindnclose);
6935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6936 END_PROFILE(SMBfindnclose);
6940 dptr_num = SVAL(req->inbuf,smb_vwv0);
6942 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6944 /* We never give out valid handles for a
6945 findnotifyfirst - so any dptr_num is ok here.
6948 reply_outbuf(req, 0, 0);
6950 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6952 END_PROFILE(SMBfindnclose);
6956 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6957 struct trans_state *state)
6959 if (Protocol >= PROTOCOL_NT1) {
6960 req->flags2 |= 0x40; /* IS_LONG_NAME */
6961 SSVAL(req->inbuf,smb_flg2,req->flags2);
6964 /* Now we must call the relevant TRANS2 function */
6965 switch(state->call) {
6966 case TRANSACT2_OPEN:
6968 START_PROFILE(Trans2_open);
6969 call_trans2open(conn, req,
6970 &state->param, state->total_param,
6971 &state->data, state->total_data,
6972 state->max_data_return);
6973 END_PROFILE(Trans2_open);
6977 case TRANSACT2_FINDFIRST:
6979 START_PROFILE(Trans2_findfirst);
6980 call_trans2findfirst(conn, req,
6981 &state->param, state->total_param,
6982 &state->data, state->total_data,
6983 state->max_data_return);
6984 END_PROFILE(Trans2_findfirst);
6988 case TRANSACT2_FINDNEXT:
6990 START_PROFILE(Trans2_findnext);
6991 call_trans2findnext(conn, req,
6992 &state->param, state->total_param,
6993 &state->data, state->total_data,
6994 state->max_data_return);
6995 END_PROFILE(Trans2_findnext);
6999 case TRANSACT2_QFSINFO:
7001 START_PROFILE(Trans2_qfsinfo);
7002 call_trans2qfsinfo(conn, req,
7003 &state->param, state->total_param,
7004 &state->data, state->total_data,
7005 state->max_data_return);
7006 END_PROFILE(Trans2_qfsinfo);
7010 case TRANSACT2_SETFSINFO:
7012 START_PROFILE(Trans2_setfsinfo);
7013 call_trans2setfsinfo(conn, req,
7014 &state->param, state->total_param,
7015 &state->data, state->total_data,
7016 state->max_data_return);
7017 END_PROFILE(Trans2_setfsinfo);
7021 case TRANSACT2_QPATHINFO:
7022 case TRANSACT2_QFILEINFO:
7024 START_PROFILE(Trans2_qpathinfo);
7025 call_trans2qfilepathinfo(conn, req, state->call,
7026 &state->param, state->total_param,
7027 &state->data, state->total_data,
7028 state->max_data_return);
7029 END_PROFILE(Trans2_qpathinfo);
7033 case TRANSACT2_SETPATHINFO:
7034 case TRANSACT2_SETFILEINFO:
7036 START_PROFILE(Trans2_setpathinfo);
7037 call_trans2setfilepathinfo(conn, req, state->call,
7038 &state->param, state->total_param,
7039 &state->data, state->total_data,
7040 state->max_data_return);
7041 END_PROFILE(Trans2_setpathinfo);
7045 case TRANSACT2_FINDNOTIFYFIRST:
7047 START_PROFILE(Trans2_findnotifyfirst);
7048 call_trans2findnotifyfirst(conn, req,
7049 &state->param, state->total_param,
7050 &state->data, state->total_data,
7051 state->max_data_return);
7052 END_PROFILE(Trans2_findnotifyfirst);
7056 case TRANSACT2_FINDNOTIFYNEXT:
7058 START_PROFILE(Trans2_findnotifynext);
7059 call_trans2findnotifynext(conn, req,
7060 &state->param, state->total_param,
7061 &state->data, state->total_data,
7062 state->max_data_return);
7063 END_PROFILE(Trans2_findnotifynext);
7067 case TRANSACT2_MKDIR:
7069 START_PROFILE(Trans2_mkdir);
7070 call_trans2mkdir(conn, req,
7071 &state->param, state->total_param,
7072 &state->data, state->total_data,
7073 state->max_data_return);
7074 END_PROFILE(Trans2_mkdir);
7078 case TRANSACT2_GET_DFS_REFERRAL:
7080 START_PROFILE(Trans2_get_dfs_referral);
7081 call_trans2getdfsreferral(conn, req,
7082 &state->param, state->total_param,
7083 &state->data, state->total_data,
7084 state->max_data_return);
7085 END_PROFILE(Trans2_get_dfs_referral);
7089 case TRANSACT2_IOCTL:
7091 START_PROFILE(Trans2_ioctl);
7092 call_trans2ioctl(conn, req,
7093 &state->param, state->total_param,
7094 &state->data, state->total_data,
7095 state->max_data_return);
7096 END_PROFILE(Trans2_ioctl);
7101 /* Error in request */
7102 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7103 reply_doserror(req, ERRSRV,ERRerror);
7107 /****************************************************************************
7108 Reply to a SMBtrans2.
7109 ****************************************************************************/
7111 void reply_trans2(connection_struct *conn, struct smb_request *req)
7117 unsigned int tran_call;
7119 struct trans_state *state;
7122 START_PROFILE(SMBtrans2);
7124 if (req->wct < 14) {
7125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7126 END_PROFILE(SMBtrans2);
7130 dsoff = SVAL(req->inbuf, smb_dsoff);
7131 dscnt = SVAL(req->inbuf, smb_dscnt);
7132 psoff = SVAL(req->inbuf, smb_psoff);
7133 pscnt = SVAL(req->inbuf, smb_pscnt);
7134 tran_call = SVAL(req->inbuf, smb_setup0);
7135 size = smb_len(req->inbuf) + 4;
7137 result = allow_new_trans(conn->pending_trans, req->mid);
7138 if (!NT_STATUS_IS_OK(result)) {
7139 DEBUG(2, ("Got invalid trans2 request: %s\n",
7140 nt_errstr(result)));
7141 reply_nterror(req, result);
7142 END_PROFILE(SMBtrans2);
7146 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7147 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7148 && (tran_call != TRANSACT2_QFILEINFO)) {
7149 reply_doserror(req, ERRSRV, ERRaccess);
7150 END_PROFILE(SMBtrans2);
7154 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7155 DEBUG(0, ("talloc failed\n"));
7156 reply_nterror(req, NT_STATUS_NO_MEMORY);
7157 END_PROFILE(SMBtrans2);
7161 state->cmd = SMBtrans2;
7163 state->mid = req->mid;
7164 state->vuid = req->vuid;
7165 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7166 state->setup = NULL;
7167 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7168 state->param = NULL;
7169 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7171 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7172 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7173 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7174 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7175 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7177 state->call = tran_call;
7179 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7180 is so as a sanity check */
7181 if (state->setup_count != 1) {
7183 * Need to have rc=0 for ioctl to get job id for OS/2.
7184 * Network printing will fail if function is not successful.
7185 * Similar function in reply.c will be used if protocol
7186 * is LANMAN1.0 instead of LM1.2X002.
7187 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7188 * outbuf doesn't have to be set(only job id is used).
7190 if ( (state->setup_count == 4)
7191 && (tran_call == TRANSACT2_IOCTL)
7192 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7193 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7194 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7196 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7197 DEBUG(2,("Transaction is %d\n",tran_call));
7199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7200 END_PROFILE(SMBtrans2);
7205 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7208 if (state->total_data) {
7209 /* Can't use talloc here, the core routines do realloc on the
7210 * params and data. */
7211 state->data = (char *)SMB_MALLOC(state->total_data);
7212 if (state->data == NULL) {
7213 DEBUG(0,("reply_trans2: data malloc fail for %u "
7214 "bytes !\n", (unsigned int)state->total_data));
7216 reply_nterror(req, NT_STATUS_NO_MEMORY);
7217 END_PROFILE(SMBtrans2);
7220 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7222 if ((smb_base(req->inbuf)+dsoff+dscnt
7223 > (char *)req->inbuf + size) ||
7224 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7227 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7230 if (state->total_param) {
7231 /* Can't use talloc here, the core routines do realloc on the
7232 * params and data. */
7233 state->param = (char *)SMB_MALLOC(state->total_param);
7234 if (state->param == NULL) {
7235 DEBUG(0,("reply_trans: param malloc fail for %u "
7236 "bytes !\n", (unsigned int)state->total_param));
7237 SAFE_FREE(state->data);
7239 reply_nterror(req, NT_STATUS_NO_MEMORY);
7240 END_PROFILE(SMBtrans2);
7243 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7245 if ((smb_base(req->inbuf)+psoff+pscnt
7246 > (char *)req->inbuf + size) ||
7247 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7250 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7253 state->received_data = dscnt;
7254 state->received_param = pscnt;
7256 if ((state->received_param == state->total_param) &&
7257 (state->received_data == state->total_data)) {
7259 handle_trans2(conn, req, state);
7261 SAFE_FREE(state->data);
7262 SAFE_FREE(state->param);
7264 END_PROFILE(SMBtrans2);
7268 DLIST_ADD(conn->pending_trans, state);
7270 /* We need to send an interim response then receive the rest
7271 of the parameter/data bytes */
7272 reply_outbuf(req, 0, 0);
7273 show_msg((char *)req->outbuf);
7274 END_PROFILE(SMBtrans2);
7279 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7280 SAFE_FREE(state->data);
7281 SAFE_FREE(state->param);
7283 END_PROFILE(SMBtrans2);
7284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7288 /****************************************************************************
7289 Reply to a SMBtranss2
7290 ****************************************************************************/
7292 void reply_transs2(connection_struct *conn, struct smb_request *req)
7294 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7295 struct trans_state *state;
7298 START_PROFILE(SMBtranss2);
7300 show_msg((char *)req->inbuf);
7303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7304 END_PROFILE(SMBtranss2);
7308 size = smb_len(req->inbuf)+4;
7310 for (state = conn->pending_trans; state != NULL;
7311 state = state->next) {
7312 if (state->mid == req->mid) {
7317 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7319 END_PROFILE(SMBtranss2);
7323 /* Revise state->total_param and state->total_data in case they have
7324 changed downwards */
7326 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7327 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7328 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7329 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7331 pcnt = SVAL(req->inbuf, smb_spscnt);
7332 poff = SVAL(req->inbuf, smb_spsoff);
7333 pdisp = SVAL(req->inbuf, smb_spsdisp);
7335 dcnt = SVAL(req->inbuf, smb_sdscnt);
7336 doff = SVAL(req->inbuf, smb_sdsoff);
7337 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7339 state->received_param += pcnt;
7340 state->received_data += dcnt;
7342 if ((state->received_data > state->total_data) ||
7343 (state->received_param > state->total_param))
7347 if (pdisp+pcnt > state->total_param)
7349 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7351 if (pdisp > state->total_param)
7353 if ((smb_base(req->inbuf) + poff + pcnt
7354 > (char *)req->inbuf + size) ||
7355 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7357 if (state->param + pdisp < state->param)
7360 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7365 if (ddisp+dcnt > state->total_data)
7367 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7369 if (ddisp > state->total_data)
7371 if ((smb_base(req->inbuf) + doff + dcnt
7372 > (char *)req->inbuf + size) ||
7373 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7375 if (state->data + ddisp < state->data)
7378 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7382 if ((state->received_param < state->total_param) ||
7383 (state->received_data < state->total_data)) {
7384 END_PROFILE(SMBtranss2);
7389 * construct_reply_common will copy smb_com from inbuf to
7390 * outbuf. SMBtranss2 is wrong here.
7392 SCVAL(req->inbuf,smb_com,SMBtrans2);
7394 handle_trans2(conn, req, state);
7396 DLIST_REMOVE(conn->pending_trans, state);
7397 SAFE_FREE(state->data);
7398 SAFE_FREE(state->param);
7401 END_PROFILE(SMBtranss2);
7406 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7407 DLIST_REMOVE(conn->pending_trans, state);
7408 SAFE_FREE(state->data);
7409 SAFE_FREE(state->param);
7411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7412 END_PROFILE(SMBtranss2);