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 /* Needed to show the msdfs symlinks as
1274 if(lp_host_msdfs() &&
1275 lp_msdfs_root(SNUM(conn)) &&
1276 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1277 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1280 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1284 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1285 pathreal,strerror(errno)));
1291 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1293 mode = dos_mode(conn,pathreal,&sbuf);
1296 if (!dir_check_ftype(conn,mode,dirtype)) {
1297 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1301 if (!(mode & aDIR)) {
1302 file_size = get_file_size(sbuf);
1304 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1306 mdate_ts = get_mtimespec(&sbuf);
1307 adate_ts = get_atimespec(&sbuf);
1308 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1310 if (lp_dos_filetime_resolution(SNUM(conn))) {
1311 dos_filetime_timespec(&create_date_ts);
1312 dos_filetime_timespec(&mdate_ts);
1313 dos_filetime_timespec(&adate_ts);
1316 create_date = convert_timespec_to_time_t(create_date_ts);
1317 mdate = convert_timespec_to_time_t(mdate_ts);
1318 adate = convert_timespec_to_time_t(adate_ts);
1320 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1324 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1331 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1333 switch (info_level) {
1334 case SMB_FIND_INFO_STANDARD:
1335 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1336 if(requires_resume_key) {
1340 srv_put_dos_date2(p,0,create_date);
1341 srv_put_dos_date2(p,4,adate);
1342 srv_put_dos_date2(p,8,mdate);
1343 SIVAL(p,12,(uint32)file_size);
1344 SIVAL(p,16,(uint32)allocation_size);
1348 p += align_string(pdata, p, 0);
1349 len = srvstr_push(base_data, flags2, p,
1350 fname, PTR_DIFF(end_data, p),
1352 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1354 SCVAL(nameptr, -1, len - 2);
1356 SCVAL(nameptr, -1, 0);
1360 SCVAL(nameptr, -1, len - 1);
1362 SCVAL(nameptr, -1, 0);
1368 case SMB_FIND_EA_SIZE:
1369 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1370 if(requires_resume_key) {
1374 srv_put_dos_date2(p,0,create_date);
1375 srv_put_dos_date2(p,4,adate);
1376 srv_put_dos_date2(p,8,mdate);
1377 SIVAL(p,12,(uint32)file_size);
1378 SIVAL(p,16,(uint32)allocation_size);
1381 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1382 SIVAL(p,22,ea_size); /* Extended attributes */
1386 len = srvstr_push(base_data, flags2,
1387 p, fname, PTR_DIFF(end_data, p),
1388 STR_TERMINATE | STR_NOALIGN);
1389 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1402 SCVAL(nameptr,0,len);
1404 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1407 case SMB_FIND_EA_LIST:
1409 struct ea_list *file_list = NULL;
1412 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1416 if(requires_resume_key) {
1420 srv_put_dos_date2(p,0,create_date);
1421 srv_put_dos_date2(p,4,adate);
1422 srv_put_dos_date2(p,8,mdate);
1423 SIVAL(p,12,(uint32)file_size);
1424 SIVAL(p,16,(uint32)allocation_size);
1426 p += 22; /* p now points to the EA area. */
1428 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1429 name_list = ea_list_union(name_list, file_list, &ea_len);
1431 /* We need to determine if this entry will fit in the space available. */
1432 /* Max string size is 255 bytes. */
1433 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1434 /* Move the dirptr back to prev_dirpos */
1435 dptr_SeekDir(conn->dirptr, prev_dirpos);
1436 *out_of_space = True;
1437 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1438 return False; /* Not finished - just out of space */
1441 /* Push the ea_data followed by the name. */
1442 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1444 len = srvstr_push(base_data, flags2,
1445 p + 1, fname, PTR_DIFF(end_data, p),
1446 STR_TERMINATE | STR_NOALIGN);
1447 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1460 SCVAL(nameptr,0,len);
1462 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1466 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1467 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1468 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1470 SIVAL(p,0,reskey); p += 4;
1471 put_long_date_timespec(p,create_date_ts); p += 8;
1472 put_long_date_timespec(p,adate_ts); p += 8;
1473 put_long_date_timespec(p,mdate_ts); p += 8;
1474 put_long_date_timespec(p,mdate_ts); p += 8;
1475 SOFF_T(p,0,file_size); p += 8;
1476 SOFF_T(p,0,allocation_size); p += 8;
1477 SIVAL(p,0,nt_extmode); p += 4;
1478 q = p; p += 4; /* q is placeholder for name length. */
1480 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1481 SIVAL(p,0,ea_size); /* Extended attributes */
1484 /* Clear the short name buffer. This is
1485 * IMPORTANT as not doing so will trigger
1486 * a Win2k client bug. JRA.
1488 if (!was_8_3 && check_mangled_names) {
1489 if (!name_to_8_3(fname,mangled_name,True,
1491 /* Error - mangle failed ! */
1492 memset(mangled_name,'\0',12);
1494 mangled_name[12] = 0;
1495 len = srvstr_push(base_data, flags2,
1496 p+2, mangled_name, 24,
1497 STR_UPPER|STR_UNICODE);
1499 memset(p + 2 + len,'\0',24 - len);
1506 len = srvstr_push(base_data, flags2, p,
1507 fname, PTR_DIFF(end_data, p),
1508 STR_TERMINATE_ASCII);
1511 SIVAL(p,0,0); /* Ensure any padding is null. */
1512 len = PTR_DIFF(p, pdata);
1513 len = (len + 3) & ~3;
1518 case SMB_FIND_FILE_DIRECTORY_INFO:
1519 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1521 SIVAL(p,0,reskey); p += 4;
1522 put_long_date_timespec(p,create_date_ts); p += 8;
1523 put_long_date_timespec(p,adate_ts); p += 8;
1524 put_long_date_timespec(p,mdate_ts); p += 8;
1525 put_long_date_timespec(p,mdate_ts); p += 8;
1526 SOFF_T(p,0,file_size); p += 8;
1527 SOFF_T(p,0,allocation_size); p += 8;
1528 SIVAL(p,0,nt_extmode); p += 4;
1529 len = srvstr_push(base_data, flags2,
1530 p + 4, fname, PTR_DIFF(end_data, p),
1531 STR_TERMINATE_ASCII);
1534 SIVAL(p,0,0); /* Ensure any padding is null. */
1535 len = PTR_DIFF(p, pdata);
1536 len = (len + 3) & ~3;
1541 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1544 SIVAL(p,0,reskey); p += 4;
1545 put_long_date_timespec(p,create_date_ts); p += 8;
1546 put_long_date_timespec(p,adate_ts); p += 8;
1547 put_long_date_timespec(p,mdate_ts); p += 8;
1548 put_long_date_timespec(p,mdate_ts); p += 8;
1549 SOFF_T(p,0,file_size); p += 8;
1550 SOFF_T(p,0,allocation_size); p += 8;
1551 SIVAL(p,0,nt_extmode); p += 4;
1552 q = p; p += 4; /* q is placeholder for name length. */
1554 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1555 SIVAL(p,0,ea_size); /* Extended attributes */
1558 len = srvstr_push(base_data, flags2, p,
1559 fname, PTR_DIFF(end_data, p),
1560 STR_TERMINATE_ASCII);
1564 SIVAL(p,0,0); /* Ensure any padding is null. */
1565 len = PTR_DIFF(p, pdata);
1566 len = (len + 3) & ~3;
1571 case SMB_FIND_FILE_NAMES_INFO:
1572 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1574 SIVAL(p,0,reskey); p += 4;
1576 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1577 acl on a dir (tridge) */
1578 len = srvstr_push(base_data, flags2, p,
1579 fname, PTR_DIFF(end_data, p),
1580 STR_TERMINATE_ASCII);
1583 SIVAL(p,0,0); /* Ensure any padding is null. */
1584 len = PTR_DIFF(p, pdata);
1585 len = (len + 3) & ~3;
1590 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1591 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1593 SIVAL(p,0,reskey); p += 4;
1594 put_long_date_timespec(p,create_date_ts); p += 8;
1595 put_long_date_timespec(p,adate_ts); p += 8;
1596 put_long_date_timespec(p,mdate_ts); p += 8;
1597 put_long_date_timespec(p,mdate_ts); p += 8;
1598 SOFF_T(p,0,file_size); p += 8;
1599 SOFF_T(p,0,allocation_size); p += 8;
1600 SIVAL(p,0,nt_extmode); p += 4;
1601 q = p; p += 4; /* q is placeholder for name length. */
1603 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1604 SIVAL(p,0,ea_size); /* Extended attributes */
1607 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1608 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1609 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1610 len = srvstr_push(base_data, flags2, p,
1611 fname, PTR_DIFF(end_data, p),
1612 STR_TERMINATE_ASCII);
1615 SIVAL(p,0,0); /* Ensure any padding is null. */
1616 len = PTR_DIFF(p, pdata);
1617 len = (len + 3) & ~3;
1622 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1623 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1624 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1626 SIVAL(p,0,reskey); p += 4;
1627 put_long_date_timespec(p,create_date_ts); p += 8;
1628 put_long_date_timespec(p,adate_ts); p += 8;
1629 put_long_date_timespec(p,mdate_ts); p += 8;
1630 put_long_date_timespec(p,mdate_ts); p += 8;
1631 SOFF_T(p,0,file_size); p += 8;
1632 SOFF_T(p,0,allocation_size); p += 8;
1633 SIVAL(p,0,nt_extmode); p += 4;
1634 q = p; p += 4; /* q is placeholder for name length */
1636 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1637 SIVAL(p,0,ea_size); /* Extended attributes */
1640 /* Clear the short name buffer. This is
1641 * IMPORTANT as not doing so will trigger
1642 * a Win2k client bug. JRA.
1644 if (!was_8_3 && check_mangled_names) {
1645 if (!name_to_8_3(fname,mangled_name,True,
1647 /* Error - mangle failed ! */
1648 memset(mangled_name,'\0',12);
1650 mangled_name[12] = 0;
1651 len = srvstr_push(base_data, flags2,
1652 p+2, mangled_name, 24,
1653 STR_UPPER|STR_UNICODE);
1656 memset(p + 2 + len,'\0',24 - len);
1663 SSVAL(p,0,0); p += 2; /* Reserved ? */
1664 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1665 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1666 len = srvstr_push(base_data, flags2, p,
1667 fname, PTR_DIFF(end_data, p),
1668 STR_TERMINATE_ASCII);
1671 SIVAL(p,0,0); /* Ensure any padding is null. */
1672 len = PTR_DIFF(p, pdata);
1673 len = (len + 3) & ~3;
1678 /* CIFS UNIX Extension. */
1680 case SMB_FIND_FILE_UNIX:
1681 case SMB_FIND_FILE_UNIX_INFO2:
1683 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1685 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1687 if (info_level == SMB_FIND_FILE_UNIX) {
1688 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1689 p = store_file_unix_basic(conn, p,
1691 len = srvstr_push(base_data, flags2, p,
1692 fname, PTR_DIFF(end_data, p),
1695 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1696 p = store_file_unix_basic_info2(conn, p,
1700 len = srvstr_push(base_data, flags2, p, fname,
1701 PTR_DIFF(end_data, p), 0);
1702 SIVAL(nameptr, 0, len);
1706 SIVAL(p,0,0); /* Ensure any padding is null. */
1708 len = PTR_DIFF(p, pdata);
1709 len = (len + 3) & ~3;
1710 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1712 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1721 if (PTR_DIFF(p,pdata) > space_remaining) {
1722 /* Move the dirptr back to prev_dirpos */
1723 dptr_SeekDir(conn->dirptr, prev_dirpos);
1724 *out_of_space = True;
1725 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1726 return False; /* Not finished - just out of space */
1729 /* Setup the last entry pointer, as an offset from base_data */
1730 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1731 /* Advance the data pointer to the next slot */
1737 /****************************************************************************
1738 Reply to a TRANS2_FINDFIRST.
1739 ****************************************************************************/
1741 static void call_trans2findfirst(connection_struct *conn,
1742 struct smb_request *req,
1743 char **pparams, int total_params,
1744 char **ppdata, int total_data,
1745 unsigned int max_data_bytes)
1747 /* We must be careful here that we don't return more than the
1748 allowed number of data bytes. If this means returning fewer than
1749 maxentries then so be it. We assume that the redirector has
1750 enough room for the fixed number of parameter bytes it has
1752 char *params = *pparams;
1753 char *pdata = *ppdata;
1757 uint16 findfirst_flags;
1758 BOOL close_after_first;
1760 BOOL requires_resume_key;
1762 pstring directory_in;
1763 char *directory = NULL;
1766 int last_entry_off=0;
1770 BOOL finished = False;
1771 BOOL dont_descend = False;
1772 BOOL out_of_space = False;
1773 int space_remaining;
1774 BOOL mask_contains_wcard = False;
1775 SMB_STRUCT_STAT sbuf;
1776 TALLOC_CTX *ea_ctx = NULL;
1777 struct ea_list *ea_list = NULL;
1778 NTSTATUS ntstatus = NT_STATUS_OK;
1779 TALLOC_CTX *ctx = talloc_tos();
1781 if (total_params < 13) {
1782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1786 dirtype = SVAL(params,0);
1787 maxentries = SVAL(params,2);
1788 findfirst_flags = SVAL(params,4);
1789 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1790 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1791 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1792 info_level = SVAL(params,6);
1794 *directory_in = *mask = 0;
1796 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1797 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1798 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1799 info_level, max_data_bytes));
1802 /* W2K3 seems to treat zero as 1. */
1806 switch (info_level) {
1807 case SMB_FIND_INFO_STANDARD:
1808 case SMB_FIND_EA_SIZE:
1809 case SMB_FIND_EA_LIST:
1810 case SMB_FIND_FILE_DIRECTORY_INFO:
1811 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1812 case SMB_FIND_FILE_NAMES_INFO:
1813 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1814 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1815 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1817 case SMB_FIND_FILE_UNIX:
1818 case SMB_FIND_FILE_UNIX_INFO2:
1819 if (!lp_unix_extensions()) {
1820 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1825 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1829 srvstr_get_path_wcard(params, req->flags2, directory_in,
1830 params+12, sizeof(directory_in), total_params - 12,
1831 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1832 if (!NT_STATUS_IS_OK(ntstatus)) {
1833 reply_nterror(req, ntstatus);
1837 ntstatus = resolve_dfspath_wcard(ctx, conn,
1838 req->flags2 & FLAGS2_DFS_PATHNAMES,
1841 &mask_contains_wcard);
1842 if (!NT_STATUS_IS_OK(ntstatus)) {
1843 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1844 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1845 ERRSRV, ERRbadpath);
1848 reply_nterror(req, ntstatus);
1852 ntstatus = unix_convert(conn, directory, True, &directory, NULL, &sbuf);
1853 if (!NT_STATUS_IS_OK(ntstatus)) {
1854 reply_nterror(req, ntstatus);
1858 ntstatus = check_name(conn, directory);
1859 if (!NT_STATUS_IS_OK(ntstatus)) {
1860 reply_nterror(req, ntstatus);
1864 p = strrchr_m(directory,'/');
1866 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1867 if((directory[0] == '.') && (directory[1] == '\0')) {
1869 mask_contains_wcard = True;
1871 pstrcpy(mask,directory);
1873 directory = talloc_strdup(talloc_tos(), "./");
1875 reply_nterror(req, NT_STATUS_NO_MEMORY);
1883 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1885 if (info_level == SMB_FIND_EA_LIST) {
1888 if (total_data < 4) {
1889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1893 ea_size = IVAL(pdata,0);
1894 if (ea_size != total_data) {
1895 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1896 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1901 if (!lp_ea_support(SNUM(conn))) {
1902 reply_doserror(req, ERRDOS, ERReasnotsupported);
1906 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1907 reply_nterror(req, NT_STATUS_NO_MEMORY);
1911 /* Pull out the list of names. */
1912 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1914 talloc_destroy(ea_ctx);
1915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1920 *ppdata = (char *)SMB_REALLOC(
1921 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1922 if(*ppdata == NULL ) {
1923 talloc_destroy(ea_ctx);
1924 reply_nterror(req, NT_STATUS_NO_MEMORY);
1928 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1930 /* Realloc the params space */
1931 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1932 if (*pparams == NULL) {
1933 talloc_destroy(ea_ctx);
1934 reply_nterror(req, NT_STATUS_NO_MEMORY);
1939 /* Save the wildcard match and attribs we are using on this directory -
1940 needed as lanman2 assumes these are being saved between calls */
1942 ntstatus = dptr_create(conn,
1948 mask_contains_wcard,
1952 if (!NT_STATUS_IS_OK(ntstatus)) {
1953 talloc_destroy(ea_ctx);
1954 reply_nterror(req, ntstatus);
1958 dptr_num = dptr_dnum(conn->dirptr);
1959 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1961 /* We don't need to check for VOL here as this is returned by
1962 a different TRANS2 call. */
1964 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1965 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1966 dont_descend = True;
1969 space_remaining = max_data_bytes;
1970 out_of_space = False;
1972 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1973 BOOL got_exact_match = False;
1975 /* this is a heuristic to avoid seeking the dirptr except when
1976 absolutely necessary. It allows for a filename of about 40 chars */
1977 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1978 out_of_space = True;
1981 finished = !get_lanman2_dir_entry(conn,
1983 mask,dirtype,info_level,
1984 requires_resume_key,dont_descend,
1986 space_remaining, &out_of_space,
1988 &last_entry_off, ea_list, ea_ctx);
1991 if (finished && out_of_space)
1994 if (!finished && !out_of_space)
1998 * As an optimisation if we know we aren't looking
1999 * for a wildcard name (ie. the name matches the wildcard exactly)
2000 * then we can finish on any (first) match.
2001 * This speeds up large directory searches. JRA.
2007 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2010 talloc_destroy(ea_ctx);
2012 /* Check if we can close the dirptr */
2013 if(close_after_first || (finished && close_if_end)) {
2014 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2015 dptr_close(&dptr_num);
2019 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2020 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2021 * the protocol level is less than NT1. Tested with smbclient. JRA.
2022 * This should fix the OS/2 client bug #2335.
2025 if(numentries == 0) {
2026 dptr_close(&dptr_num);
2027 if (Protocol < PROTOCOL_NT1) {
2028 reply_doserror(req, ERRDOS, ERRnofiles);
2031 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2032 ERRDOS, ERRbadfile);
2037 /* At this point pdata points to numentries directory entries. */
2039 /* Set up the return parameter block */
2040 SSVAL(params,0,dptr_num);
2041 SSVAL(params,2,numentries);
2042 SSVAL(params,4,finished);
2043 SSVAL(params,6,0); /* Never an EA error */
2044 SSVAL(params,8,last_entry_off);
2046 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2049 if ((! *directory) && dptr_path(dptr_num)) {
2050 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2052 reply_nterror(req, NT_STATUS_NO_MEMORY);
2056 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2057 smb_fn_name(CVAL(req->inbuf,smb_com)),
2058 mask, directory, dirtype, numentries ) );
2061 * Force a name mangle here to ensure that the
2062 * mask as an 8.3 name is top of the mangled cache.
2063 * The reasons for this are subtle. Don't remove
2064 * this code unless you know what you are doing
2065 * (see PR#13758). JRA.
2068 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2069 char mangled_name[13];
2070 name_to_8_3(mask, mangled_name, True, conn->params);
2076 /****************************************************************************
2077 Reply to a TRANS2_FINDNEXT.
2078 ****************************************************************************/
2080 static void call_trans2findnext(connection_struct *conn,
2081 struct smb_request *req,
2082 char **pparams, int total_params,
2083 char **ppdata, int total_data,
2084 unsigned int max_data_bytes)
2086 /* We must be careful here that we don't return more than the
2087 allowed number of data bytes. If this means returning fewer than
2088 maxentries then so be it. We assume that the redirector has
2089 enough room for the fixed number of parameter bytes it has
2091 char *params = *pparams;
2092 char *pdata = *ppdata;
2098 uint16 findnext_flags;
2099 BOOL close_after_request;
2101 BOOL requires_resume_key;
2103 BOOL mask_contains_wcard = False;
2104 pstring resume_name;
2110 int i, last_entry_off=0;
2111 BOOL finished = False;
2112 BOOL dont_descend = False;
2113 BOOL out_of_space = False;
2114 int space_remaining;
2115 TALLOC_CTX *ea_ctx = NULL;
2116 struct ea_list *ea_list = NULL;
2117 NTSTATUS ntstatus = NT_STATUS_OK;
2119 if (total_params < 13) {
2120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2124 dptr_num = SVAL(params,0);
2125 maxentries = SVAL(params,2);
2126 info_level = SVAL(params,4);
2127 resume_key = IVAL(params,6);
2128 findnext_flags = SVAL(params,10);
2129 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2130 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2131 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2132 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2134 *mask = *directory = *resume_name = 0;
2136 srvstr_get_path_wcard(params, req->flags2, resume_name,
2137 params+12, sizeof(resume_name),
2138 total_params - 12, STR_TERMINATE, &ntstatus,
2139 &mask_contains_wcard);
2140 if (!NT_STATUS_IS_OK(ntstatus)) {
2141 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2142 complain (it thinks we're asking for the directory above the shared
2143 path or an invalid name). Catch this as the resume name is only compared, never used in
2144 a file access. JRA. */
2145 srvstr_pull(params, req->flags2,
2146 resume_name, params+12,
2147 sizeof(resume_name), total_params - 12,
2150 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2151 reply_nterror(req, ntstatus);
2156 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2157 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2158 resume_key = %d resume name = %s continue=%d level = %d\n",
2159 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2160 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2163 /* W2K3 seems to treat zero as 1. */
2167 switch (info_level) {
2168 case SMB_FIND_INFO_STANDARD:
2169 case SMB_FIND_EA_SIZE:
2170 case SMB_FIND_EA_LIST:
2171 case SMB_FIND_FILE_DIRECTORY_INFO:
2172 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2173 case SMB_FIND_FILE_NAMES_INFO:
2174 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2175 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2176 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2178 case SMB_FIND_FILE_UNIX:
2179 case SMB_FIND_FILE_UNIX_INFO2:
2180 if (!lp_unix_extensions()) {
2181 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2186 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2190 if (info_level == SMB_FIND_EA_LIST) {
2193 if (total_data < 4) {
2194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2198 ea_size = IVAL(pdata,0);
2199 if (ea_size != total_data) {
2200 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2201 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2206 if (!lp_ea_support(SNUM(conn))) {
2207 reply_doserror(req, ERRDOS, ERReasnotsupported);
2211 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2212 reply_nterror(req, NT_STATUS_NO_MEMORY);
2216 /* Pull out the list of names. */
2217 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2219 talloc_destroy(ea_ctx);
2220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2225 *ppdata = (char *)SMB_REALLOC(
2226 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2227 if(*ppdata == NULL) {
2228 talloc_destroy(ea_ctx);
2229 reply_nterror(req, NT_STATUS_NO_MEMORY);
2234 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2236 /* Realloc the params space */
2237 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2238 if(*pparams == NULL ) {
2239 talloc_destroy(ea_ctx);
2240 reply_nterror(req, NT_STATUS_NO_MEMORY);
2246 /* Check that the dptr is valid */
2247 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2248 talloc_destroy(ea_ctx);
2249 reply_doserror(req, ERRDOS, ERRnofiles);
2253 string_set(&conn->dirpath,dptr_path(dptr_num));
2255 /* Get the wildcard mask from the dptr */
2256 if((p = dptr_wcard(dptr_num))== NULL) {
2257 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2258 talloc_destroy(ea_ctx);
2259 reply_doserror(req, ERRDOS, ERRnofiles);
2264 pstrcpy(directory,conn->dirpath);
2266 /* Get the attr mask from the dptr */
2267 dirtype = dptr_attr(dptr_num);
2269 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2270 dptr_num, mask, dirtype,
2272 dptr_TellDir(conn->dirptr)));
2274 /* We don't need to check for VOL here as this is returned by
2275 a different TRANS2 call. */
2277 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2278 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2279 dont_descend = True;
2282 space_remaining = max_data_bytes;
2283 out_of_space = False;
2286 * Seek to the correct position. We no longer use the resume key but
2287 * depend on the last file name instead.
2290 if(*resume_name && !continue_bit) {
2293 long current_pos = 0;
2295 * Remember, name_to_8_3 is called by
2296 * get_lanman2_dir_entry(), so the resume name
2297 * could be mangled. Ensure we check the unmangled name.
2300 if (mangle_is_mangled(resume_name, conn->params)) {
2301 char *new_resume_name = NULL;
2302 mangle_lookup_name_from_8_3(talloc_tos(),
2306 if (new_resume_name) {
2307 pstrcpy(resume_name, new_resume_name);
2312 * Fix for NT redirector problem triggered by resume key indexes
2313 * changing between directory scans. We now return a resume key of 0
2314 * and instead look for the filename to continue from (also given
2315 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2316 * findfirst/findnext (as is usual) then the directory pointer
2317 * should already be at the correct place.
2320 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2321 } /* end if resume_name && !continue_bit */
2323 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2324 BOOL got_exact_match = False;
2326 /* this is a heuristic to avoid seeking the dirptr except when
2327 absolutely necessary. It allows for a filename of about 40 chars */
2328 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2329 out_of_space = True;
2332 finished = !get_lanman2_dir_entry(conn,
2334 mask,dirtype,info_level,
2335 requires_resume_key,dont_descend,
2337 space_remaining, &out_of_space,
2339 &last_entry_off, ea_list, ea_ctx);
2342 if (finished && out_of_space)
2345 if (!finished && !out_of_space)
2349 * As an optimisation if we know we aren't looking
2350 * for a wildcard name (ie. the name matches the wildcard exactly)
2351 * then we can finish on any (first) match.
2352 * This speeds up large directory searches. JRA.
2358 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2361 talloc_destroy(ea_ctx);
2363 /* Check if we can close the dirptr */
2364 if(close_after_request || (finished && close_if_end)) {
2365 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2366 dptr_close(&dptr_num); /* This frees up the saved mask */
2369 /* Set up the return parameter block */
2370 SSVAL(params,0,numentries);
2371 SSVAL(params,2,finished);
2372 SSVAL(params,4,0); /* Never an EA error */
2373 SSVAL(params,6,last_entry_off);
2375 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2378 if ((! *directory) && dptr_path(dptr_num))
2379 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2381 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2382 smb_fn_name(CVAL(req->inbuf,smb_com)),
2383 mask, directory, dirtype, numentries ) );
2388 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2390 E_md4hash(lp_servicename(SNUM(conn)),objid);
2394 /****************************************************************************
2395 Reply to a TRANS2_QFSINFO (query filesystem info).
2396 ****************************************************************************/
2398 static void call_trans2qfsinfo(connection_struct *conn,
2399 struct smb_request *req,
2400 char **pparams, int total_params,
2401 char **ppdata, int total_data,
2402 unsigned int max_data_bytes)
2404 char *pdata, *end_data;
2405 char *params = *pparams;
2409 const char *vname = volume_label(SNUM(conn));
2410 int snum = SNUM(conn);
2411 char *fstype = lp_fstype(SNUM(conn));
2414 if (total_params < 2) {
2415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2419 info_level = SVAL(params,0);
2421 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2423 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2424 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2425 reply_doserror(req, ERRSRV, ERRinvdevice);
2429 *ppdata = (char *)SMB_REALLOC(
2430 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2431 if (*ppdata == NULL ) {
2432 reply_nterror(req, NT_STATUS_NO_MEMORY);
2437 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2438 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2440 switch (info_level) {
2441 case SMB_INFO_ALLOCATION:
2443 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2445 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2446 reply_unixerror(req, ERRHRD, ERRgeneral);
2450 block_size = lp_block_size(snum);
2451 if (bsize < block_size) {
2452 SMB_BIG_UINT factor = block_size/bsize;
2457 if (bsize > block_size) {
2458 SMB_BIG_UINT factor = bsize/block_size;
2463 bytes_per_sector = 512;
2464 sectors_per_unit = bsize/bytes_per_sector;
2466 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2467 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2468 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2470 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2471 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2472 SIVAL(pdata,l1_cUnit,dsize);
2473 SIVAL(pdata,l1_cUnitAvail,dfree);
2474 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2478 case SMB_INFO_VOLUME:
2479 /* Return volume name */
2481 * Add volume serial number - hash of a combination of
2482 * the called hostname and the service name.
2484 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2486 * Win2k3 and previous mess this up by sending a name length
2487 * one byte short. I believe only older clients (OS/2 Win9x) use
2488 * this call so try fixing this by adding a terminating null to
2489 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2493 pdata+l2_vol_szVolLabel, vname,
2494 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2495 STR_NOALIGN|STR_TERMINATE);
2496 SCVAL(pdata,l2_vol_cch,len);
2497 data_len = l2_vol_szVolLabel + len;
2498 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2499 (unsigned)st.st_ctime, len, vname));
2502 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2503 case SMB_FS_ATTRIBUTE_INFORMATION:
2506 #if defined(HAVE_SYS_QUOTAS)
2507 quota_flag = FILE_VOLUME_QUOTAS;
2510 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2511 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2512 FILE_SUPPORTS_OBJECT_IDS|
2513 FILE_UNICODE_ON_DISK|
2514 quota_flag); /* FS ATTRIBUTES */
2516 SIVAL(pdata,4,255); /* Max filename component length */
2517 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2518 and will think we can't do long filenames */
2519 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2520 PTR_DIFF(end_data, pdata+12),
2523 data_len = 12 + len;
2526 case SMB_QUERY_FS_LABEL_INFO:
2527 case SMB_FS_LABEL_INFORMATION:
2528 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2529 PTR_DIFF(end_data, pdata+4), 0);
2534 case SMB_QUERY_FS_VOLUME_INFO:
2535 case SMB_FS_VOLUME_INFORMATION:
2538 * Add volume serial number - hash of a combination of
2539 * the called hostname and the service name.
2541 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2542 (str_checksum(get_local_machine_name())<<16));
2544 /* Max label len is 32 characters. */
2545 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2546 PTR_DIFF(end_data, pdata+18),
2548 SIVAL(pdata,12,len);
2551 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2552 (int)strlen(vname),vname, lp_servicename(snum)));
2555 case SMB_QUERY_FS_SIZE_INFO:
2556 case SMB_FS_SIZE_INFORMATION:
2558 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2560 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2561 reply_unixerror(req, ERRHRD, ERRgeneral);
2564 block_size = lp_block_size(snum);
2565 if (bsize < block_size) {
2566 SMB_BIG_UINT factor = block_size/bsize;
2571 if (bsize > block_size) {
2572 SMB_BIG_UINT factor = bsize/block_size;
2577 bytes_per_sector = 512;
2578 sectors_per_unit = bsize/bytes_per_sector;
2579 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2580 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2581 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2582 SBIG_UINT(pdata,0,dsize);
2583 SBIG_UINT(pdata,8,dfree);
2584 SIVAL(pdata,16,sectors_per_unit);
2585 SIVAL(pdata,20,bytes_per_sector);
2589 case SMB_FS_FULL_SIZE_INFORMATION:
2591 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2593 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2594 reply_unixerror(req, ERRHRD, ERRgeneral);
2597 block_size = lp_block_size(snum);
2598 if (bsize < block_size) {
2599 SMB_BIG_UINT factor = block_size/bsize;
2604 if (bsize > block_size) {
2605 SMB_BIG_UINT factor = bsize/block_size;
2610 bytes_per_sector = 512;
2611 sectors_per_unit = bsize/bytes_per_sector;
2612 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2613 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2614 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2615 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2616 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2617 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2618 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2619 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2623 case SMB_QUERY_FS_DEVICE_INFO:
2624 case SMB_FS_DEVICE_INFORMATION:
2626 SIVAL(pdata,0,0); /* dev type */
2627 SIVAL(pdata,4,0); /* characteristics */
2630 #ifdef HAVE_SYS_QUOTAS
2631 case SMB_FS_QUOTA_INFORMATION:
2633 * what we have to send --metze:
2635 * Unknown1: 24 NULL bytes
2636 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2637 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2638 * Quota Flags: 2 byte :
2639 * Unknown3: 6 NULL bytes
2643 * details for Quota Flags:
2645 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2646 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2647 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2648 * 0x0001 Enable Quotas: enable quota for this fs
2652 /* we need to fake up a fsp here,
2653 * because its not send in this call
2656 SMB_NTQUOTA_STRUCT quotas;
2659 ZERO_STRUCT(quotas);
2665 if (current_user.ut.uid != 0) {
2666 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2667 lp_servicename(SNUM(conn)),conn->user));
2668 reply_doserror(req, ERRDOS, ERRnoaccess);
2672 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2673 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2674 reply_doserror(req, ERRSRV, ERRerror);
2680 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2682 /* Unknown1 24 NULL bytes*/
2683 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2684 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2685 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2687 /* Default Soft Quota 8 bytes */
2688 SBIG_UINT(pdata,24,quotas.softlim);
2690 /* Default Hard Quota 8 bytes */
2691 SBIG_UINT(pdata,32,quotas.hardlim);
2693 /* Quota flag 2 bytes */
2694 SSVAL(pdata,40,quotas.qflags);
2696 /* Unknown3 6 NULL bytes */
2702 #endif /* HAVE_SYS_QUOTAS */
2703 case SMB_FS_OBJECTID_INFORMATION:
2705 unsigned char objid[16];
2706 memcpy(pdata,create_volume_objectid(conn, objid),16);
2712 * Query the version and capabilities of the CIFS UNIX extensions
2716 case SMB_QUERY_CIFS_UNIX_INFO:
2717 if (!lp_unix_extensions()) {
2718 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2722 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2723 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2724 /* We have POSIX ACLs, pathname and locking capability. */
2725 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2726 CIFS_UNIX_POSIX_ACLS_CAP|
2727 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2728 CIFS_UNIX_FCNTL_LOCKS_CAP|
2729 CIFS_UNIX_EXTATTR_CAP|
2730 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2731 /* Ensure we don't do this on signed or sealed data. */
2732 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2736 case SMB_QUERY_POSIX_FS_INFO:
2739 vfs_statvfs_struct svfs;
2741 if (!lp_unix_extensions()) {
2742 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2746 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2750 SIVAL(pdata,0,svfs.OptimalTransferSize);
2751 SIVAL(pdata,4,svfs.BlockSize);
2752 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2753 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2754 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2755 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2756 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2757 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2758 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2760 } else if (rc == EOPNOTSUPP) {
2761 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2763 #endif /* EOPNOTSUPP */
2765 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2766 reply_doserror(req, ERRSRV, ERRerror);
2772 case SMB_QUERY_POSIX_WHOAMI:
2778 if (!lp_unix_extensions()) {
2779 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2783 if (max_data_bytes < 40) {
2784 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2788 /* We ARE guest if global_sid_Builtin_Guests is
2789 * in our list of SIDs.
2791 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2792 current_user.nt_user_token)) {
2793 flags |= SMB_WHOAMI_GUEST;
2796 /* We are NOT guest if global_sid_Authenticated_Users
2797 * is in our list of SIDs.
2799 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2800 current_user.nt_user_token)) {
2801 flags &= ~SMB_WHOAMI_GUEST;
2804 /* NOTE: 8 bytes for UID/GID, irrespective of native
2805 * platform size. This matches
2806 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2808 data_len = 4 /* flags */
2815 + 4 /* pad/reserved */
2816 + (current_user.ut.ngroups * 8)
2818 + (current_user.nt_user_token->num_sids *
2822 SIVAL(pdata, 0, flags);
2823 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2824 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2825 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2828 if (data_len >= max_data_bytes) {
2829 /* Potential overflow, skip the GIDs and SIDs. */
2831 SIVAL(pdata, 24, 0); /* num_groups */
2832 SIVAL(pdata, 28, 0); /* num_sids */
2833 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2834 SIVAL(pdata, 36, 0); /* reserved */
2840 SIVAL(pdata, 24, current_user.ut.ngroups);
2842 current_user.nt_user_token->num_sids);
2844 /* We walk the SID list twice, but this call is fairly
2845 * infrequent, and I don't expect that it's performance
2846 * sensitive -- jpeach
2848 for (i = 0, sid_bytes = 0;
2849 i < current_user.nt_user_token->num_sids; ++i) {
2851 sid_size(¤t_user.nt_user_token->user_sids[i]);
2854 /* SID list byte count */
2855 SIVAL(pdata, 32, sid_bytes);
2857 /* 4 bytes pad/reserved - must be zero */
2858 SIVAL(pdata, 36, 0);
2862 for (i = 0; i < current_user.ut.ngroups; ++i) {
2863 SBIG_UINT(pdata, data_len,
2864 (SMB_BIG_UINT)current_user.ut.groups[i]);
2870 i < current_user.nt_user_token->num_sids; ++i) {
2872 sid_size(¤t_user.nt_user_token->user_sids[i]);
2874 sid_linearize(pdata + data_len, sid_len,
2875 ¤t_user.nt_user_token->user_sids[i]);
2876 data_len += sid_len;
2882 case SMB_MAC_QUERY_FS_INFO:
2884 * Thursby MAC extension... ONLY on NTFS filesystems
2885 * once we do streams then we don't need this
2887 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2889 SIVAL(pdata,84,0x100); /* Don't support mac... */
2894 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2899 send_trans2_replies(req, params, 0, pdata, data_len,
2902 DEBUG( 4, ( "%s info_level = %d\n",
2903 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2908 /****************************************************************************
2909 Reply to a TRANS2_SETFSINFO (set filesystem info).
2910 ****************************************************************************/
2912 static void call_trans2setfsinfo(connection_struct *conn,
2913 struct smb_request *req,
2914 char **pparams, int total_params,
2915 char **ppdata, int total_data,
2916 unsigned int max_data_bytes)
2918 char *pdata = *ppdata;
2919 char *params = *pparams;
2922 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2925 if (total_params < 4) {
2926 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2932 info_level = SVAL(params,2);
2934 switch(info_level) {
2935 case SMB_SET_CIFS_UNIX_INFO:
2937 uint16 client_unix_major;
2938 uint16 client_unix_minor;
2939 uint32 client_unix_cap_low;
2940 uint32 client_unix_cap_high;
2942 if (!lp_unix_extensions()) {
2944 NT_STATUS_INVALID_LEVEL);
2948 /* There should be 12 bytes of capabilities set. */
2949 if (total_data < 8) {
2952 NT_STATUS_INVALID_PARAMETER);
2955 client_unix_major = SVAL(pdata,0);
2956 client_unix_minor = SVAL(pdata,2);
2957 client_unix_cap_low = IVAL(pdata,4);
2958 client_unix_cap_high = IVAL(pdata,8);
2959 /* Just print these values for now. */
2960 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2961 cap_low = 0x%x, cap_high = 0x%x\n",
2962 (unsigned int)client_unix_major,
2963 (unsigned int)client_unix_minor,
2964 (unsigned int)client_unix_cap_low,
2965 (unsigned int)client_unix_cap_high ));
2967 /* Here is where we must switch to posix pathname processing... */
2968 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2969 lp_set_posix_pathnames();
2970 mangle_change_to_posix();
2973 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2974 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2975 /* Client that knows how to do posix locks,
2976 * but not posix open/mkdir operations. Set a
2977 * default type for read/write checks. */
2979 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2984 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2987 size_t param_len = 0;
2988 size_t data_len = total_data;
2990 if (!lp_unix_extensions()) {
2992 req, NT_STATUS_INVALID_LEVEL);
2996 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2998 status = srv_request_encryption_setup(conn,
2999 (unsigned char **)ppdata,
3001 (unsigned char **)pparams,
3005 if (!NT_STATUS_IS_OK(status)) {
3008 * MORE_PROCESSING_REQUIRED, this used
3009 * to have special handling here.
3011 reply_nterror(req, status);
3015 send_trans2_replies(req,
3016 *pparams, param_len,
3020 if (NT_STATUS_IS_OK(status)) {
3021 /* Server-side transport encryption is now *on*. */
3022 status = srv_encryption_start(conn);
3023 if (!NT_STATUS_IS_OK(status)) {
3024 exit_server_cleanly("Failure in setting up encrypted transport");
3029 case SMB_FS_QUOTA_INFORMATION:
3031 files_struct *fsp = NULL;
3032 SMB_NTQUOTA_STRUCT quotas;
3034 ZERO_STRUCT(quotas);
3037 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3038 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3039 lp_servicename(SNUM(conn)),conn->user));
3040 reply_doserror(req, ERRSRV, ERRaccess);
3044 /* note: normaly there're 48 bytes,
3045 * but we didn't use the last 6 bytes for now
3048 fsp = file_fsp(SVAL(params,0));
3049 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3050 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3052 req, NT_STATUS_INVALID_HANDLE);
3056 if (total_data < 42) {
3057 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3061 NT_STATUS_INVALID_PARAMETER);
3065 /* unknown_1 24 NULL bytes in pdata*/
3067 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3068 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3069 #ifdef LARGE_SMB_OFF_T
3070 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3071 #else /* LARGE_SMB_OFF_T */
3072 if ((IVAL(pdata,28) != 0)&&
3073 ((quotas.softlim != 0xFFFFFFFF)||
3074 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3075 /* more than 32 bits? */
3078 NT_STATUS_INVALID_PARAMETER);
3081 #endif /* LARGE_SMB_OFF_T */
3083 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3084 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3085 #ifdef LARGE_SMB_OFF_T
3086 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3087 #else /* LARGE_SMB_OFF_T */
3088 if ((IVAL(pdata,36) != 0)&&
3089 ((quotas.hardlim != 0xFFFFFFFF)||
3090 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3091 /* more than 32 bits? */
3094 NT_STATUS_INVALID_PARAMETER);
3097 #endif /* LARGE_SMB_OFF_T */
3099 /* quota_flags 2 bytes **/
3100 quotas.qflags = SVAL(pdata,40);
3102 /* unknown_2 6 NULL bytes follow*/
3104 /* now set the quotas */
3105 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3106 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3107 reply_doserror(req, ERRSRV, ERRerror);
3114 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3116 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3122 * sending this reply works fine,
3123 * but I'm not sure it's the same
3124 * like windows do...
3127 reply_outbuf(req, 10, 0);
3130 #if defined(HAVE_POSIX_ACLS)
3131 /****************************************************************************
3132 Utility function to count the number of entries in a POSIX acl.
3133 ****************************************************************************/
3135 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3137 unsigned int ace_count = 0;
3138 int entry_id = SMB_ACL_FIRST_ENTRY;
3139 SMB_ACL_ENTRY_T entry;
3141 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3143 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3144 entry_id = SMB_ACL_NEXT_ENTRY;
3151 /****************************************************************************
3152 Utility function to marshall a POSIX acl into wire format.
3153 ****************************************************************************/
3155 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3157 int entry_id = SMB_ACL_FIRST_ENTRY;
3158 SMB_ACL_ENTRY_T entry;
3160 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3161 SMB_ACL_TAG_T tagtype;
3162 SMB_ACL_PERMSET_T permset;
3163 unsigned char perms = 0;
3164 unsigned int own_grp;
3167 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3168 entry_id = SMB_ACL_NEXT_ENTRY;
3171 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3172 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3176 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3177 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3181 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3182 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3183 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3185 SCVAL(pdata,1,perms);
3188 case SMB_ACL_USER_OBJ:
3189 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3190 own_grp = (unsigned int)pst->st_uid;
3191 SIVAL(pdata,2,own_grp);
3196 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3198 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3201 own_grp = (unsigned int)*puid;
3202 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3203 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3204 SIVAL(pdata,2,own_grp);
3208 case SMB_ACL_GROUP_OBJ:
3209 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3210 own_grp = (unsigned int)pst->st_gid;
3211 SIVAL(pdata,2,own_grp);
3216 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3218 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3221 own_grp = (unsigned int)*pgid;
3222 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3223 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3224 SIVAL(pdata,2,own_grp);
3229 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3230 SIVAL(pdata,2,0xFFFFFFFF);
3231 SIVAL(pdata,6,0xFFFFFFFF);
3234 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3235 SIVAL(pdata,2,0xFFFFFFFF);
3236 SIVAL(pdata,6,0xFFFFFFFF);
3239 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3242 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3249 /****************************************************************************
3250 Store the FILE_UNIX_BASIC info.
3251 ****************************************************************************/
3253 static char *store_file_unix_basic(connection_struct *conn,
3256 const SMB_STRUCT_STAT *psbuf)
3258 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3259 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3261 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3264 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3267 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3268 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3269 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3272 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3276 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3280 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3283 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3287 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3291 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3294 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3298 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3305 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3306 * the chflags(2) (or equivalent) flags.
3308 * XXX: this really should be behind the VFS interface. To do this, we would
3309 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3310 * Each VFS module could then implement it's own mapping as appropriate for the
3311 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3313 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3317 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3321 { UF_IMMUTABLE, EXT_IMMUTABLE },
3325 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3329 { UF_HIDDEN, EXT_HIDDEN },
3332 /* Do not remove. We need to guarantee that this array has at least one
3333 * entry to build on HP-UX.
3339 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3340 uint32 *smb_fflags, uint32 *smb_fmask)
3342 #ifdef HAVE_STAT_ST_FLAGS
3345 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3346 *smb_fmask |= info2_flags_map[i].smb_fflag;
3347 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3348 *smb_fflags |= info2_flags_map[i].smb_fflag;
3351 #endif /* HAVE_STAT_ST_FLAGS */
3354 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3355 const uint32 smb_fflags,
3356 const uint32 smb_fmask,
3359 #ifdef HAVE_STAT_ST_FLAGS
3360 uint32 max_fmask = 0;
3363 *stat_fflags = psbuf->st_flags;
3365 /* For each flags requested in smb_fmask, check the state of the
3366 * corresponding flag in smb_fflags and set or clear the matching
3370 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3371 max_fmask |= info2_flags_map[i].smb_fflag;
3372 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3373 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3374 *stat_fflags |= info2_flags_map[i].stat_fflag;
3376 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3381 /* If smb_fmask is asking to set any bits that are not supported by
3382 * our flag mappings, we should fail.
3384 if ((smb_fmask & max_fmask) != smb_fmask) {
3391 #endif /* HAVE_STAT_ST_FLAGS */
3395 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3396 * of file flags and birth (create) time.
3398 static char *store_file_unix_basic_info2(connection_struct *conn,
3401 const SMB_STRUCT_STAT *psbuf)
3403 uint32 file_flags = 0;
3404 uint32 flags_mask = 0;
3406 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3408 /* Create (birth) time 64 bit */
3409 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3412 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3413 SIVAL(pdata, 0, file_flags); /* flags */
3414 SIVAL(pdata, 4, flags_mask); /* mask */
3420 /****************************************************************************
3421 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3422 ****************************************************************************/
3424 static void call_trans2qpipeinfo(connection_struct *conn,
3425 struct smb_request *req,
3426 unsigned int tran_call,
3427 char **pparams, int total_params,
3428 char **ppdata, int total_data,
3429 unsigned int max_data_bytes)
3431 char *params = *pparams;
3432 char *pdata = *ppdata;
3433 unsigned int data_size = 0;
3434 unsigned int param_size = 2;
3436 smb_np_struct *p_pipe = NULL;
3439 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3443 if (total_params < 4) {
3444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3448 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3449 if (p_pipe == NULL) {
3450 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3454 info_level = SVAL(params,2);
3456 *pparams = (char *)SMB_REALLOC(*pparams,2);
3457 if (*pparams == NULL) {
3458 reply_nterror(req, NT_STATUS_NO_MEMORY);
3463 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3464 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3465 if (*ppdata == NULL ) {
3466 reply_nterror(req, NT_STATUS_NO_MEMORY);
3471 switch (info_level) {
3472 case SMB_FILE_STANDARD_INFORMATION:
3474 SOFF_T(pdata,0,4096LL);
3481 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3485 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3491 /****************************************************************************
3492 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3493 file name or file id).
3494 ****************************************************************************/
3496 static void call_trans2qfilepathinfo(connection_struct *conn,
3497 struct smb_request *req,
3498 unsigned int tran_call,
3499 char **pparams, int total_params,
3500 char **ppdata, int total_data,
3501 unsigned int max_data_bytes)
3503 char *params = *pparams;
3504 char *pdata = *ppdata;
3505 char *dstart, *dend;
3509 SMB_OFF_T file_size=0;
3510 SMB_BIG_UINT allocation_size=0;
3511 unsigned int data_size = 0;
3512 unsigned int param_size = 2;
3513 SMB_STRUCT_STAT sbuf;
3520 BOOL delete_pending = False;
3522 time_t create_time, mtime, atime;
3523 struct timespec create_time_ts, mtime_ts, atime_ts;
3524 files_struct *fsp = NULL;
3525 struct file_id fileid;
3526 TALLOC_CTX *data_ctx = NULL;
3527 struct ea_list *ea_list = NULL;
3528 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3529 char *lock_data = NULL;
3530 TALLOC_CTX *ctx = NULL;
3533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3539 if (tran_call == TRANSACT2_QFILEINFO) {
3540 if (total_params < 4) {
3541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3546 call_trans2qpipeinfo(conn, req, tran_call,
3547 pparams, total_params,
3553 fsp = file_fsp(SVAL(params,0));
3554 info_level = SVAL(params,2);
3556 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3558 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3559 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3563 /* Initial check for valid fsp ptr. */
3564 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3568 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3570 reply_nterror(req, NT_STATUS_NO_MEMORY);
3574 if(fsp->fake_file_handle) {
3576 * This is actually for the QUOTA_FAKE_FILE --metze
3579 /* We know this name is ok, it's already passed the checks. */
3581 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3583 * This is actually a QFILEINFO on a directory
3584 * handle (returned from an NT SMB). NT5.0 seems
3585 * to do this call. JRA.
3588 if (INFO_LEVEL_IS_UNIX(info_level)) {
3589 /* Always do lstat for UNIX calls. */
3590 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3591 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3592 reply_unixerror(req,ERRDOS,ERRbadpath);
3595 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3596 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3597 reply_unixerror(req, ERRDOS, ERRbadpath);
3601 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3602 delete_pending = get_delete_on_close_flag(fileid);
3605 * Original code - this is an open file.
3607 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3611 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3612 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3613 reply_unixerror(req, ERRDOS, ERRbadfid);
3616 pos = fsp->fh->position_information;
3617 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3618 delete_pending = get_delete_on_close_flag(fileid);
3619 access_mask = fsp->access_mask;
3624 NTSTATUS status = NT_STATUS_OK;
3627 if (total_params < 7) {
3628 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3632 info_level = SVAL(params,0);
3634 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3636 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3637 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3641 srvstr_get_path(params, req->flags2, fname_in, ¶ms[6],
3642 sizeof(fname_in), total_params - 6,
3643 STR_TERMINATE, &status);
3644 if (!NT_STATUS_IS_OK(status)) {
3645 reply_nterror(req, status);
3649 status = resolve_dfspath(ctx,
3651 req->flags2 & FLAGS2_DFS_PATHNAMES,
3654 if (!NT_STATUS_IS_OK(status)) {
3655 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3656 reply_botherror(req,
3657 NT_STATUS_PATH_NOT_COVERED,
3658 ERRSRV, ERRbadpath);
3660 reply_nterror(req, status);
3664 status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
3665 if (!NT_STATUS_IS_OK(status)) {
3666 reply_nterror(req, status);
3669 status = check_name(conn, fname);
3670 if (!NT_STATUS_IS_OK(status)) {
3671 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3672 reply_nterror(req, status);
3676 if (INFO_LEVEL_IS_UNIX(info_level)) {
3677 /* Always do lstat for UNIX calls. */
3678 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3679 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3680 reply_unixerror(req, ERRDOS, ERRbadpath);
3683 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3684 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3685 reply_unixerror(req, ERRDOS, ERRbadpath);
3689 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3690 delete_pending = get_delete_on_close_flag(fileid);
3691 if (delete_pending) {
3692 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3697 nlink = sbuf.st_nlink;
3699 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3700 /* NTFS does not seem to count ".." */
3704 if ((nlink > 0) && delete_pending) {
3708 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3709 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3713 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3714 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3716 p = strrchr_m(fname,'/');
3722 mode = dos_mode(conn,fname,&sbuf);
3724 mode = FILE_ATTRIBUTE_NORMAL;
3726 fullpathname = fname;
3728 file_size = get_file_size(sbuf);
3730 /* Pull out any data sent here before we realloc. */
3731 switch (info_level) {
3732 case SMB_INFO_QUERY_EAS_FROM_LIST:
3734 /* Pull any EA list from the data portion. */
3737 if (total_data < 4) {
3739 req, NT_STATUS_INVALID_PARAMETER);
3742 ea_size = IVAL(pdata,0);
3744 if (total_data > 0 && ea_size != total_data) {
3745 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3746 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3748 req, NT_STATUS_INVALID_PARAMETER);
3752 if (!lp_ea_support(SNUM(conn))) {
3753 reply_doserror(req, ERRDOS,
3754 ERReasnotsupported);
3758 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3759 reply_nterror(req, NT_STATUS_NO_MEMORY);
3763 /* Pull out the list of names. */
3764 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3766 talloc_destroy(data_ctx);
3768 req, NT_STATUS_INVALID_PARAMETER);
3774 case SMB_QUERY_POSIX_LOCK:
3776 if (fsp == NULL || fsp->fh->fd == -1) {
3777 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3781 if (total_data != POSIX_LOCK_DATA_SIZE) {
3783 req, NT_STATUS_INVALID_PARAMETER);
3787 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3788 reply_nterror(req, NT_STATUS_NO_MEMORY);
3792 /* Copy the lock range data. */
3793 lock_data = (char *)TALLOC_MEMDUP(
3794 data_ctx, pdata, total_data);
3796 talloc_destroy(data_ctx);
3797 reply_nterror(req, NT_STATUS_NO_MEMORY);
3805 *pparams = (char *)SMB_REALLOC(*pparams,2);
3806 if (*pparams == NULL) {
3807 talloc_destroy(data_ctx);
3808 reply_nterror(req, NT_STATUS_NO_MEMORY);
3813 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3814 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3815 if (*ppdata == NULL ) {
3816 talloc_destroy(data_ctx);
3817 reply_nterror(req, NT_STATUS_NO_MEMORY);
3822 dend = dstart + data_size - 1;
3824 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3825 mtime_ts = get_mtimespec(&sbuf);
3826 atime_ts = get_atimespec(&sbuf);
3828 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3831 if (!null_timespec(fsp->pending_modtime)) {
3832 /* the pending modtime overrides the current modtime */
3833 mtime_ts = fsp->pending_modtime;
3837 /* Do we have this path open ? */
3838 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3839 fsp1 = file_find_di_first(fileid);
3840 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3841 /* the pending modtime overrides the current modtime */
3842 mtime_ts = fsp1->pending_modtime;
3844 if (fsp1 && fsp1->initial_allocation_size) {
3845 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3849 if (lp_dos_filetime_resolution(SNUM(conn))) {
3850 dos_filetime_timespec(&create_time_ts);
3851 dos_filetime_timespec(&mtime_ts);
3852 dos_filetime_timespec(&atime_ts);
3855 create_time = convert_timespec_to_time_t(create_time_ts);
3856 mtime = convert_timespec_to_time_t(mtime_ts);
3857 atime = convert_timespec_to_time_t(atime_ts);
3859 /* NT expects the name to be in an exact form of the *full*
3860 filename. See the trans2 torture test */
3861 if (strequal(base_name,".")) {
3862 pstrcpy(dos_fname, "\\");
3864 pstr_sprintf(dos_fname, "\\%s", fname);
3865 string_replace(dos_fname, '/', '\\');
3868 switch (info_level) {
3869 case SMB_INFO_STANDARD:
3870 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3872 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3873 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3874 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3875 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3876 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3877 SSVAL(pdata,l1_attrFile,mode);
3880 case SMB_INFO_QUERY_EA_SIZE:
3882 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3883 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3885 srv_put_dos_date2(pdata,0,create_time);
3886 srv_put_dos_date2(pdata,4,atime);
3887 srv_put_dos_date2(pdata,8,mtime); /* write time */
3888 SIVAL(pdata,12,(uint32)file_size);
3889 SIVAL(pdata,16,(uint32)allocation_size);
3890 SSVAL(pdata,20,mode);
3891 SIVAL(pdata,22,ea_size);
3895 case SMB_INFO_IS_NAME_VALID:
3896 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3897 if (tran_call == TRANSACT2_QFILEINFO) {
3898 /* os/2 needs this ? really ?*/
3899 reply_doserror(req, ERRDOS, ERRbadfunc);
3906 case SMB_INFO_QUERY_EAS_FROM_LIST:
3908 size_t total_ea_len = 0;
3909 struct ea_list *ea_file_list = NULL;
3911 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3913 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3914 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3916 if (!ea_list || (total_ea_len > data_size)) {
3917 talloc_destroy(data_ctx);
3919 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3923 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3924 talloc_destroy(data_ctx);
3928 case SMB_INFO_QUERY_ALL_EAS:
3930 /* We have data_size bytes to put EA's into. */
3931 size_t total_ea_len = 0;
3933 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3935 data_ctx = talloc_init("ea_ctx");
3937 reply_nterror(req, NT_STATUS_NO_MEMORY);
3941 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3942 if (!ea_list || (total_ea_len > data_size)) {
3943 talloc_destroy(data_ctx);
3945 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3949 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3950 talloc_destroy(data_ctx);
3954 case SMB_FILE_BASIC_INFORMATION:
3955 case SMB_QUERY_FILE_BASIC_INFO:
3957 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3958 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3959 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3961 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3965 put_long_date_timespec(pdata,create_time_ts);
3966 put_long_date_timespec(pdata+8,atime_ts);
3967 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3968 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3969 SIVAL(pdata,32,mode);
3971 DEBUG(5,("SMB_QFBI - "));
3972 DEBUG(5,("create: %s ", ctime(&create_time)));
3973 DEBUG(5,("access: %s ", ctime(&atime)));
3974 DEBUG(5,("write: %s ", ctime(&mtime)));
3975 DEBUG(5,("change: %s ", ctime(&mtime)));
3976 DEBUG(5,("mode: %x\n", mode));
3979 case SMB_FILE_STANDARD_INFORMATION:
3980 case SMB_QUERY_FILE_STANDARD_INFO:
3982 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3984 SOFF_T(pdata,0,allocation_size);
3985 SOFF_T(pdata,8,file_size);
3986 SIVAL(pdata,16,nlink);
3987 SCVAL(pdata,20,delete_pending?1:0);
3988 SCVAL(pdata,21,(mode&aDIR)?1:0);
3989 SSVAL(pdata,22,0); /* Padding. */
3992 case SMB_FILE_EA_INFORMATION:
3993 case SMB_QUERY_FILE_EA_INFO:
3995 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3996 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3998 SIVAL(pdata,0,ea_size);
4002 /* Get the 8.3 name - used if NT SMB was negotiated. */
4003 case SMB_QUERY_FILE_ALT_NAME_INFO:
4004 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4006 char mangled_name[13];
4007 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4008 if (!name_to_8_3(base_name,mangled_name,
4009 True,conn->params)) {
4012 NT_STATUS_NO_MEMORY);
4014 len = srvstr_push(dstart, req->flags2,
4015 pdata+4, mangled_name,
4016 PTR_DIFF(dend, pdata+4),
4018 data_size = 4 + len;
4023 case SMB_QUERY_FILE_NAME_INFO:
4025 this must be *exactly* right for ACLs on mapped drives to work
4027 len = srvstr_push(dstart, req->flags2,
4029 PTR_DIFF(dend, pdata+4),
4031 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4032 data_size = 4 + len;
4036 case SMB_FILE_ALLOCATION_INFORMATION:
4037 case SMB_QUERY_FILE_ALLOCATION_INFO:
4038 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4040 SOFF_T(pdata,0,allocation_size);
4043 case SMB_FILE_END_OF_FILE_INFORMATION:
4044 case SMB_QUERY_FILE_END_OF_FILEINFO:
4045 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4047 SOFF_T(pdata,0,file_size);
4050 case SMB_QUERY_FILE_ALL_INFO:
4051 case SMB_FILE_ALL_INFORMATION:
4053 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4054 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4055 put_long_date_timespec(pdata,create_time_ts);
4056 put_long_date_timespec(pdata+8,atime_ts);
4057 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4058 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4059 SIVAL(pdata,32,mode);
4060 SIVAL(pdata,36,0); /* padding. */
4062 SOFF_T(pdata,0,allocation_size);
4063 SOFF_T(pdata,8,file_size);
4064 SIVAL(pdata,16,nlink);
4065 SCVAL(pdata,20,delete_pending);
4066 SCVAL(pdata,21,(mode&aDIR)?1:0);
4069 SIVAL(pdata,0,ea_size);
4070 pdata += 4; /* EA info */
4071 len = srvstr_push(dstart, req->flags2,
4073 PTR_DIFF(dend, pdata+4),
4077 data_size = PTR_DIFF(pdata,(*ppdata));
4080 case SMB_FILE_INTERNAL_INFORMATION:
4081 /* This should be an index number - looks like
4084 I think this causes us to fail the IFSKIT
4085 BasicFileInformationTest. -tpot */
4087 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4088 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4089 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4093 case SMB_FILE_ACCESS_INFORMATION:
4094 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4095 SIVAL(pdata,0,access_mask);
4099 case SMB_FILE_NAME_INFORMATION:
4100 /* Pathname with leading '\'. */
4103 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4104 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4105 SIVAL(pdata,0,byte_len);
4106 data_size = 4 + byte_len;
4110 case SMB_FILE_DISPOSITION_INFORMATION:
4111 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4113 SCVAL(pdata,0,delete_pending);
4116 case SMB_FILE_POSITION_INFORMATION:
4117 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4119 SOFF_T(pdata,0,pos);
4122 case SMB_FILE_MODE_INFORMATION:
4123 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4124 SIVAL(pdata,0,mode);
4128 case SMB_FILE_ALIGNMENT_INFORMATION:
4129 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4130 SIVAL(pdata,0,0); /* No alignment needed. */
4136 * NT4 server just returns "invalid query" to this - if we try to answer
4137 * it then NTws gets a BSOD! (tridge).
4138 * W2K seems to want this. JRA.
4140 case SMB_QUERY_FILE_STREAM_INFO:
4142 case SMB_FILE_STREAM_INFORMATION:
4143 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4147 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4148 SIVAL(pdata,0,0); /* ??? */
4149 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4150 SOFF_T(pdata,8,file_size);
4151 SOFF_T(pdata,16,allocation_size);
4152 data_size = 24 + byte_len;
4156 case SMB_QUERY_COMPRESSION_INFO:
4157 case SMB_FILE_COMPRESSION_INFORMATION:
4158 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4159 SOFF_T(pdata,0,file_size);
4160 SIVAL(pdata,8,0); /* ??? */
4161 SIVAL(pdata,12,0); /* ??? */
4165 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4166 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4167 put_long_date_timespec(pdata,create_time_ts);
4168 put_long_date_timespec(pdata+8,atime_ts);
4169 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4170 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4171 SOFF_T(pdata,32,allocation_size);
4172 SOFF_T(pdata,40,file_size);
4173 SIVAL(pdata,48,mode);
4174 SIVAL(pdata,52,0); /* ??? */
4178 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4179 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4180 SIVAL(pdata,0,mode);
4186 * CIFS UNIX Extensions.
4189 case SMB_QUERY_FILE_UNIX_BASIC:
4191 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4192 data_size = PTR_DIFF(pdata,(*ppdata));
4196 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4198 for (i=0; i<100; i++)
4199 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4205 case SMB_QUERY_FILE_UNIX_INFO2:
4207 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4208 data_size = PTR_DIFF(pdata,(*ppdata));
4212 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4214 for (i=0; i<100; i++)
4215 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4221 case SMB_QUERY_FILE_UNIX_LINK:
4225 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4227 if(!S_ISLNK(sbuf.st_mode)) {
4228 reply_unixerror(req, ERRSRV,
4233 reply_unixerror(req, ERRDOS, ERRbadlink);
4236 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
4238 reply_unixerror(req, ERRDOS,
4243 len = srvstr_push(dstart, req->flags2,
4245 PTR_DIFF(dend, pdata),
4248 data_size = PTR_DIFF(pdata,(*ppdata));
4253 #if defined(HAVE_POSIX_ACLS)
4254 case SMB_QUERY_POSIX_ACL:
4256 SMB_ACL_T file_acl = NULL;
4257 SMB_ACL_T def_acl = NULL;
4258 uint16 num_file_acls = 0;
4259 uint16 num_def_acls = 0;
4261 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4262 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4264 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4267 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4268 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4272 NT_STATUS_NOT_IMPLEMENTED);
4276 if (S_ISDIR(sbuf.st_mode)) {
4277 if (fsp && fsp->is_directory) {
4278 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4280 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4282 def_acl = free_empty_sys_acl(conn, def_acl);
4285 num_file_acls = count_acl_entries(conn, file_acl);
4286 num_def_acls = count_acl_entries(conn, def_acl);
4288 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4289 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4291 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4292 SMB_POSIX_ACL_HEADER_SIZE) ));
4294 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4297 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4301 NT_STATUS_BUFFER_TOO_SMALL);
4305 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4306 SSVAL(pdata,2,num_file_acls);
4307 SSVAL(pdata,4,num_def_acls);
4308 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4310 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4313 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4316 req, NT_STATUS_INTERNAL_ERROR);
4319 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4321 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4324 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4328 NT_STATUS_INTERNAL_ERROR);
4333 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4336 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4338 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4344 case SMB_QUERY_POSIX_LOCK:
4346 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4348 SMB_BIG_UINT offset;
4350 enum brl_type lock_type;
4352 if (total_data != POSIX_LOCK_DATA_SIZE) {
4354 req, NT_STATUS_INVALID_PARAMETER);
4358 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4359 case POSIX_LOCK_TYPE_READ:
4360 lock_type = READ_LOCK;
4362 case POSIX_LOCK_TYPE_WRITE:
4363 lock_type = WRITE_LOCK;
4365 case POSIX_LOCK_TYPE_UNLOCK:
4367 /* There's no point in asking for an unlock... */
4368 talloc_destroy(data_ctx);
4371 NT_STATUS_INVALID_PARAMETER);
4375 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4376 #if defined(HAVE_LONGLONG)
4377 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4378 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4379 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4380 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4381 #else /* HAVE_LONGLONG */
4382 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4383 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4384 #endif /* HAVE_LONGLONG */
4386 status = query_lock(fsp,
4393 if (ERROR_WAS_LOCK_DENIED(status)) {
4394 /* Here we need to report who has it locked... */
4395 data_size = POSIX_LOCK_DATA_SIZE;
4397 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4398 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4399 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4400 #if defined(HAVE_LONGLONG)
4401 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4402 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4403 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4404 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4405 #else /* HAVE_LONGLONG */
4406 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4407 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4408 #endif /* HAVE_LONGLONG */
4410 } else if (NT_STATUS_IS_OK(status)) {
4411 /* For success we just return a copy of what we sent
4412 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4413 data_size = POSIX_LOCK_DATA_SIZE;
4414 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4415 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4417 reply_nterror(req, status);
4424 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4428 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4434 /****************************************************************************
4435 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4437 ****************************************************************************/
4439 NTSTATUS hardlink_internals(connection_struct *conn,
4440 const char *oldname_in,
4441 const char *newname_in)
4443 SMB_STRUCT_STAT sbuf1, sbuf2;
4444 char *last_component_oldname = NULL;
4445 char *last_component_newname = NULL;
4446 char *oldname = NULL;
4447 char *newname = NULL;
4448 NTSTATUS status = NT_STATUS_OK;
4453 status = unix_convert(conn, oldname_in, False, &oldname,
4454 &last_component_oldname, &sbuf1);
4455 if (!NT_STATUS_IS_OK(status)) {
4459 status = check_name(conn, oldname);
4460 if (!NT_STATUS_IS_OK(status)) {
4464 /* source must already exist. */
4465 if (!VALID_STAT(sbuf1)) {
4466 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4469 status = unix_convert(conn, newname_in, False, &newname,
4470 &last_component_newname, &sbuf2);
4471 if (!NT_STATUS_IS_OK(status)) {
4475 status = check_name(conn, newname);
4476 if (!NT_STATUS_IS_OK(status)) {
4480 /* Disallow if newname already exists. */
4481 if (VALID_STAT(sbuf2)) {
4482 return NT_STATUS_OBJECT_NAME_COLLISION;
4485 /* No links from a directory. */
4486 if (S_ISDIR(sbuf1.st_mode)) {
4487 return NT_STATUS_FILE_IS_A_DIRECTORY;
4490 /* Ensure this is within the share. */
4491 status = check_reduced_name(conn, oldname);
4492 if (!NT_STATUS_IS_OK(status)) {
4496 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4498 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4499 status = map_nt_error_from_unix(errno);
4500 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4501 nt_errstr(status), newname, oldname));
4507 /****************************************************************************
4508 Deal with setting the time from any of the setfilepathinfo functions.
4509 ****************************************************************************/
4511 static NTSTATUS smb_set_file_time(connection_struct *conn,
4514 const SMB_STRUCT_STAT *psbuf,
4515 struct timespec ts[2])
4518 FILE_NOTIFY_CHANGE_LAST_ACCESS
4519 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4522 if (!VALID_STAT(*psbuf)) {
4523 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4526 /* get some defaults (no modifications) if any info is zero or -1. */
4527 if (null_timespec(ts[0])) {
4528 ts[0] = get_atimespec(psbuf);
4529 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4532 if (null_timespec(ts[1])) {
4533 ts[1] = get_mtimespec(psbuf);
4534 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4537 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4538 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4541 * Try and set the times of this file if
4542 * they are different from the current values.
4546 struct timespec mts = get_mtimespec(psbuf);
4547 struct timespec ats = get_atimespec(psbuf);
4548 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4549 return NT_STATUS_OK;
4555 * This was a setfileinfo on an open file.
4556 * NT does this a lot. We also need to
4557 * set the time here, as it can be read by
4558 * FindFirst/FindNext and with the patch for bug #2045
4559 * in smbd/fileio.c it ensures that this timestamp is
4560 * kept sticky even after a write. We save the request
4561 * away and will set it on file close and after a write. JRA.
4564 if (!null_timespec(ts[1])) {
4565 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4566 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4567 fsp_set_pending_modtime(fsp, ts[1]);
4571 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4573 if(file_ntimes(conn, fname, ts)!=0) {
4574 return map_nt_error_from_unix(errno);
4577 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4579 return NT_STATUS_OK;
4582 /****************************************************************************
4583 Deal with setting the dosmode from any of the setfilepathinfo functions.
4584 ****************************************************************************/
4586 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4588 SMB_STRUCT_STAT *psbuf,
4591 if (!VALID_STAT(*psbuf)) {
4592 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4596 if (S_ISDIR(psbuf->st_mode)) {
4603 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4605 /* check the mode isn't different, before changing it */
4606 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4608 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4609 fname, (unsigned int)dosmode ));
4611 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4612 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4613 fname, strerror(errno)));
4614 return map_nt_error_from_unix(errno);
4617 return NT_STATUS_OK;
4620 /****************************************************************************
4621 Deal with setting the size from any of the setfilepathinfo functions.
4622 ****************************************************************************/
4624 static NTSTATUS smb_set_file_size(connection_struct *conn,
4625 struct smb_request *req,
4628 SMB_STRUCT_STAT *psbuf,
4631 NTSTATUS status = NT_STATUS_OK;
4632 files_struct *new_fsp = NULL;
4634 if (!VALID_STAT(*psbuf)) {
4635 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4638 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4640 if (size == get_file_size(*psbuf)) {
4641 return NT_STATUS_OK;
4644 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4645 fname, (double)size ));
4647 if (fsp && fsp->fh->fd != -1) {
4648 /* Handle based call. */
4649 if (vfs_set_filelen(fsp, size) == -1) {
4650 return map_nt_error_from_unix(errno);
4652 return NT_STATUS_OK;
4655 status = open_file_ntcreate(conn, req, fname, psbuf,
4657 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4660 FILE_ATTRIBUTE_NORMAL,
4661 FORCE_OPLOCK_BREAK_TO_NONE,
4664 if (!NT_STATUS_IS_OK(status)) {
4665 /* NB. We check for open_was_deferred in the caller. */
4669 if (vfs_set_filelen(new_fsp, size) == -1) {
4670 status = map_nt_error_from_unix(errno);
4671 close_file(new_fsp,NORMAL_CLOSE);
4675 close_file(new_fsp,NORMAL_CLOSE);
4676 return NT_STATUS_OK;
4679 /****************************************************************************
4680 Deal with SMB_INFO_SET_EA.
4681 ****************************************************************************/
4683 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4689 struct ea_list *ea_list = NULL;
4690 TALLOC_CTX *ctx = NULL;
4691 NTSTATUS status = NT_STATUS_OK;
4693 if (total_data < 10) {
4695 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4696 length. They seem to have no effect. Bug #3212. JRA */
4698 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4699 /* We're done. We only get EA info in this call. */
4700 return NT_STATUS_OK;
4703 return NT_STATUS_INVALID_PARAMETER;
4706 if (IVAL(pdata,0) > total_data) {
4707 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4708 IVAL(pdata,0), (unsigned int)total_data));
4709 return NT_STATUS_INVALID_PARAMETER;
4712 ctx = talloc_init("SMB_INFO_SET_EA");
4714 return NT_STATUS_NO_MEMORY;
4716 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4718 talloc_destroy(ctx);
4719 return NT_STATUS_INVALID_PARAMETER;
4721 status = set_ea(conn, fsp, fname, ea_list);
4722 talloc_destroy(ctx);
4727 /****************************************************************************
4728 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4729 ****************************************************************************/
4731 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4736 SMB_STRUCT_STAT *psbuf)
4738 NTSTATUS status = NT_STATUS_OK;
4739 BOOL delete_on_close;
4742 if (total_data < 1) {
4743 return NT_STATUS_INVALID_PARAMETER;
4747 return NT_STATUS_INVALID_HANDLE;
4750 delete_on_close = (CVAL(pdata,0) ? True : False);
4751 dosmode = dos_mode(conn, fname, psbuf);
4753 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4754 "delete_on_close = %u\n",
4756 (unsigned int)dosmode,
4757 (unsigned int)delete_on_close ));
4759 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4761 if (!NT_STATUS_IS_OK(status)) {
4765 /* The set is across all open files on this dev/inode pair. */
4766 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4767 return NT_STATUS_ACCESS_DENIED;
4769 return NT_STATUS_OK;
4772 /****************************************************************************
4773 Deal with SMB_FILE_POSITION_INFORMATION.
4774 ****************************************************************************/
4776 static NTSTATUS smb_file_position_information(connection_struct *conn,
4781 SMB_BIG_UINT position_information;
4783 if (total_data < 8) {
4784 return NT_STATUS_INVALID_PARAMETER;
4788 /* Ignore on pathname based set. */
4789 return NT_STATUS_OK;
4792 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4793 #ifdef LARGE_SMB_OFF_T
4794 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4795 #else /* LARGE_SMB_OFF_T */
4796 if (IVAL(pdata,4) != 0) {
4797 /* more than 32 bits? */
4798 return NT_STATUS_INVALID_PARAMETER;
4800 #endif /* LARGE_SMB_OFF_T */
4802 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4803 fsp->fsp_name, (double)position_information ));
4804 fsp->fh->position_information = position_information;
4805 return NT_STATUS_OK;
4808 /****************************************************************************
4809 Deal with SMB_FILE_MODE_INFORMATION.
4810 ****************************************************************************/
4812 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4818 if (total_data < 4) {
4819 return NT_STATUS_INVALID_PARAMETER;
4821 mode = IVAL(pdata,0);
4822 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4823 return NT_STATUS_INVALID_PARAMETER;
4825 return NT_STATUS_OK;
4828 /****************************************************************************
4829 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4830 ****************************************************************************/
4832 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4833 struct smb_request *req,
4838 pstring link_target;
4839 const char *newname = fname;
4840 NTSTATUS status = NT_STATUS_OK;
4842 /* Set a symbolic link. */
4843 /* Don't allow this if follow links is false. */
4845 if (total_data == 0) {
4846 return NT_STATUS_INVALID_PARAMETER;
4849 if (!lp_symlinks(SNUM(conn))) {
4850 return NT_STATUS_ACCESS_DENIED;
4853 srvstr_pull(pdata, req->flags2, link_target, pdata,
4854 sizeof(link_target), total_data, STR_TERMINATE);
4856 /* !widelinks forces the target path to be within the share. */
4857 /* This means we can interpret the target as a pathname. */
4858 if (!lp_widelinks(SNUM(conn))) {
4860 char *last_dirp = NULL;
4862 if (*link_target == '/') {
4863 /* No absolute paths allowed. */
4864 return NT_STATUS_ACCESS_DENIED;
4866 pstrcpy(rel_name, newname);
4867 last_dirp = strrchr_m(rel_name, '/');
4869 last_dirp[1] = '\0';
4871 pstrcpy(rel_name, "./");
4873 pstrcat(rel_name, link_target);
4875 status = check_name(conn, rel_name);
4876 if (!NT_STATUS_IS_OK(status)) {
4881 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4882 newname, link_target ));
4884 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4885 return map_nt_error_from_unix(errno);
4888 return NT_STATUS_OK;
4891 /****************************************************************************
4892 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4893 ****************************************************************************/
4895 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4896 struct smb_request *req,
4897 const char *pdata, int total_data,
4901 char *oldname = NULL;
4902 TALLOC_CTX *ctx = talloc_tos();
4903 NTSTATUS status = NT_STATUS_OK;
4905 /* Set a hard link. */
4906 if (total_data == 0) {
4907 return NT_STATUS_INVALID_PARAMETER;
4910 srvstr_get_path(pdata, req->flags2, oldname_in, pdata,
4911 sizeof(oldname_in), total_data, STR_TERMINATE, &status);
4912 if (!NT_STATUS_IS_OK(status)) {
4916 status = resolve_dfspath(ctx, conn,
4917 req->flags2 & FLAGS2_DFS_PATHNAMES,
4920 if (!NT_STATUS_IS_OK(status)) {
4924 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4927 return hardlink_internals(conn, oldname, fname);
4930 /****************************************************************************
4931 Deal with SMB_FILE_RENAME_INFORMATION.
4932 ****************************************************************************/
4934 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4935 struct smb_request *req,
4945 char *newname = NULL;
4947 BOOL dest_has_wcard = False;
4948 NTSTATUS status = NT_STATUS_OK;
4950 TALLOC_CTX *ctx = talloc_tos();
4952 if (total_data < 13) {
4953 return NT_STATUS_INVALID_PARAMETER;
4956 overwrite = (CVAL(pdata,0) ? True : False);
4957 root_fid = IVAL(pdata,4);
4958 len = IVAL(pdata,8);
4960 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4961 return NT_STATUS_INVALID_PARAMETER;
4964 srvstr_get_path_wcard(pdata, req->flags2, newname_in, &pdata[12],
4965 sizeof(newname_in), len, 0, &status,
4967 if (!NT_STATUS_IS_OK(status)) {
4971 status = resolve_dfspath_wcard(ctx, conn,
4972 req->flags2 & FLAGS2_DFS_PATHNAMES,
4976 if (!NT_STATUS_IS_OK(status)) {
4980 /* Check the new name has no '/' characters. */
4981 if (strchr_m(newname, '/')) {
4982 return NT_STATUS_NOT_SUPPORTED;
4985 /* Create the base directory. */
4986 pstrcpy(base_name, fname);
4987 p = strrchr_m(base_name, '/');
4991 pstrcpy(base_name, "./");
4993 /* Append the new name. */
4994 pstrcat(base_name, newname);
4997 SMB_STRUCT_STAT sbuf;
4998 char *newname_last_component = NULL;
5002 status = unix_convert(conn, newname, False,
5004 &newname_last_component,
5007 /* If an error we expect this to be
5008 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5010 if (!NT_STATUS_IS_OK(status)
5011 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5016 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5017 fsp->fnum, fsp->fsp_name, base_name ));
5018 status = rename_internals_fsp(conn, fsp, base_name,
5019 newname_last_component, 0,
5022 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5023 fname, base_name ));
5024 status = rename_internals(conn, req, fname, base_name, 0,
5025 overwrite, False, dest_has_wcard);
5031 /****************************************************************************
5032 Deal with SMB_SET_POSIX_ACL.
5033 ****************************************************************************/
5035 #if defined(HAVE_POSIX_ACLS)
5036 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5041 SMB_STRUCT_STAT *psbuf)
5043 uint16 posix_acl_version;
5044 uint16 num_file_acls;
5045 uint16 num_def_acls;
5046 BOOL valid_file_acls = True;
5047 BOOL valid_def_acls = True;
5049 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5050 return NT_STATUS_INVALID_PARAMETER;
5052 posix_acl_version = SVAL(pdata,0);
5053 num_file_acls = SVAL(pdata,2);
5054 num_def_acls = SVAL(pdata,4);
5056 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5057 valid_file_acls = False;
5061 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5062 valid_def_acls = False;
5066 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5067 return NT_STATUS_INVALID_PARAMETER;
5070 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5071 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5072 return NT_STATUS_INVALID_PARAMETER;
5075 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5076 fname ? fname : fsp->fsp_name,
5077 (unsigned int)num_file_acls,
5078 (unsigned int)num_def_acls));
5080 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5081 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5082 return map_nt_error_from_unix(errno);
5085 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5086 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5087 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5088 return map_nt_error_from_unix(errno);
5090 return NT_STATUS_OK;
5094 /****************************************************************************
5095 Deal with SMB_SET_POSIX_LOCK.
5096 ****************************************************************************/
5098 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5106 SMB_BIG_UINT offset;
5108 BOOL blocking_lock = False;
5109 enum brl_type lock_type;
5110 NTSTATUS status = NT_STATUS_OK;
5112 if (fsp == NULL || fsp->fh->fd == -1) {
5113 return NT_STATUS_INVALID_HANDLE;
5116 if (total_data != POSIX_LOCK_DATA_SIZE) {
5117 return NT_STATUS_INVALID_PARAMETER;
5120 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5121 case POSIX_LOCK_TYPE_READ:
5122 lock_type = READ_LOCK;
5124 case POSIX_LOCK_TYPE_WRITE:
5125 /* Return the right POSIX-mappable error code for files opened read-only. */
5126 if (!fsp->can_write) {
5127 return NT_STATUS_INVALID_HANDLE;
5129 lock_type = WRITE_LOCK;
5131 case POSIX_LOCK_TYPE_UNLOCK:
5132 lock_type = UNLOCK_LOCK;
5135 return NT_STATUS_INVALID_PARAMETER;
5138 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5139 blocking_lock = False;
5140 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5141 blocking_lock = True;
5143 return NT_STATUS_INVALID_PARAMETER;
5146 if (!lp_blocking_locks(SNUM(conn))) {
5147 blocking_lock = False;
5150 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5151 #if defined(HAVE_LONGLONG)
5152 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5153 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5154 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5155 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5156 #else /* HAVE_LONGLONG */
5157 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5158 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5159 #endif /* HAVE_LONGLONG */
5161 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5162 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5164 (unsigned int)lock_type,
5165 (unsigned int)lock_pid,
5169 if (lock_type == UNLOCK_LOCK) {
5170 status = do_unlock(smbd_messaging_context(),
5177 uint32 block_smbpid;
5179 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5190 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5192 * A blocking lock was requested. Package up
5193 * this smb into a queued request and push it
5194 * onto the blocking lock queue.
5196 if(push_blocking_lock_request(br_lck,
5197 (char *)inbuf, length,
5199 -1, /* infinite timeout. */
5207 TALLOC_FREE(br_lck);
5211 TALLOC_FREE(br_lck);
5217 /****************************************************************************
5218 Deal with SMB_INFO_STANDARD.
5219 ****************************************************************************/
5221 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5226 const SMB_STRUCT_STAT *psbuf)
5228 struct timespec ts[2];
5230 if (total_data < 12) {
5231 return NT_STATUS_INVALID_PARAMETER;
5235 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5237 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5239 DEBUG(10,("smb_set_info_standard: file %s\n",
5240 fname ? fname : fsp->fsp_name ));
5242 return smb_set_file_time(conn,
5249 /****************************************************************************
5250 Deal with SMB_SET_FILE_BASIC_INFO.
5251 ****************************************************************************/
5253 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5258 SMB_STRUCT_STAT *psbuf)
5260 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5261 struct timespec write_time;
5262 struct timespec changed_time;
5264 struct timespec ts[2];
5265 NTSTATUS status = NT_STATUS_OK;
5267 if (total_data < 36) {
5268 return NT_STATUS_INVALID_PARAMETER;
5271 /* Set the attributes */
5272 dosmode = IVAL(pdata,32);
5273 status = smb_set_file_dosmode(conn,
5277 if (!NT_STATUS_IS_OK(status)) {
5281 /* Ignore create time at offset pdata. */
5284 ts[0] = interpret_long_date(pdata+8);
5286 write_time = interpret_long_date(pdata+16);
5287 changed_time = interpret_long_date(pdata+24);
5290 ts[1] = timespec_min(&write_time, &changed_time);
5292 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5296 /* Prefer a defined time to an undefined one. */
5297 if (null_timespec(ts[1])) {
5298 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5301 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5302 fname ? fname : fsp->fsp_name ));
5304 return smb_set_file_time(conn,
5311 /****************************************************************************
5312 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5313 ****************************************************************************/
5315 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5316 struct smb_request *req,
5321 SMB_STRUCT_STAT *psbuf)
5323 SMB_BIG_UINT allocation_size = 0;
5324 NTSTATUS status = NT_STATUS_OK;
5325 files_struct *new_fsp = NULL;
5327 if (!VALID_STAT(*psbuf)) {
5328 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5331 if (total_data < 8) {
5332 return NT_STATUS_INVALID_PARAMETER;
5335 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5336 #ifdef LARGE_SMB_OFF_T
5337 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5338 #else /* LARGE_SMB_OFF_T */
5339 if (IVAL(pdata,4) != 0) {
5340 /* more than 32 bits? */
5341 return NT_STATUS_INVALID_PARAMETER;
5343 #endif /* LARGE_SMB_OFF_T */
5345 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5346 fname, (double)allocation_size ));
5348 if (allocation_size) {
5349 allocation_size = smb_roundup(conn, allocation_size);
5352 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5353 fname, (double)allocation_size ));
5355 if (fsp && fsp->fh->fd != -1) {
5356 /* Open file handle. */
5357 /* Only change if needed. */
5358 if (allocation_size != get_file_size(*psbuf)) {
5359 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5360 return map_nt_error_from_unix(errno);
5363 /* But always update the time. */
5364 if (null_timespec(fsp->pending_modtime)) {
5366 * This is equivalent to a write. Ensure it's seen immediately
5367 * if there are no pending writes.
5369 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5371 return NT_STATUS_OK;
5374 /* Pathname or stat or directory file. */
5376 status = open_file_ntcreate(conn, req, fname, psbuf,
5378 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5381 FILE_ATTRIBUTE_NORMAL,
5382 FORCE_OPLOCK_BREAK_TO_NONE,
5385 if (!NT_STATUS_IS_OK(status)) {
5386 /* NB. We check for open_was_deferred in the caller. */
5390 /* Only change if needed. */
5391 if (allocation_size != get_file_size(*psbuf)) {
5392 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5393 status = map_nt_error_from_unix(errno);
5394 close_file(new_fsp,NORMAL_CLOSE);
5399 /* Changing the allocation size should set the last mod time. */
5400 /* Don't need to call set_filetime as this will be flushed on
5403 fsp_set_pending_modtime(new_fsp, timespec_current());
5405 close_file(new_fsp,NORMAL_CLOSE);
5406 return NT_STATUS_OK;
5409 /****************************************************************************
5410 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5411 ****************************************************************************/
5413 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5414 struct smb_request *req,
5419 SMB_STRUCT_STAT *psbuf)
5423 if (total_data < 8) {
5424 return NT_STATUS_INVALID_PARAMETER;
5427 size = IVAL(pdata,0);
5428 #ifdef LARGE_SMB_OFF_T
5429 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5430 #else /* LARGE_SMB_OFF_T */
5431 if (IVAL(pdata,4) != 0) {
5432 /* more than 32 bits? */
5433 return NT_STATUS_INVALID_PARAMETER;
5435 #endif /* LARGE_SMB_OFF_T */
5436 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5437 "file %s to %.0f\n", fname, (double)size ));
5439 return smb_set_file_size(conn, req,
5446 /****************************************************************************
5447 Allow a UNIX info mknod.
5448 ****************************************************************************/
5450 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5454 SMB_STRUCT_STAT *psbuf)
5456 uint32 file_type = IVAL(pdata,56);
5457 #if defined(HAVE_MAKEDEV)
5458 uint32 dev_major = IVAL(pdata,60);
5459 uint32 dev_minor = IVAL(pdata,68);
5461 SMB_DEV_T dev = (SMB_DEV_T)0;
5462 uint32 raw_unixmode = IVAL(pdata,84);
5466 if (total_data < 100) {
5467 return NT_STATUS_INVALID_PARAMETER;
5470 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5471 if (!NT_STATUS_IS_OK(status)) {
5475 #if defined(HAVE_MAKEDEV)
5476 dev = makedev(dev_major, dev_minor);
5479 switch (file_type) {
5480 #if defined(S_IFIFO)
5481 case UNIX_TYPE_FIFO:
5482 unixmode |= S_IFIFO;
5485 #if defined(S_IFSOCK)
5486 case UNIX_TYPE_SOCKET:
5487 unixmode |= S_IFSOCK;
5490 #if defined(S_IFCHR)
5491 case UNIX_TYPE_CHARDEV:
5492 unixmode |= S_IFCHR;
5495 #if defined(S_IFBLK)
5496 case UNIX_TYPE_BLKDEV:
5497 unixmode |= S_IFBLK;
5501 return NT_STATUS_INVALID_PARAMETER;
5504 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5505 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5507 /* Ok - do the mknod. */
5508 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5509 return map_nt_error_from_unix(errno);
5512 /* If any of the other "set" calls fail we
5513 * don't want to end up with a half-constructed mknod.
5516 if (lp_inherit_perms(SNUM(conn))) {
5518 conn, parent_dirname(fname),
5522 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5523 status = map_nt_error_from_unix(errno);
5524 SMB_VFS_UNLINK(conn,fname);
5527 return NT_STATUS_OK;
5530 /****************************************************************************
5531 Deal with SMB_SET_FILE_UNIX_BASIC.
5532 ****************************************************************************/
5534 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5535 struct smb_request *req,
5540 SMB_STRUCT_STAT *psbuf)
5542 struct timespec ts[2];
5543 uint32 raw_unixmode;
5546 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5547 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5548 NTSTATUS status = NT_STATUS_OK;
5549 BOOL delete_on_fail = False;
5550 enum perm_type ptype;
5552 if (total_data < 100) {
5553 return NT_STATUS_INVALID_PARAMETER;
5556 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5557 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5558 size=IVAL(pdata,0); /* first 8 Bytes are size */
5559 #ifdef LARGE_SMB_OFF_T
5560 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5561 #else /* LARGE_SMB_OFF_T */
5562 if (IVAL(pdata,4) != 0) {
5563 /* more than 32 bits? */
5564 return NT_STATUS_INVALID_PARAMETER;
5566 #endif /* LARGE_SMB_OFF_T */
5569 ts[0] = interpret_long_date(pdata+24); /* access_time */
5570 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5571 set_owner = (uid_t)IVAL(pdata,40);
5572 set_grp = (gid_t)IVAL(pdata,48);
5573 raw_unixmode = IVAL(pdata,84);
5575 if (VALID_STAT(*psbuf)) {
5576 if (S_ISDIR(psbuf->st_mode)) {
5577 ptype = PERM_EXISTING_DIR;
5579 ptype = PERM_EXISTING_FILE;
5582 ptype = PERM_NEW_FILE;
5585 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5586 if (!NT_STATUS_IS_OK(status)) {
5590 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5591 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5592 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5594 if (!VALID_STAT(*psbuf)) {
5596 * The only valid use of this is to create character and block
5597 * devices, and named pipes. This is deprecated (IMHO) and
5598 * a new info level should be used for mknod. JRA.
5601 status = smb_unix_mknod(conn,
5606 if (!NT_STATUS_IS_OK(status)) {
5610 /* Ensure we don't try and change anything else. */
5611 raw_unixmode = SMB_MODE_NO_CHANGE;
5612 size = get_file_size(*psbuf);
5613 ts[0] = get_atimespec(psbuf);
5614 ts[1] = get_mtimespec(psbuf);
5616 * We continue here as we might want to change the
5619 delete_on_fail = True;
5623 /* Horrible backwards compatibility hack as an old server bug
5624 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5628 size = get_file_size(*psbuf);
5633 * Deal with the UNIX specific mode set.
5636 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5637 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5638 (unsigned int)unixmode, fname ));
5639 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5640 return map_nt_error_from_unix(errno);
5645 * Deal with the UNIX specific uid set.
5648 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5651 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5652 (unsigned int)set_owner, fname ));
5654 if (S_ISLNK(psbuf->st_mode)) {
5655 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5657 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5661 status = map_nt_error_from_unix(errno);
5662 if (delete_on_fail) {
5663 SMB_VFS_UNLINK(conn,fname);
5670 * Deal with the UNIX specific gid set.
5673 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5674 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5675 (unsigned int)set_owner, fname ));
5676 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5677 status = map_nt_error_from_unix(errno);
5678 if (delete_on_fail) {
5679 SMB_VFS_UNLINK(conn,fname);
5685 /* Deal with any size changes. */
5687 status = smb_set_file_size(conn, req,
5692 if (!NT_STATUS_IS_OK(status)) {
5696 /* Deal with any time changes. */
5698 return smb_set_file_time(conn,
5705 /****************************************************************************
5706 Deal with SMB_SET_FILE_UNIX_INFO2.
5707 ****************************************************************************/
5709 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5710 struct smb_request *req,
5715 SMB_STRUCT_STAT *psbuf)
5721 if (total_data < 116) {
5722 return NT_STATUS_INVALID_PARAMETER;
5725 /* Start by setting all the fields that are common between UNIX_BASIC
5728 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5730 if (!NT_STATUS_IS_OK(status)) {
5734 smb_fflags = IVAL(pdata, 108);
5735 smb_fmask = IVAL(pdata, 112);
5737 /* NB: We should only attempt to alter the file flags if the client
5738 * sends a non-zero mask.
5740 if (smb_fmask != 0) {
5741 int stat_fflags = 0;
5743 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5745 /* Client asked to alter a flag we don't understand. */
5746 return NT_STATUS_INVALID_PARAMETER;
5749 if (fsp && fsp->fh->fd != -1) {
5750 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5751 return NT_STATUS_NOT_SUPPORTED;
5753 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5754 return map_nt_error_from_unix(errno);
5759 /* XXX: need to add support for changing the create_time here. You
5760 * can do this for paths on Darwin with setattrlist(2). The right way
5761 * to hook this up is probably by extending the VFS utimes interface.
5764 return NT_STATUS_OK;
5767 /****************************************************************************
5768 Create a directory with POSIX semantics.
5769 ****************************************************************************/
5771 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5772 struct smb_request *req,
5776 SMB_STRUCT_STAT *psbuf,
5777 int *pdata_return_size)
5779 NTSTATUS status = NT_STATUS_OK;
5780 uint32 raw_unixmode = 0;
5781 uint32 mod_unixmode = 0;
5782 mode_t unixmode = (mode_t)0;
5783 files_struct *fsp = NULL;
5784 uint16 info_level_return = 0;
5786 char *pdata = *ppdata;
5788 if (total_data < 18) {
5789 return NT_STATUS_INVALID_PARAMETER;
5792 raw_unixmode = IVAL(pdata,8);
5793 /* Next 4 bytes are not yet defined. */
5795 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5796 if (!NT_STATUS_IS_OK(status)) {
5800 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5802 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5803 fname, (unsigned int)unixmode ));
5805 status = open_directory(conn, req,
5808 FILE_READ_ATTRIBUTES, /* Just a stat open */
5809 FILE_SHARE_NONE, /* Ignored for stat opens */
5816 if (NT_STATUS_IS_OK(status)) {
5817 close_file(fsp, NORMAL_CLOSE);
5820 info_level_return = SVAL(pdata,16);
5822 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5823 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5824 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5825 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5827 *pdata_return_size = 12;
5830 /* Realloc the data size */
5831 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5832 if (*ppdata == NULL) {
5833 *pdata_return_size = 0;
5834 return NT_STATUS_NO_MEMORY;
5838 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5839 SSVAL(pdata,2,0); /* No fnum. */
5840 SIVAL(pdata,4,info); /* Was directory created. */
5842 switch (info_level_return) {
5843 case SMB_QUERY_FILE_UNIX_BASIC:
5844 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5845 SSVAL(pdata,10,0); /* Padding. */
5846 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5848 case SMB_QUERY_FILE_UNIX_INFO2:
5849 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5850 SSVAL(pdata,10,0); /* Padding. */
5851 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5854 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5855 SSVAL(pdata,10,0); /* Padding. */
5862 /****************************************************************************
5863 Open/Create a file with POSIX semantics.
5864 ****************************************************************************/
5866 static NTSTATUS smb_posix_open(connection_struct *conn,
5867 struct smb_request *req,
5871 SMB_STRUCT_STAT *psbuf,
5872 int *pdata_return_size)
5874 BOOL extended_oplock_granted = False;
5875 char *pdata = *ppdata;
5877 uint32 wire_open_mode = 0;
5878 uint32 raw_unixmode = 0;
5879 uint32 mod_unixmode = 0;
5880 uint32 create_disp = 0;
5881 uint32 access_mask = 0;
5882 uint32 create_options = 0;
5883 NTSTATUS status = NT_STATUS_OK;
5884 mode_t unixmode = (mode_t)0;
5885 files_struct *fsp = NULL;
5886 int oplock_request = 0;
5888 uint16 info_level_return = 0;
5890 if (total_data < 18) {
5891 return NT_STATUS_INVALID_PARAMETER;
5894 flags = IVAL(pdata,0);
5895 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5896 if (oplock_request) {
5897 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5900 wire_open_mode = IVAL(pdata,4);
5902 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5903 return smb_posix_mkdir(conn, req,
5911 switch (wire_open_mode & SMB_ACCMODE) {
5913 access_mask = FILE_READ_DATA;
5916 access_mask = FILE_WRITE_DATA;
5919 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5922 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5923 (unsigned int)wire_open_mode ));
5924 return NT_STATUS_INVALID_PARAMETER;
5927 wire_open_mode &= ~SMB_ACCMODE;
5929 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5930 create_disp = FILE_CREATE;
5931 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5932 create_disp = FILE_OVERWRITE_IF;
5933 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5934 create_disp = FILE_OPEN_IF;
5936 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5937 (unsigned int)wire_open_mode ));
5938 return NT_STATUS_INVALID_PARAMETER;
5941 raw_unixmode = IVAL(pdata,8);
5942 /* Next 4 bytes are not yet defined. */
5944 status = unix_perms_from_wire(conn,
5947 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5950 if (!NT_STATUS_IS_OK(status)) {
5954 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5956 if (wire_open_mode & SMB_O_SYNC) {
5957 create_options |= FILE_WRITE_THROUGH;
5959 if (wire_open_mode & SMB_O_APPEND) {
5960 access_mask |= FILE_APPEND_DATA;
5962 if (wire_open_mode & SMB_O_DIRECT) {
5963 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5966 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5968 (unsigned int)wire_open_mode,
5969 (unsigned int)unixmode ));
5971 status = open_file_ntcreate(conn, req,
5975 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5977 0, /* no create options yet. */
5983 if (!NT_STATUS_IS_OK(status)) {
5987 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5988 extended_oplock_granted = True;
5991 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5992 extended_oplock_granted = True;
5995 info_level_return = SVAL(pdata,16);
5997 /* Allocate the correct return size. */
5999 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6000 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6001 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6002 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6004 *pdata_return_size = 12;
6007 /* Realloc the data size */
6008 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6009 if (*ppdata == NULL) {
6010 close_file(fsp,ERROR_CLOSE);
6011 *pdata_return_size = 0;
6012 return NT_STATUS_NO_MEMORY;
6016 if (extended_oplock_granted) {
6017 if (flags & REQUEST_BATCH_OPLOCK) {
6018 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6020 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6022 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6023 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6025 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6028 SSVAL(pdata,2,fsp->fnum);
6029 SIVAL(pdata,4,info); /* Was file created etc. */
6031 switch (info_level_return) {
6032 case SMB_QUERY_FILE_UNIX_BASIC:
6033 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6034 SSVAL(pdata,10,0); /* padding. */
6035 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6037 case SMB_QUERY_FILE_UNIX_INFO2:
6038 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6039 SSVAL(pdata,10,0); /* padding. */
6040 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6043 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6044 SSVAL(pdata,10,0); /* padding. */
6047 return NT_STATUS_OK;
6050 /****************************************************************************
6051 Delete a file with POSIX semantics.
6052 ****************************************************************************/
6054 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6055 struct smb_request *req,
6059 SMB_STRUCT_STAT *psbuf)
6061 NTSTATUS status = NT_STATUS_OK;
6062 files_struct *fsp = NULL;
6067 struct share_mode_lock *lck = NULL;
6069 if (total_data < 2) {
6070 return NT_STATUS_INVALID_PARAMETER;
6073 flags = SVAL(pdata,0);
6075 if (!VALID_STAT(*psbuf)) {
6076 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6079 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6080 !VALID_STAT_OF_DIR(*psbuf)) {
6081 return NT_STATUS_NOT_A_DIRECTORY;
6084 DEBUG(10,("smb_posix_unlink: %s %s\n",
6085 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6088 if (VALID_STAT_OF_DIR(*psbuf)) {
6089 status = open_directory(conn, req,
6093 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6096 FILE_FLAG_POSIX_SEMANTICS|0777,
6101 status = open_file_ntcreate(conn, req,
6105 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6108 FILE_FLAG_POSIX_SEMANTICS|0777,
6109 0, /* No oplock, but break existing ones. */
6114 if (!NT_STATUS_IS_OK(status)) {
6119 * Don't lie to client. If we can't really delete due to
6120 * non-POSIX opens return SHARING_VIOLATION.
6123 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6125 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6126 "lock for file %s\n", fsp->fsp_name));
6127 close_file(fsp, NORMAL_CLOSE);
6128 return NT_STATUS_INVALID_PARAMETER;
6132 * See if others still have the file open. If this is the case, then
6133 * don't delete. If all opens are POSIX delete we can set the delete
6134 * on close disposition.
6136 for (i=0; i<lck->num_share_modes; i++) {
6137 struct share_mode_entry *e = &lck->share_modes[i];
6138 if (is_valid_share_mode_entry(e)) {
6139 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6142 /* Fail with sharing violation. */
6143 close_file(fsp, NORMAL_CLOSE);
6145 return NT_STATUS_SHARING_VIOLATION;
6150 * Set the delete on close.
6152 status = smb_set_file_disposition_info(conn,
6159 if (!NT_STATUS_IS_OK(status)) {
6160 close_file(fsp, NORMAL_CLOSE);
6165 return close_file(fsp, NORMAL_CLOSE);
6168 /****************************************************************************
6169 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6170 ****************************************************************************/
6172 static void call_trans2setfilepathinfo(connection_struct *conn,
6173 struct smb_request *req,
6174 unsigned int tran_call,
6175 char **pparams, int total_params,
6176 char **ppdata, int total_data,
6177 unsigned int max_data_bytes)
6179 char *params = *pparams;
6180 char *pdata = *ppdata;
6182 SMB_STRUCT_STAT sbuf;
6184 files_struct *fsp = NULL;
6185 NTSTATUS status = NT_STATUS_OK;
6186 int data_return_size = 0;
6187 TALLOC_CTX *ctx = talloc_tos();
6190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6196 if (tran_call == TRANSACT2_SETFILEINFO) {
6197 if (total_params < 4) {
6198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6202 fsp = file_fsp(SVAL(params,0));
6203 /* Basic check for non-null fsp. */
6204 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6207 info_level = SVAL(params,2);
6209 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6211 reply_nterror(req, NT_STATUS_NO_MEMORY);
6215 if(fsp->is_directory || fsp->fh->fd == -1) {
6217 * This is actually a SETFILEINFO on a directory
6218 * handle (returned from an NT SMB). NT5.0 seems
6219 * to do this call. JRA.
6221 if (INFO_LEVEL_IS_UNIX(info_level)) {
6222 /* Always do lstat for UNIX calls. */
6223 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6224 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6225 reply_unixerror(req,ERRDOS,ERRbadpath);
6229 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6230 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6231 reply_unixerror(req,ERRDOS,ERRbadpath);
6235 } else if (fsp->print_file) {
6237 * Doing a DELETE_ON_CLOSE should cancel a print job.
6239 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6240 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6242 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6245 send_trans2_replies(req, params, 2,
6250 reply_unixerror(req, ERRDOS, ERRbadpath);
6255 * Original code - this is an open file.
6257 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6261 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6262 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6263 reply_unixerror(req, ERRDOS, ERRbadfid);
6271 if (total_params < 7) {
6272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6276 info_level = SVAL(params,0);
6277 srvstr_get_path(params, req->flags2, fname_in, ¶ms[6],
6278 sizeof(fname_in), total_params - 6, STR_TERMINATE,
6280 if (!NT_STATUS_IS_OK(status)) {
6281 reply_nterror(req, status);
6285 status = resolve_dfspath(ctx, conn,
6286 req->flags2 & FLAGS2_DFS_PATHNAMES,
6289 if (!NT_STATUS_IS_OK(status)) {
6290 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6291 reply_botherror(req,
6292 NT_STATUS_PATH_NOT_COVERED,
6293 ERRSRV, ERRbadpath);
6296 reply_nterror(req, status);
6300 status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
6301 if (!NT_STATUS_IS_OK(status)) {
6302 reply_nterror(req, status);
6306 status = check_name(conn, fname);
6307 if (!NT_STATUS_IS_OK(status)) {
6308 reply_nterror(req, status);
6312 if (INFO_LEVEL_IS_UNIX(info_level)) {
6314 * For CIFS UNIX extensions the target name may not exist.
6317 /* Always do lstat for UNIX calls. */
6318 SMB_VFS_LSTAT(conn,fname,&sbuf);
6320 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6321 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6322 reply_unixerror(req, ERRDOS, ERRbadpath);
6327 if (!CAN_WRITE(conn)) {
6328 reply_doserror(req, ERRSRV, ERRaccess);
6332 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6333 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6337 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6338 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6340 /* Realloc the parameter size */
6341 *pparams = (char *)SMB_REALLOC(*pparams,2);
6342 if (*pparams == NULL) {
6343 reply_nterror(req, NT_STATUS_NO_MEMORY);
6350 if (fsp && !null_timespec(fsp->pending_modtime)) {
6351 /* the pending modtime overrides the current modtime */
6352 set_mtimespec(&sbuf, fsp->pending_modtime);
6355 switch (info_level) {
6357 case SMB_INFO_STANDARD:
6359 status = smb_set_info_standard(conn,
6368 case SMB_INFO_SET_EA:
6370 status = smb_info_set_ea(conn,
6378 case SMB_SET_FILE_BASIC_INFO:
6379 case SMB_FILE_BASIC_INFORMATION:
6381 status = smb_set_file_basic_info(conn,
6390 case SMB_FILE_ALLOCATION_INFORMATION:
6391 case SMB_SET_FILE_ALLOCATION_INFO:
6393 status = smb_set_file_allocation_info(conn, req,
6402 case SMB_FILE_END_OF_FILE_INFORMATION:
6403 case SMB_SET_FILE_END_OF_FILE_INFO:
6405 status = smb_set_file_end_of_file_info(conn, req,
6414 case SMB_FILE_DISPOSITION_INFORMATION:
6415 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6418 /* JRA - We used to just ignore this on a path ?
6419 * Shouldn't this be invalid level on a pathname
6422 if (tran_call != TRANSACT2_SETFILEINFO) {
6423 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6426 status = smb_set_file_disposition_info(conn,
6435 case SMB_FILE_POSITION_INFORMATION:
6437 status = smb_file_position_information(conn,
6444 /* From tridge Samba4 :
6445 * MODE_INFORMATION in setfileinfo (I have no
6446 * idea what "mode information" on a file is - it takes a value of 0,
6447 * 2, 4 or 6. What could it be?).
6450 case SMB_FILE_MODE_INFORMATION:
6452 status = smb_file_mode_information(conn,
6459 * CIFS UNIX extensions.
6462 case SMB_SET_FILE_UNIX_BASIC:
6464 status = smb_set_file_unix_basic(conn, req,
6473 case SMB_SET_FILE_UNIX_INFO2:
6475 status = smb_set_file_unix_info2(conn, req,
6484 case SMB_SET_FILE_UNIX_LINK:
6486 if (tran_call != TRANSACT2_SETPATHINFO) {
6487 /* We must have a pathname for this. */
6488 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6491 status = smb_set_file_unix_link(conn, req, pdata,
6496 case SMB_SET_FILE_UNIX_HLINK:
6498 if (tran_call != TRANSACT2_SETPATHINFO) {
6499 /* We must have a pathname for this. */
6500 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6503 status = smb_set_file_unix_hlink(conn, req,
6509 case SMB_FILE_RENAME_INFORMATION:
6511 status = smb_file_rename_information(conn, req,
6517 #if defined(HAVE_POSIX_ACLS)
6518 case SMB_SET_POSIX_ACL:
6520 status = smb_set_posix_acl(conn,
6530 case SMB_SET_POSIX_LOCK:
6532 if (tran_call != TRANSACT2_SETFILEINFO) {
6533 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6536 status = smb_set_posix_lock(conn, req->inbuf,
6537 smb_len(req->inbuf) + 4,
6538 pdata, total_data, fsp);
6542 case SMB_POSIX_PATH_OPEN:
6544 if (tran_call != TRANSACT2_SETPATHINFO) {
6545 /* We must have a pathname for this. */
6546 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6550 status = smb_posix_open(conn, req,
6559 case SMB_POSIX_PATH_UNLINK:
6561 if (tran_call != TRANSACT2_SETPATHINFO) {
6562 /* We must have a pathname for this. */
6563 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6567 status = smb_posix_unlink(conn, req,
6576 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6581 if (!NT_STATUS_IS_OK(status)) {
6582 if (open_was_deferred(req->mid)) {
6583 /* We have re-scheduled this call. */
6586 if (blocking_lock_was_deferred(req->mid)) {
6587 /* We have re-scheduled this call. */
6590 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6591 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6592 ERRSRV, ERRbadpath);
6595 if (info_level == SMB_POSIX_PATH_OPEN) {
6596 reply_openerror(req, status);
6600 reply_nterror(req, status);
6605 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6611 /****************************************************************************
6612 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6613 ****************************************************************************/
6615 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6616 char **pparams, int total_params,
6617 char **ppdata, int total_data,
6618 unsigned int max_data_bytes)
6620 char *params = *pparams;
6621 char *pdata = *ppdata;
6622 pstring directory_in;
6623 char *directory = NULL;
6624 SMB_STRUCT_STAT sbuf;
6625 NTSTATUS status = NT_STATUS_OK;
6626 struct ea_list *ea_list = NULL;
6628 if (!CAN_WRITE(conn)) {
6629 reply_doserror(req, ERRSRV, ERRaccess);
6633 if (total_params < 5) {
6634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6638 srvstr_get_path(params, req->flags2, directory_in, ¶ms[4],
6639 sizeof(directory_in), total_params - 4, STR_TERMINATE,
6641 if (!NT_STATUS_IS_OK(status)) {
6642 reply_nterror(req, status);
6646 DEBUG(3,("call_trans2mkdir : name = %s\n", directory_in));
6648 status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf);
6649 if (!NT_STATUS_IS_OK(status)) {
6650 reply_nterror(req, status);
6654 status = check_name(conn, directory);
6655 if (!NT_STATUS_IS_OK(status)) {
6656 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6657 reply_nterror(req, status);
6661 /* Any data in this call is an EA list. */
6662 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6663 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6668 * OS/2 workplace shell seems to send SET_EA requests of "null"
6669 * length (4 bytes containing IVAL 4).
6670 * They seem to have no effect. Bug #3212. JRA.
6673 if (total_data != 4) {
6674 if (total_data < 10) {
6675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6679 if (IVAL(pdata,0) > total_data) {
6680 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6681 IVAL(pdata,0), (unsigned int)total_data));
6682 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6686 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6692 } else if (IVAL(pdata,0) != 4) {
6693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6697 status = create_directory(conn, directory);
6699 if (!NT_STATUS_IS_OK(status)) {
6700 reply_nterror(req, status);
6704 /* Try and set any given EA. */
6706 status = set_ea(conn, NULL, directory, ea_list);
6707 if (!NT_STATUS_IS_OK(status)) {
6708 reply_nterror(req, status);
6713 /* Realloc the parameter and data sizes */
6714 *pparams = (char *)SMB_REALLOC(*pparams,2);
6715 if(*pparams == NULL) {
6716 reply_nterror(req, NT_STATUS_NO_MEMORY);
6723 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6728 /****************************************************************************
6729 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6730 We don't actually do this - we just send a null response.
6731 ****************************************************************************/
6733 static void call_trans2findnotifyfirst(connection_struct *conn,
6734 struct smb_request *req,
6735 char **pparams, int total_params,
6736 char **ppdata, int total_data,
6737 unsigned int max_data_bytes)
6739 static uint16 fnf_handle = 257;
6740 char *params = *pparams;
6743 if (total_params < 6) {
6744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6748 info_level = SVAL(params,4);
6749 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6751 switch (info_level) {
6756 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6760 /* Realloc the parameter and data sizes */
6761 *pparams = (char *)SMB_REALLOC(*pparams,6);
6762 if (*pparams == NULL) {
6763 reply_nterror(req, NT_STATUS_NO_MEMORY);
6768 SSVAL(params,0,fnf_handle);
6769 SSVAL(params,2,0); /* No changes */
6770 SSVAL(params,4,0); /* No EA errors */
6777 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6782 /****************************************************************************
6783 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6784 changes). Currently this does nothing.
6785 ****************************************************************************/
6787 static void call_trans2findnotifynext(connection_struct *conn,
6788 struct smb_request *req,
6789 char **pparams, int total_params,
6790 char **ppdata, int total_data,
6791 unsigned int max_data_bytes)
6793 char *params = *pparams;
6795 DEBUG(3,("call_trans2findnotifynext\n"));
6797 /* Realloc the parameter and data sizes */
6798 *pparams = (char *)SMB_REALLOC(*pparams,4);
6799 if (*pparams == NULL) {
6800 reply_nterror(req, NT_STATUS_NO_MEMORY);
6805 SSVAL(params,0,0); /* No changes */
6806 SSVAL(params,2,0); /* No EA errors */
6808 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6813 /****************************************************************************
6814 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6815 ****************************************************************************/
6817 static void call_trans2getdfsreferral(connection_struct *conn,
6818 struct smb_request *req,
6819 char **pparams, int total_params,
6820 char **ppdata, int total_data,
6821 unsigned int max_data_bytes)
6823 char *params = *pparams;
6826 int max_referral_level;
6827 NTSTATUS status = NT_STATUS_OK;
6829 DEBUG(10,("call_trans2getdfsreferral\n"));
6831 if (total_params < 3) {
6832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6836 max_referral_level = SVAL(params,0);
6838 if(!lp_host_msdfs()) {
6839 reply_doserror(req, ERRDOS, ERRbadfunc);
6843 srvstr_pull(params, req->flags2, pathname, ¶ms[2],
6844 sizeof(pathname), total_params - 2, STR_TERMINATE);
6845 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6846 ppdata,&status)) < 0) {
6847 reply_nterror(req, status);
6851 SSVAL(req->inbuf, smb_flg2,
6852 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6853 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6858 #define LMCAT_SPL 0x53
6859 #define LMFUNC_GETJOBID 0x60
6861 /****************************************************************************
6862 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6863 ****************************************************************************/
6865 static void call_trans2ioctl(connection_struct *conn,
6866 struct smb_request *req,
6867 char **pparams, int total_params,
6868 char **ppdata, int total_data,
6869 unsigned int max_data_bytes)
6871 char *pdata = *ppdata;
6872 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6874 /* check for an invalid fid before proceeding */
6877 reply_doserror(req, ERRDOS, ERRbadfid);
6881 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6882 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6883 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6884 if (*ppdata == NULL) {
6885 reply_nterror(req, NT_STATUS_NO_MEMORY);
6890 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6891 CAN ACCEPT THIS IN UNICODE. JRA. */
6893 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6894 srvstr_push(pdata, req->flags2, pdata + 2,
6895 global_myname(), 15,
6896 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6897 srvstr_push(pdata, req->flags2, pdata+18,
6898 lp_servicename(SNUM(conn)), 13,
6899 STR_ASCII|STR_TERMINATE); /* Service name */
6900 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6905 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6906 reply_doserror(req, ERRSRV, ERRerror);
6909 /****************************************************************************
6910 Reply to a SMBfindclose (stop trans2 directory search).
6911 ****************************************************************************/
6913 void reply_findclose(connection_struct *conn, struct smb_request *req)
6917 START_PROFILE(SMBfindclose);
6920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6921 END_PROFILE(SMBfindclose);
6925 dptr_num = SVALS(req->inbuf,smb_vwv0);
6927 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6929 dptr_close(&dptr_num);
6931 reply_outbuf(req, 0, 0);
6933 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6935 END_PROFILE(SMBfindclose);
6939 /****************************************************************************
6940 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6941 ****************************************************************************/
6943 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6947 START_PROFILE(SMBfindnclose);
6950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6951 END_PROFILE(SMBfindnclose);
6955 dptr_num = SVAL(req->inbuf,smb_vwv0);
6957 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6959 /* We never give out valid handles for a
6960 findnotifyfirst - so any dptr_num is ok here.
6963 reply_outbuf(req, 0, 0);
6965 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6967 END_PROFILE(SMBfindnclose);
6971 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6972 struct trans_state *state)
6974 if (Protocol >= PROTOCOL_NT1) {
6975 req->flags2 |= 0x40; /* IS_LONG_NAME */
6976 SSVAL(req->inbuf,smb_flg2,req->flags2);
6979 /* Now we must call the relevant TRANS2 function */
6980 switch(state->call) {
6981 case TRANSACT2_OPEN:
6983 START_PROFILE(Trans2_open);
6984 call_trans2open(conn, req,
6985 &state->param, state->total_param,
6986 &state->data, state->total_data,
6987 state->max_data_return);
6988 END_PROFILE(Trans2_open);
6992 case TRANSACT2_FINDFIRST:
6994 START_PROFILE(Trans2_findfirst);
6995 call_trans2findfirst(conn, req,
6996 &state->param, state->total_param,
6997 &state->data, state->total_data,
6998 state->max_data_return);
6999 END_PROFILE(Trans2_findfirst);
7003 case TRANSACT2_FINDNEXT:
7005 START_PROFILE(Trans2_findnext);
7006 call_trans2findnext(conn, req,
7007 &state->param, state->total_param,
7008 &state->data, state->total_data,
7009 state->max_data_return);
7010 END_PROFILE(Trans2_findnext);
7014 case TRANSACT2_QFSINFO:
7016 START_PROFILE(Trans2_qfsinfo);
7017 call_trans2qfsinfo(conn, req,
7018 &state->param, state->total_param,
7019 &state->data, state->total_data,
7020 state->max_data_return);
7021 END_PROFILE(Trans2_qfsinfo);
7025 case TRANSACT2_SETFSINFO:
7027 START_PROFILE(Trans2_setfsinfo);
7028 call_trans2setfsinfo(conn, req,
7029 &state->param, state->total_param,
7030 &state->data, state->total_data,
7031 state->max_data_return);
7032 END_PROFILE(Trans2_setfsinfo);
7036 case TRANSACT2_QPATHINFO:
7037 case TRANSACT2_QFILEINFO:
7039 START_PROFILE(Trans2_qpathinfo);
7040 call_trans2qfilepathinfo(conn, req, state->call,
7041 &state->param, state->total_param,
7042 &state->data, state->total_data,
7043 state->max_data_return);
7044 END_PROFILE(Trans2_qpathinfo);
7048 case TRANSACT2_SETPATHINFO:
7049 case TRANSACT2_SETFILEINFO:
7051 START_PROFILE(Trans2_setpathinfo);
7052 call_trans2setfilepathinfo(conn, req, state->call,
7053 &state->param, state->total_param,
7054 &state->data, state->total_data,
7055 state->max_data_return);
7056 END_PROFILE(Trans2_setpathinfo);
7060 case TRANSACT2_FINDNOTIFYFIRST:
7062 START_PROFILE(Trans2_findnotifyfirst);
7063 call_trans2findnotifyfirst(conn, req,
7064 &state->param, state->total_param,
7065 &state->data, state->total_data,
7066 state->max_data_return);
7067 END_PROFILE(Trans2_findnotifyfirst);
7071 case TRANSACT2_FINDNOTIFYNEXT:
7073 START_PROFILE(Trans2_findnotifynext);
7074 call_trans2findnotifynext(conn, req,
7075 &state->param, state->total_param,
7076 &state->data, state->total_data,
7077 state->max_data_return);
7078 END_PROFILE(Trans2_findnotifynext);
7082 case TRANSACT2_MKDIR:
7084 START_PROFILE(Trans2_mkdir);
7085 call_trans2mkdir(conn, req,
7086 &state->param, state->total_param,
7087 &state->data, state->total_data,
7088 state->max_data_return);
7089 END_PROFILE(Trans2_mkdir);
7093 case TRANSACT2_GET_DFS_REFERRAL:
7095 START_PROFILE(Trans2_get_dfs_referral);
7096 call_trans2getdfsreferral(conn, req,
7097 &state->param, state->total_param,
7098 &state->data, state->total_data,
7099 state->max_data_return);
7100 END_PROFILE(Trans2_get_dfs_referral);
7104 case TRANSACT2_IOCTL:
7106 START_PROFILE(Trans2_ioctl);
7107 call_trans2ioctl(conn, req,
7108 &state->param, state->total_param,
7109 &state->data, state->total_data,
7110 state->max_data_return);
7111 END_PROFILE(Trans2_ioctl);
7116 /* Error in request */
7117 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7118 reply_doserror(req, ERRSRV,ERRerror);
7122 /****************************************************************************
7123 Reply to a SMBtrans2.
7124 ****************************************************************************/
7126 void reply_trans2(connection_struct *conn, struct smb_request *req)
7132 unsigned int tran_call;
7134 struct trans_state *state;
7137 START_PROFILE(SMBtrans2);
7139 if (req->wct < 14) {
7140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7141 END_PROFILE(SMBtrans2);
7145 dsoff = SVAL(req->inbuf, smb_dsoff);
7146 dscnt = SVAL(req->inbuf, smb_dscnt);
7147 psoff = SVAL(req->inbuf, smb_psoff);
7148 pscnt = SVAL(req->inbuf, smb_pscnt);
7149 tran_call = SVAL(req->inbuf, smb_setup0);
7150 size = smb_len(req->inbuf) + 4;
7152 result = allow_new_trans(conn->pending_trans, req->mid);
7153 if (!NT_STATUS_IS_OK(result)) {
7154 DEBUG(2, ("Got invalid trans2 request: %s\n",
7155 nt_errstr(result)));
7156 reply_nterror(req, result);
7157 END_PROFILE(SMBtrans2);
7161 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7162 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7163 && (tran_call != TRANSACT2_QFILEINFO)) {
7164 reply_doserror(req, ERRSRV, ERRaccess);
7165 END_PROFILE(SMBtrans2);
7169 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7170 DEBUG(0, ("talloc failed\n"));
7171 reply_nterror(req, NT_STATUS_NO_MEMORY);
7172 END_PROFILE(SMBtrans2);
7176 state->cmd = SMBtrans2;
7178 state->mid = req->mid;
7179 state->vuid = req->vuid;
7180 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7181 state->setup = NULL;
7182 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7183 state->param = NULL;
7184 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7186 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7187 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7188 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7189 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7190 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7192 state->call = tran_call;
7194 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7195 is so as a sanity check */
7196 if (state->setup_count != 1) {
7198 * Need to have rc=0 for ioctl to get job id for OS/2.
7199 * Network printing will fail if function is not successful.
7200 * Similar function in reply.c will be used if protocol
7201 * is LANMAN1.0 instead of LM1.2X002.
7202 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7203 * outbuf doesn't have to be set(only job id is used).
7205 if ( (state->setup_count == 4)
7206 && (tran_call == TRANSACT2_IOCTL)
7207 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7208 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7209 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7211 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7212 DEBUG(2,("Transaction is %d\n",tran_call));
7214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7215 END_PROFILE(SMBtrans2);
7220 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7223 if (state->total_data) {
7224 /* Can't use talloc here, the core routines do realloc on the
7225 * params and data. */
7226 state->data = (char *)SMB_MALLOC(state->total_data);
7227 if (state->data == NULL) {
7228 DEBUG(0,("reply_trans2: data malloc fail for %u "
7229 "bytes !\n", (unsigned int)state->total_data));
7231 reply_nterror(req, NT_STATUS_NO_MEMORY);
7232 END_PROFILE(SMBtrans2);
7235 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7237 if ((smb_base(req->inbuf)+dsoff+dscnt
7238 > (char *)req->inbuf + size) ||
7239 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7242 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7245 if (state->total_param) {
7246 /* Can't use talloc here, the core routines do realloc on the
7247 * params and data. */
7248 state->param = (char *)SMB_MALLOC(state->total_param);
7249 if (state->param == NULL) {
7250 DEBUG(0,("reply_trans: param malloc fail for %u "
7251 "bytes !\n", (unsigned int)state->total_param));
7252 SAFE_FREE(state->data);
7254 reply_nterror(req, NT_STATUS_NO_MEMORY);
7255 END_PROFILE(SMBtrans2);
7258 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7260 if ((smb_base(req->inbuf)+psoff+pscnt
7261 > (char *)req->inbuf + size) ||
7262 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7265 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7268 state->received_data = dscnt;
7269 state->received_param = pscnt;
7271 if ((state->received_param == state->total_param) &&
7272 (state->received_data == state->total_data)) {
7274 handle_trans2(conn, req, state);
7276 SAFE_FREE(state->data);
7277 SAFE_FREE(state->param);
7279 END_PROFILE(SMBtrans2);
7283 DLIST_ADD(conn->pending_trans, state);
7285 /* We need to send an interim response then receive the rest
7286 of the parameter/data bytes */
7287 reply_outbuf(req, 0, 0);
7288 show_msg((char *)req->outbuf);
7289 END_PROFILE(SMBtrans2);
7294 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7295 SAFE_FREE(state->data);
7296 SAFE_FREE(state->param);
7298 END_PROFILE(SMBtrans2);
7299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7303 /****************************************************************************
7304 Reply to a SMBtranss2
7305 ****************************************************************************/
7307 void reply_transs2(connection_struct *conn, struct smb_request *req)
7309 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7310 struct trans_state *state;
7313 START_PROFILE(SMBtranss2);
7315 show_msg((char *)req->inbuf);
7318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7319 END_PROFILE(SMBtranss2);
7323 size = smb_len(req->inbuf)+4;
7325 for (state = conn->pending_trans; state != NULL;
7326 state = state->next) {
7327 if (state->mid == req->mid) {
7332 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7333 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7334 END_PROFILE(SMBtranss2);
7338 /* Revise state->total_param and state->total_data in case they have
7339 changed downwards */
7341 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7342 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7343 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7344 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7346 pcnt = SVAL(req->inbuf, smb_spscnt);
7347 poff = SVAL(req->inbuf, smb_spsoff);
7348 pdisp = SVAL(req->inbuf, smb_spsdisp);
7350 dcnt = SVAL(req->inbuf, smb_sdscnt);
7351 doff = SVAL(req->inbuf, smb_sdsoff);
7352 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7354 state->received_param += pcnt;
7355 state->received_data += dcnt;
7357 if ((state->received_data > state->total_data) ||
7358 (state->received_param > state->total_param))
7362 if (pdisp+pcnt > state->total_param)
7364 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7366 if (pdisp > state->total_param)
7368 if ((smb_base(req->inbuf) + poff + pcnt
7369 > (char *)req->inbuf + size) ||
7370 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7372 if (state->param + pdisp < state->param)
7375 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7380 if (ddisp+dcnt > state->total_data)
7382 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7384 if (ddisp > state->total_data)
7386 if ((smb_base(req->inbuf) + doff + dcnt
7387 > (char *)req->inbuf + size) ||
7388 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7390 if (state->data + ddisp < state->data)
7393 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7397 if ((state->received_param < state->total_param) ||
7398 (state->received_data < state->total_data)) {
7399 END_PROFILE(SMBtranss2);
7404 * construct_reply_common will copy smb_com from inbuf to
7405 * outbuf. SMBtranss2 is wrong here.
7407 SCVAL(req->inbuf,smb_com,SMBtrans2);
7409 handle_trans2(conn, req, state);
7411 DLIST_REMOVE(conn->pending_trans, state);
7412 SAFE_FREE(state->data);
7413 SAFE_FREE(state->param);
7416 END_PROFILE(SMBtranss2);
7421 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7422 DLIST_REMOVE(conn->pending_trans, state);
7423 SAFE_FREE(state->data);
7424 SAFE_FREE(state->param);
7426 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7427 END_PROFILE(SMBtranss2);