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
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 2 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, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct *conn,
41 const SMB_STRUCT_STAT *psbuf);
43 static char *store_file_unix_basic_info2(connection_struct *conn,
46 const SMB_STRUCT_STAT *psbuf);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
55 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type = get_remote_arch();
59 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60 val = SMB_ROUNDUP(val,rval);
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
68 ********************************************************************/
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
74 if(S_ISDIR(sbuf->st_mode)) {
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
81 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
84 if (fsp && fsp->initial_allocation_size)
85 ret = MAX(ret,fsp->initial_allocation_size);
87 return smb_roundup(conn, ret);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120 const char *fname, char *ea_name, struct ea_struct *pea)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size = 256;
129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 if (fsp && fsp->fh->fd != -1) {
135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150 dump_data(10, (uint8 *)val, sizeret);
153 if (strnequal(ea_name, "user.", 5)) {
154 pea->name = &ea_name[5];
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168 const char *fname, size_t *pea_total_len)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size = 1024;
176 struct ea_list *ea_list_head = NULL;
180 if (!lp_ea_support(SNUM(conn))) {
184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
191 if (fsp && fsp->fh->fd != -1) {
192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
197 if (sizeret == -1 && errno == ERANGE) {
198 ea_namelist_size *= 2;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211 struct ea_list *listp;
213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
216 listp = TALLOC_P(mem_ctx, struct ea_list);
220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
226 push_ascii_fstring(dos_ea_name, listp->ea.name);
227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len, dos_ea_name,
230 (unsigned int)listp->ea.value.length ));
232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
234 /* Add on 4 for total length. */
235 if (*pea_total_len) {
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250 connection_struct *conn, struct ea_list *ea_list)
252 unsigned int ret_data_size = 4;
255 SMB_ASSERT(total_data_size >= 4);
257 if (!lp_ea_support(SNUM(conn))) {
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
270 if (ea_list->ea.value.length > 65535) {
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290 SIVAL(pdata,0,ret_data_size);
291 return ret_data_size;
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
296 size_t total_ea_len = 0;
297 TALLOC_CTX *mem_ctx = NULL;
299 if (!lp_ea_support(SNUM(conn))) {
302 mem_ctx = talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304 talloc_destroy(mem_ctx);
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
318 for (; ea_list; ea_list = ea_list->next) {
319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name[5], ea_list->ea.name));
322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
326 talloc_destroy(mem_ctx);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
335 if (!lp_ea_support(SNUM(conn))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED;
339 for (;ea_list; ea_list = ea_list->next) {
341 fstring unix_ea_name;
343 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name, ea_list->ea.name);
346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
350 if (samba_private_attr_name(unix_ea_name)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352 return NT_STATUS_ACCESS_DENIED;
355 if (ea_list->ea.value.length == 0) {
356 /* Remove the attribute. */
357 if (fsp && (fsp->fh->fd != -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name, fsp->fsp_name));
360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name, fname));
364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
367 /* Removing a non existent attribute always succeeds. */
368 if (ret == -1 && errno == ENOATTR) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
375 if (fsp && (fsp->fh->fd != -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name, fsp->fsp_name));
378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name, fname));
383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
390 if (errno == ENOTSUP) {
391 return NT_STATUS_EAS_NOT_SUPPORTED;
394 return map_nt_error_from_unix(errno);
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
406 struct ea_list *ea_list_head = NULL;
409 while (offset + 2 < data_size) {
410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411 unsigned int namelen = CVAL(pdata,offset);
413 offset++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417 (offset > data_size) || (namelen > data_size) ||
418 (offset + namelen >= data_size)) {
421 /* Ensure the name is null terminated. */
422 if (pdata[offset + namelen] != '\0') {
425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
430 offset += (namelen + 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
446 unsigned int namelen;
456 eal->ea.flags = CVAL(pdata,0);
457 namelen = CVAL(pdata,1);
458 val_len = SVAL(pdata,2);
460 if (4 + namelen + 1 + val_len > data_size) {
464 /* Ensure the name is null terminated. */
465 if (pdata[namelen + 4] != '\0') {
468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474 if (!eal->ea.value.data) {
478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal->ea.value.data[val_len] = '\0';
482 /* But don't count the null. */
483 eal->ea.value.length--;
486 *pbytes_used = 4 + namelen + 1 + val_len;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490 dump_data(10, eal->ea.value.data, eal->ea.value.length);
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
501 struct ea_list *ea_list_head = NULL;
503 size_t bytes_used = 0;
505 while (offset < data_size) {
506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513 offset += bytes_used;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list *ealist)
526 struct ea_list *listp;
529 for (listp = ealist; listp; listp = listp->next) {
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 /* Add on 4 for total length. */
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
549 struct ea_list *nlistp, *flistp;
551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552 for (flistp = file_list; flistp; flistp = flistp->next) {
553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
559 /* Copy the data from this entry. */
560 nlistp->ea.flags = flistp->ea.flags;
561 nlistp->ea.value = flistp->ea.value;
564 nlistp->ea.flags = 0;
565 ZERO_STRUCT(nlistp->ea.value);
569 *total_ea_len = ea_list_size(name_list);
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(const char *inbuf,
589 /* As we are using a protocol > LANMAN1 then the max_send
590 variable must have been set in the sessetupX call.
591 This takes precedence over the max_xmit field in the
592 global struct. These different max_xmit variables should
593 be merged as this is now too confusing */
595 int data_to_send = datasize;
596 int params_to_send = paramsize;
598 const char *pp = params;
599 const char *pd = pdata;
600 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
601 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
602 int data_alignment_offset = 0;
604 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
606 set_message(inbuf,outbuf,10,0,True);
608 /* Modify the data_to_send and datasize and set the error if
609 we're trying to send more than max_data_bytes. We still send
610 the part of the packet(s) that fit. Strange, but needed
613 if (max_data_bytes > 0 && datasize > max_data_bytes) {
614 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
615 max_data_bytes, datasize ));
616 datasize = data_to_send = max_data_bytes;
617 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
620 /* If there genuinely are no parameters or data to send just send the empty packet */
622 if(params_to_send == 0 && data_to_send == 0) {
624 if (!send_smb(smbd_server_fd(),outbuf))
625 exit_server_cleanly("send_trans2_replies: send_smb failed.");
629 /* When sending params and data ensure that both are nicely aligned */
630 /* Only do this alignment when there is also data to send - else
631 can cause NT redirector problems. */
633 if (((params_to_send % 4) != 0) && (data_to_send != 0))
634 data_alignment_offset = 4 - (params_to_send % 4);
636 /* Space is bufsize minus Netbios over TCP header minus SMB header */
637 /* The alignment_offset is to align the param bytes on an even byte
638 boundary. NT 4.0 Beta needs this to work correctly. */
640 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
642 /* useable_space can never be more than max_send minus the alignment offset. */
644 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
646 while (params_to_send || data_to_send) {
647 /* Calculate whether we will totally or partially fill this packet */
649 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
651 /* We can never send more than useable_space */
653 * Note that 'useable_space' does not include the alignment offsets,
654 * but we must include the alignment offsets in the calculation of
655 * the length of the data we send over the wire, as the alignment offsets
656 * are sent here. Fix from Marc_Jacobsen@hp.com.
659 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
661 set_message(inbuf, outbuf, 10, total_sent_thistime, True);
663 /* Set total params and data to be sent */
664 SSVAL(outbuf,smb_tprcnt,paramsize);
665 SSVAL(outbuf,smb_tdrcnt,datasize);
667 /* Calculate how many parameters and data we can fit into
668 * this packet. Parameters get precedence
671 params_sent_thistime = MIN(params_to_send,useable_space);
672 data_sent_thistime = useable_space - params_sent_thistime;
673 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
675 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
677 /* smb_proff is the offset from the start of the SMB header to the
678 parameter bytes, however the first 4 bytes of outbuf are
679 the Netbios over TCP header. Thus use smb_base() to subtract
680 them from the calculation */
682 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
684 if(params_sent_thistime == 0)
685 SSVAL(outbuf,smb_prdisp,0);
687 /* Absolute displacement of param bytes sent in this packet */
688 SSVAL(outbuf,smb_prdisp,pp - params);
690 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
691 if(data_sent_thistime == 0) {
692 SSVAL(outbuf,smb_droff,0);
693 SSVAL(outbuf,smb_drdisp, 0);
695 /* The offset of the data bytes is the offset of the
696 parameter bytes plus the number of parameters being sent this time */
697 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
698 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
699 SSVAL(outbuf,smb_drdisp, pd - pdata);
702 /* Copy the param bytes into the packet */
704 if(params_sent_thistime)
705 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
707 /* Copy in the data bytes */
708 if(data_sent_thistime)
709 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
710 data_alignment_offset,pd,data_sent_thistime);
712 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
713 params_sent_thistime, data_sent_thistime, useable_space));
714 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
715 params_to_send, data_to_send, paramsize, datasize));
717 /* Send the packet */
719 if (!send_smb(smbd_server_fd(),outbuf))
720 exit_server_cleanly("send_trans2_replies: send_smb failed.");
722 pp += params_sent_thistime;
723 pd += data_sent_thistime;
725 params_to_send -= params_sent_thistime;
726 data_to_send -= data_sent_thistime;
729 if(params_to_send < 0 || data_to_send < 0) {
730 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
731 params_to_send, data_to_send));
739 /****************************************************************************
740 Reply to a TRANSACT2_OPEN.
741 ****************************************************************************/
743 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
744 char **pparams, int total_params, char **ppdata, int total_data,
745 unsigned int max_data_bytes)
747 char *params = *pparams;
748 char *pdata = *ppdata;
753 BOOL return_additional_info;
764 SMB_STRUCT_STAT sbuf;
767 struct ea_list *ea_list = NULL;
772 uint32 create_disposition;
773 uint32 create_options = 0;
776 * Ensure we have enough parameters to perform the operation.
779 if (total_params < 29) {
780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
783 flags = SVAL(params, 0);
784 deny_mode = SVAL(params, 2);
785 open_attr = SVAL(params,6);
786 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
787 if (oplock_request) {
788 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
792 return_additional_info = BITSETW(params,0);
793 open_sattr = SVAL(params, 4);
794 open_time = make_unix_date3(params+8);
796 open_ofun = SVAL(params,12);
797 open_size = IVAL(params,14);
801 return(ERROR_DOS(ERRSRV,ERRaccess));
804 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
805 if (!NT_STATUS_IS_OK(status)) {
806 return ERROR_NT(status);
809 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
810 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
811 (unsigned int)open_ofun, open_size));
813 /* XXXX we need to handle passed times, sattr and flags */
815 status = unix_convert(conn, fname, False, NULL, &sbuf);
816 if (!NT_STATUS_IS_OK(status)) {
817 return ERROR_NT(status);
820 status = check_name(conn, fname);
821 if (!NT_STATUS_IS_OK(status)) {
822 return ERROR_NT(status);
825 if (open_ofun == 0) {
826 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
829 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
834 return ERROR_DOS(ERRDOS, ERRbadaccess);
837 /* Any data in this call is an EA list. */
838 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
839 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
842 if (total_data != 4) {
843 if (total_data < 10) {
844 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
847 if (IVAL(pdata,0) > total_data) {
848 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
849 IVAL(pdata,0), (unsigned int)total_data));
850 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
853 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
858 } else if (IVAL(pdata,0) != 4) {
859 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
862 status = open_file_ntcreate(conn,fname,&sbuf,
871 if (!NT_STATUS_IS_OK(status)) {
872 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
873 /* We have re-scheduled this call. */
876 return ERROR_NT(status);
879 size = get_file_size(sbuf);
880 fattr = dos_mode(conn,fname,&sbuf);
881 mtime = sbuf.st_mtime;
884 close_file(fsp,ERROR_CLOSE);
885 return(ERROR_DOS(ERRDOS,ERRnoaccess));
888 /* Save the requested allocation size. */
889 /* Allocate space for the file if a size hint is supplied */
890 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
891 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
892 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
893 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
894 if (fsp->is_directory) {
895 close_file(fsp,ERROR_CLOSE);
896 /* Can't set allocation size on a directory. */
897 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
899 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
900 close_file(fsp,ERROR_CLOSE);
901 return ERROR_NT(NT_STATUS_DISK_FULL);
904 /* Adjust size here to return the right size in the reply.
905 Windows does it this way. */
906 size = fsp->initial_allocation_size;
908 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
912 if (ea_list && smb_action == FILE_WAS_CREATED) {
913 status = set_ea(conn, fsp, fname, ea_list);
914 if (!NT_STATUS_IS_OK(status)) {
915 close_file(fsp,ERROR_CLOSE);
916 return ERROR_NT(status);
920 /* Realloc the size of parameters and data we will return */
921 *pparams = (char *)SMB_REALLOC(*pparams, 30);
922 if(*pparams == NULL ) {
923 return ERROR_NT(NT_STATUS_NO_MEMORY);
927 SSVAL(params,0,fsp->fnum);
928 SSVAL(params,2,fattr);
929 srv_put_dos_date2(params,4, mtime);
930 SIVAL(params,8, (uint32)size);
931 SSVAL(params,12,deny_mode);
932 SSVAL(params,14,0); /* open_type - file or directory. */
933 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
935 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
936 smb_action |= EXTENDED_OPLOCK_GRANTED;
939 SSVAL(params,18,smb_action);
942 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
944 SIVAL(params,20,inode);
945 SSVAL(params,24,0); /* Padding. */
947 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
948 SIVAL(params, 26, ea_size);
950 SIVAL(params, 26, 0);
953 /* Send the required number of replies */
954 send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
959 /*********************************************************
960 Routine to check if a given string matches exactly.
961 as a special case a mask of "." does NOT match. That
962 is required for correct wildcard semantics
963 Case can be significant or not.
964 **********************************************************/
966 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
968 if (mask[0] == '.' && mask[1] == 0)
970 if (conn->case_sensitive)
971 return strcmp(str,mask)==0;
972 if (StrCaseCmp(str,mask) != 0) {
975 if (dptr_has_wild(conn->dirptr)) {
981 /****************************************************************************
982 Return the filetype for UNIX extensions.
983 ****************************************************************************/
985 static uint32 unix_filetype(mode_t mode)
988 return UNIX_TYPE_FILE;
989 else if(S_ISDIR(mode))
990 return UNIX_TYPE_DIR;
992 else if(S_ISLNK(mode))
993 return UNIX_TYPE_SYMLINK;
996 else if(S_ISCHR(mode))
997 return UNIX_TYPE_CHARDEV;
1000 else if(S_ISBLK(mode))
1001 return UNIX_TYPE_BLKDEV;
1004 else if(S_ISFIFO(mode))
1005 return UNIX_TYPE_FIFO;
1008 else if(S_ISSOCK(mode))
1009 return UNIX_TYPE_SOCKET;
1012 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1013 return UNIX_TYPE_UNKNOWN;
1016 /****************************************************************************
1017 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1018 ****************************************************************************/
1020 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1022 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1023 SMB_STRUCT_STAT *psbuf,
1025 enum perm_type ptype,
1030 if (perms == SMB_MODE_NO_CHANGE) {
1031 if (!VALID_STAT(*psbuf)) {
1032 return NT_STATUS_INVALID_PARAMETER;
1034 *ret_perms = psbuf->st_mode;
1035 return NT_STATUS_OK;
1039 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1040 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1041 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1042 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1043 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1044 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1045 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1046 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1047 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1049 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1052 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1055 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1060 /* Apply mode mask */
1061 ret &= lp_create_mask(SNUM(conn));
1062 /* Add in force bits */
1063 ret |= lp_force_create_mode(SNUM(conn));
1066 ret &= lp_dir_mask(SNUM(conn));
1067 /* Add in force bits */
1068 ret |= lp_force_dir_mode(SNUM(conn));
1070 case PERM_EXISTING_FILE:
1071 /* Apply mode mask */
1072 ret &= lp_security_mask(SNUM(conn));
1073 /* Add in force bits */
1074 ret |= lp_force_security_mode(SNUM(conn));
1076 case PERM_EXISTING_DIR:
1077 /* Apply mode mask */
1078 ret &= lp_dir_security_mask(SNUM(conn));
1079 /* Add in force bits */
1080 ret |= lp_force_dir_security_mode(SNUM(conn));
1085 return NT_STATUS_OK;
1088 /****************************************************************************
1089 Get a level dependent lanman2 dir entry.
1090 ****************************************************************************/
1092 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1093 void *inbuf, char *outbuf,
1094 char *path_mask,uint32 dirtype,int info_level,
1095 int requires_resume_key,
1096 BOOL dont_descend,char **ppdata,
1097 char *base_data, int space_remaining,
1098 BOOL *out_of_space, BOOL *got_exact_match,
1099 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1103 SMB_STRUCT_STAT sbuf;
1107 char *p, *q, *pdata = *ppdata;
1111 SMB_OFF_T file_size = 0;
1112 SMB_BIG_UINT allocation_size = 0;
1114 struct timespec mdate_ts, adate_ts, create_date_ts;
1115 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1117 char *last_entry_ptr;
1119 uint32 nt_extmode; /* Used for NT connections instead of mode */
1120 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1121 BOOL check_mangled_names = lp_manglednames(conn->params);
1124 *out_of_space = False;
1125 *got_exact_match = False;
1127 ZERO_STRUCT(mdate_ts);
1128 ZERO_STRUCT(adate_ts);
1129 ZERO_STRUCT(create_date_ts);
1134 p = strrchr_m(path_mask,'/');
1137 pstrcpy(mask,"*.*");
1141 pstrcpy(mask, path_mask);
1146 BOOL ms_dfs_link = False;
1148 /* Needed if we run out of space */
1149 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1150 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1153 * Due to bugs in NT client redirectors we are not using
1154 * resume keys any more - set them to zero.
1155 * Check out the related comments in findfirst/findnext.
1161 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1162 (long)conn->dirptr,curr_dirpos));
1169 * fname may get mangled, dname is never mangled.
1170 * Whenever we're accessing the filesystem we use
1171 * pathreal which is composed from dname.
1174 pstrcpy(fname,dname);
1176 /* This will mangle fname if it's an illegal name. */
1177 mangle_map(fname,False,True,conn->params);
1179 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1180 got_match = mask_match(fname, mask, conn->case_sensitive);
1183 if(!got_match && check_mangled_names &&
1184 !mangle_is_8_3(fname, False, conn->params)) {
1185 pstring mangled_name;
1188 * It turns out that NT matches wildcards against
1189 * both long *and* short names. This may explain some
1190 * of the wildcard wierdness from old DOS clients
1191 * that some people have been seeing.... JRA.
1194 pstrcpy(mangled_name, fname);
1196 /* Force the mangling into 8.3. */
1197 mangle_map( mangled_name, True, False, conn->params);
1198 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1199 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1204 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1205 if (dont_descend && !isdots) {
1209 pstrcpy(pathreal,conn->dirpath);
1211 pstrcat(pathreal,"/");
1213 pstrcat(pathreal,dname);
1215 if (INFO_LEVEL_IS_UNIX(info_level)) {
1216 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1217 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1218 pathreal,strerror(errno)));
1221 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1222 pstring link_target;
1224 /* Needed to show the msdfs symlinks as
1227 if(lp_host_msdfs() &&
1228 lp_msdfs_root(SNUM(conn)) &&
1229 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1230 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1233 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1237 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1238 pathreal,strerror(errno)));
1244 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1246 mode = dos_mode(conn,pathreal,&sbuf);
1249 if (!dir_check_ftype(conn,mode,dirtype)) {
1250 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1254 if (!(mode & aDIR)) {
1255 file_size = get_file_size(sbuf);
1257 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1259 mdate_ts = get_mtimespec(&sbuf);
1260 adate_ts = get_atimespec(&sbuf);
1261 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1263 if (lp_dos_filetime_resolution(SNUM(conn))) {
1264 dos_filetime_timespec(&create_date_ts);
1265 dos_filetime_timespec(&mdate_ts);
1266 dos_filetime_timespec(&adate_ts);
1269 create_date = convert_timespec_to_time_t(create_date_ts);
1270 mdate = convert_timespec_to_time_t(mdate_ts);
1271 adate = convert_timespec_to_time_t(adate_ts);
1273 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1277 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1284 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1286 switch (info_level) {
1287 case SMB_FIND_INFO_STANDARD:
1288 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1289 if(requires_resume_key) {
1293 srv_put_dos_date2(p,0,create_date);
1294 srv_put_dos_date2(p,4,adate);
1295 srv_put_dos_date2(p,8,mdate);
1296 SIVAL(p,12,(uint32)file_size);
1297 SIVAL(p,16,(uint32)allocation_size);
1301 p += align_string(outbuf, p, 0);
1302 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1303 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1305 SCVAL(nameptr, -1, len - 2);
1307 SCVAL(nameptr, -1, 0);
1311 SCVAL(nameptr, -1, len - 1);
1313 SCVAL(nameptr, -1, 0);
1319 case SMB_FIND_EA_SIZE:
1320 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1321 if(requires_resume_key) {
1325 srv_put_dos_date2(p,0,create_date);
1326 srv_put_dos_date2(p,4,adate);
1327 srv_put_dos_date2(p,8,mdate);
1328 SIVAL(p,12,(uint32)file_size);
1329 SIVAL(p,16,(uint32)allocation_size);
1332 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1333 SIVAL(p,22,ea_size); /* Extended attributes */
1337 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1338 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1351 SCVAL(nameptr,0,len);
1353 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1356 case SMB_FIND_EA_LIST:
1358 struct ea_list *file_list = NULL;
1361 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1365 if(requires_resume_key) {
1369 srv_put_dos_date2(p,0,create_date);
1370 srv_put_dos_date2(p,4,adate);
1371 srv_put_dos_date2(p,8,mdate);
1372 SIVAL(p,12,(uint32)file_size);
1373 SIVAL(p,16,(uint32)allocation_size);
1375 p += 22; /* p now points to the EA area. */
1377 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1378 name_list = ea_list_union(name_list, file_list, &ea_len);
1380 /* We need to determine if this entry will fit in the space available. */
1381 /* Max string size is 255 bytes. */
1382 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1383 /* Move the dirptr back to prev_dirpos */
1384 dptr_SeekDir(conn->dirptr, prev_dirpos);
1385 *out_of_space = True;
1386 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1387 return False; /* Not finished - just out of space */
1390 /* Push the ea_data followed by the name. */
1391 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1393 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1394 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1407 SCVAL(nameptr,0,len);
1409 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1413 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1414 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1415 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1417 SIVAL(p,0,reskey); p += 4;
1418 put_long_date_timespec(p,create_date_ts); p += 8;
1419 put_long_date_timespec(p,adate_ts); p += 8;
1420 put_long_date_timespec(p,mdate_ts); p += 8;
1421 put_long_date_timespec(p,mdate_ts); p += 8;
1422 SOFF_T(p,0,file_size); p += 8;
1423 SOFF_T(p,0,allocation_size); p += 8;
1424 SIVAL(p,0,nt_extmode); p += 4;
1425 q = p; p += 4; /* q is placeholder for name length. */
1427 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1428 SIVAL(p,0,ea_size); /* Extended attributes */
1431 /* Clear the short name buffer. This is
1432 * IMPORTANT as not doing so will trigger
1433 * a Win2k client bug. JRA.
1435 if (!was_8_3 && check_mangled_names) {
1436 pstring mangled_name;
1437 pstrcpy(mangled_name, fname);
1438 mangle_map(mangled_name,True,True,
1440 mangled_name[12] = 0;
1441 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1443 memset(p + 2 + len,'\0',24 - len);
1450 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1453 SIVAL(p,0,0); /* Ensure any padding is null. */
1454 len = PTR_DIFF(p, pdata);
1455 len = (len + 3) & ~3;
1460 case SMB_FIND_FILE_DIRECTORY_INFO:
1461 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1463 SIVAL(p,0,reskey); p += 4;
1464 put_long_date_timespec(p,create_date_ts); p += 8;
1465 put_long_date_timespec(p,adate_ts); p += 8;
1466 put_long_date_timespec(p,mdate_ts); p += 8;
1467 put_long_date_timespec(p,mdate_ts); p += 8;
1468 SOFF_T(p,0,file_size); p += 8;
1469 SOFF_T(p,0,allocation_size); p += 8;
1470 SIVAL(p,0,nt_extmode); p += 4;
1471 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1474 SIVAL(p,0,0); /* Ensure any padding is null. */
1475 len = PTR_DIFF(p, pdata);
1476 len = (len + 3) & ~3;
1481 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1482 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1484 SIVAL(p,0,reskey); p += 4;
1485 put_long_date_timespec(p,create_date_ts); p += 8;
1486 put_long_date_timespec(p,adate_ts); p += 8;
1487 put_long_date_timespec(p,mdate_ts); p += 8;
1488 put_long_date_timespec(p,mdate_ts); p += 8;
1489 SOFF_T(p,0,file_size); p += 8;
1490 SOFF_T(p,0,allocation_size); p += 8;
1491 SIVAL(p,0,nt_extmode); p += 4;
1492 q = p; p += 4; /* q is placeholder for name length. */
1494 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1495 SIVAL(p,0,ea_size); /* Extended attributes */
1498 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1502 SIVAL(p,0,0); /* Ensure any padding is null. */
1503 len = PTR_DIFF(p, pdata);
1504 len = (len + 3) & ~3;
1509 case SMB_FIND_FILE_NAMES_INFO:
1510 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1512 SIVAL(p,0,reskey); p += 4;
1514 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1515 acl on a dir (tridge) */
1516 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1519 SIVAL(p,0,0); /* Ensure any padding is null. */
1520 len = PTR_DIFF(p, pdata);
1521 len = (len + 3) & ~3;
1526 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1527 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1529 SIVAL(p,0,reskey); p += 4;
1530 put_long_date_timespec(p,create_date_ts); p += 8;
1531 put_long_date_timespec(p,adate_ts); p += 8;
1532 put_long_date_timespec(p,mdate_ts); p += 8;
1533 put_long_date_timespec(p,mdate_ts); p += 8;
1534 SOFF_T(p,0,file_size); p += 8;
1535 SOFF_T(p,0,allocation_size); p += 8;
1536 SIVAL(p,0,nt_extmode); p += 4;
1537 q = p; p += 4; /* q is placeholder for name length. */
1539 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1540 SIVAL(p,0,ea_size); /* Extended attributes */
1543 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1544 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1545 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1546 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1549 SIVAL(p,0,0); /* Ensure any padding is null. */
1550 len = PTR_DIFF(p, pdata);
1551 len = (len + 3) & ~3;
1556 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1557 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1558 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1560 SIVAL(p,0,reskey); p += 4;
1561 put_long_date_timespec(p,create_date_ts); p += 8;
1562 put_long_date_timespec(p,adate_ts); p += 8;
1563 put_long_date_timespec(p,mdate_ts); p += 8;
1564 put_long_date_timespec(p,mdate_ts); p += 8;
1565 SOFF_T(p,0,file_size); p += 8;
1566 SOFF_T(p,0,allocation_size); p += 8;
1567 SIVAL(p,0,nt_extmode); p += 4;
1568 q = p; p += 4; /* q is placeholder for name length */
1570 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1571 SIVAL(p,0,ea_size); /* Extended attributes */
1574 /* Clear the short name buffer. This is
1575 * IMPORTANT as not doing so will trigger
1576 * a Win2k client bug. JRA.
1578 if (!was_8_3 && check_mangled_names) {
1579 pstring mangled_name;
1580 pstrcpy(mangled_name, fname);
1581 mangle_map(mangled_name,True,True,
1583 mangled_name[12] = 0;
1584 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1587 memset(p + 2 + len,'\0',24 - len);
1594 SSVAL(p,0,0); p += 2; /* Reserved ? */
1595 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1596 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1597 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1600 SIVAL(p,0,0); /* Ensure any padding is null. */
1601 len = PTR_DIFF(p, pdata);
1602 len = (len + 3) & ~3;
1607 /* CIFS UNIX Extension. */
1609 case SMB_FIND_FILE_UNIX:
1610 case SMB_FIND_FILE_UNIX_INFO2:
1612 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1614 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1616 if (info_level == SMB_FIND_FILE_UNIX) {
1617 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1618 p = store_file_unix_basic(conn, p,
1620 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1622 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1623 p = store_file_unix_basic_info2(conn, p,
1627 len = srvstr_push(outbuf, p, fname, -1, 0);
1628 SIVAL(nameptr, 0, len);
1632 SIVAL(p,0,0); /* Ensure any padding is null. */
1634 len = PTR_DIFF(p, pdata);
1635 len = (len + 3) & ~3;
1636 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1638 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1647 if (PTR_DIFF(p,pdata) > space_remaining) {
1648 /* Move the dirptr back to prev_dirpos */
1649 dptr_SeekDir(conn->dirptr, prev_dirpos);
1650 *out_of_space = True;
1651 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1652 return False; /* Not finished - just out of space */
1655 /* Setup the last entry pointer, as an offset from base_data */
1656 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1657 /* Advance the data pointer to the next slot */
1663 /****************************************************************************
1664 Reply to a TRANS2_FINDFIRST.
1665 ****************************************************************************/
1667 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1668 char **pparams, int total_params, char **ppdata, int total_data,
1669 unsigned int max_data_bytes)
1671 /* We must be careful here that we don't return more than the
1672 allowed number of data bytes. If this means returning fewer than
1673 maxentries then so be it. We assume that the redirector has
1674 enough room for the fixed number of parameter bytes it has
1676 char *params = *pparams;
1677 char *pdata = *ppdata;
1680 uint16 findfirst_flags;
1681 BOOL close_after_first;
1683 BOOL requires_resume_key;
1688 int last_entry_off=0;
1692 BOOL finished = False;
1693 BOOL dont_descend = False;
1694 BOOL out_of_space = False;
1695 int space_remaining;
1696 BOOL mask_contains_wcard = False;
1697 SMB_STRUCT_STAT sbuf;
1698 TALLOC_CTX *ea_ctx = NULL;
1699 struct ea_list *ea_list = NULL;
1700 NTSTATUS ntstatus = NT_STATUS_OK;
1702 if (total_params < 13) {
1703 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1706 dirtype = SVAL(params,0);
1707 maxentries = SVAL(params,2);
1708 findfirst_flags = SVAL(params,4);
1709 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1710 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1711 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1712 info_level = SVAL(params,6);
1714 *directory = *mask = 0;
1716 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1717 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1718 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1719 info_level, max_data_bytes));
1722 /* W2K3 seems to treat zero as 1. */
1726 switch (info_level) {
1727 case SMB_FIND_INFO_STANDARD:
1728 case SMB_FIND_EA_SIZE:
1729 case SMB_FIND_EA_LIST:
1730 case SMB_FIND_FILE_DIRECTORY_INFO:
1731 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1732 case SMB_FIND_FILE_NAMES_INFO:
1733 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1734 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1735 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1737 case SMB_FIND_FILE_UNIX:
1738 case SMB_FIND_FILE_UNIX_INFO2:
1739 if (!lp_unix_extensions()) {
1740 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1744 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1747 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1748 if (!NT_STATUS_IS_OK(ntstatus)) {
1749 return ERROR_NT(ntstatus);
1752 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1753 if (!NT_STATUS_IS_OK(ntstatus)) {
1754 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1755 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1757 return ERROR_NT(ntstatus);
1760 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1761 if (!NT_STATUS_IS_OK(ntstatus)) {
1762 return ERROR_NT(ntstatus);
1764 ntstatus = check_name(conn, directory);
1765 if (!NT_STATUS_IS_OK(ntstatus)) {
1766 return ERROR_NT(ntstatus);
1769 p = strrchr_m(directory,'/');
1771 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1772 if((directory[0] == '.') && (directory[1] == '\0')) {
1774 mask_contains_wcard = True;
1776 pstrcpy(mask,directory);
1778 pstrcpy(directory,"./");
1784 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1786 if (info_level == SMB_FIND_EA_LIST) {
1789 if (total_data < 4) {
1790 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1793 ea_size = IVAL(pdata,0);
1794 if (ea_size != total_data) {
1795 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1796 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1797 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1800 if (!lp_ea_support(SNUM(conn))) {
1801 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1804 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1805 return ERROR_NT(NT_STATUS_NO_MEMORY);
1808 /* Pull out the list of names. */
1809 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1811 talloc_destroy(ea_ctx);
1812 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1816 *ppdata = (char *)SMB_REALLOC(
1817 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1818 if(*ppdata == NULL ) {
1819 talloc_destroy(ea_ctx);
1820 return ERROR_NT(NT_STATUS_NO_MEMORY);
1824 /* Realloc the params space */
1825 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1826 if (*pparams == NULL) {
1827 talloc_destroy(ea_ctx);
1828 return ERROR_NT(NT_STATUS_NO_MEMORY);
1832 /* Save the wildcard match and attribs we are using on this directory -
1833 needed as lanman2 assumes these are being saved between calls */
1835 ntstatus = dptr_create(conn,
1839 SVAL(inbuf,smb_pid),
1841 mask_contains_wcard,
1845 if (!NT_STATUS_IS_OK(ntstatus)) {
1846 talloc_destroy(ea_ctx);
1847 return ERROR_NT(ntstatus);
1850 dptr_num = dptr_dnum(conn->dirptr);
1851 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1853 /* We don't need to check for VOL here as this is returned by
1854 a different TRANS2 call. */
1856 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1857 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1858 dont_descend = True;
1861 space_remaining = max_data_bytes;
1862 out_of_space = False;
1864 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1865 BOOL got_exact_match = False;
1867 /* this is a heuristic to avoid seeking the dirptr except when
1868 absolutely necessary. It allows for a filename of about 40 chars */
1869 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1870 out_of_space = True;
1873 finished = !get_lanman2_dir_entry(conn,
1875 mask,dirtype,info_level,
1876 requires_resume_key,dont_descend,
1877 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1878 &last_entry_off, ea_list, ea_ctx);
1881 if (finished && out_of_space)
1884 if (!finished && !out_of_space)
1888 * As an optimisation if we know we aren't looking
1889 * for a wildcard name (ie. the name matches the wildcard exactly)
1890 * then we can finish on any (first) match.
1891 * This speeds up large directory searches. JRA.
1897 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1900 talloc_destroy(ea_ctx);
1902 /* Check if we can close the dirptr */
1903 if(close_after_first || (finished && close_if_end)) {
1904 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1905 dptr_close(&dptr_num);
1909 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1910 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1911 * the protocol level is less than NT1. Tested with smbclient. JRA.
1912 * This should fix the OS/2 client bug #2335.
1915 if(numentries == 0) {
1916 dptr_close(&dptr_num);
1917 if (Protocol < PROTOCOL_NT1) {
1918 return ERROR_DOS(ERRDOS,ERRnofiles);
1920 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1924 /* At this point pdata points to numentries directory entries. */
1926 /* Set up the return parameter block */
1927 SSVAL(params,0,dptr_num);
1928 SSVAL(params,2,numentries);
1929 SSVAL(params,4,finished);
1930 SSVAL(params,6,0); /* Never an EA error */
1931 SSVAL(params,8,last_entry_off);
1933 send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1935 if ((! *directory) && dptr_path(dptr_num))
1936 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1938 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1939 smb_fn_name(CVAL(inbuf,smb_com)),
1940 mask, directory, dirtype, numentries ) );
1943 * Force a name mangle here to ensure that the
1944 * mask as an 8.3 name is top of the mangled cache.
1945 * The reasons for this are subtle. Don't remove
1946 * this code unless you know what you are doing
1947 * (see PR#13758). JRA.
1950 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1951 mangle_map(mask, True, True, conn->params);
1956 /****************************************************************************
1957 Reply to a TRANS2_FINDNEXT.
1958 ****************************************************************************/
1960 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1961 char **pparams, int total_params, char **ppdata, int total_data,
1962 unsigned int max_data_bytes)
1964 /* We must be careful here that we don't return more than the
1965 allowed number of data bytes. If this means returning fewer than
1966 maxentries then so be it. We assume that the redirector has
1967 enough room for the fixed number of parameter bytes it has
1969 char *params = *pparams;
1970 char *pdata = *ppdata;
1975 uint16 findnext_flags;
1976 BOOL close_after_request;
1978 BOOL requires_resume_key;
1980 BOOL mask_contains_wcard = False;
1981 pstring resume_name;
1987 int i, last_entry_off=0;
1988 BOOL finished = False;
1989 BOOL dont_descend = False;
1990 BOOL out_of_space = False;
1991 int space_remaining;
1992 TALLOC_CTX *ea_ctx = NULL;
1993 struct ea_list *ea_list = NULL;
1994 NTSTATUS ntstatus = NT_STATUS_OK;
1996 if (total_params < 13) {
1997 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2000 dptr_num = SVAL(params,0);
2001 maxentries = SVAL(params,2);
2002 info_level = SVAL(params,4);
2003 resume_key = IVAL(params,6);
2004 findnext_flags = SVAL(params,10);
2005 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2006 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2007 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2008 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2010 *mask = *directory = *resume_name = 0;
2012 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2013 if (!NT_STATUS_IS_OK(ntstatus)) {
2014 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2015 complain (it thinks we're asking for the directory above the shared
2016 path or an invalid name). Catch this as the resume name is only compared, never used in
2017 a file access. JRA. */
2018 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2019 pstrcpy(resume_name, "..");
2020 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2021 pstrcpy(resume_name, ".");
2023 return ERROR_NT(ntstatus);
2027 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2028 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2029 resume_key = %d resume name = %s continue=%d level = %d\n",
2030 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2031 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2034 /* W2K3 seems to treat zero as 1. */
2038 switch (info_level) {
2039 case SMB_FIND_INFO_STANDARD:
2040 case SMB_FIND_EA_SIZE:
2041 case SMB_FIND_EA_LIST:
2042 case SMB_FIND_FILE_DIRECTORY_INFO:
2043 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2044 case SMB_FIND_FILE_NAMES_INFO:
2045 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2046 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2047 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2049 case SMB_FIND_FILE_UNIX:
2050 case SMB_FIND_FILE_UNIX_INFO2:
2051 if (!lp_unix_extensions()) {
2052 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2056 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2059 if (info_level == SMB_FIND_EA_LIST) {
2062 if (total_data < 4) {
2063 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2066 ea_size = IVAL(pdata,0);
2067 if (ea_size != total_data) {
2068 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2069 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2070 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2073 if (!lp_ea_support(SNUM(conn))) {
2074 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2077 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2078 return ERROR_NT(NT_STATUS_NO_MEMORY);
2081 /* Pull out the list of names. */
2082 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2084 talloc_destroy(ea_ctx);
2085 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2089 *ppdata = (char *)SMB_REALLOC(
2090 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2091 if(*ppdata == NULL) {
2092 talloc_destroy(ea_ctx);
2093 return ERROR_NT(NT_STATUS_NO_MEMORY);
2098 /* Realloc the params space */
2099 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2100 if(*pparams == NULL ) {
2101 talloc_destroy(ea_ctx);
2102 return ERROR_NT(NT_STATUS_NO_MEMORY);
2107 /* Check that the dptr is valid */
2108 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2109 talloc_destroy(ea_ctx);
2110 return ERROR_DOS(ERRDOS,ERRnofiles);
2113 string_set(&conn->dirpath,dptr_path(dptr_num));
2115 /* Get the wildcard mask from the dptr */
2116 if((p = dptr_wcard(dptr_num))== NULL) {
2117 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2118 talloc_destroy(ea_ctx);
2119 return ERROR_DOS(ERRDOS,ERRnofiles);
2123 pstrcpy(directory,conn->dirpath);
2125 /* Get the attr mask from the dptr */
2126 dirtype = dptr_attr(dptr_num);
2128 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2129 dptr_num, mask, dirtype,
2131 dptr_TellDir(conn->dirptr)));
2133 /* We don't need to check for VOL here as this is returned by
2134 a different TRANS2 call. */
2136 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2137 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2138 dont_descend = True;
2141 space_remaining = max_data_bytes;
2142 out_of_space = False;
2145 * Seek to the correct position. We no longer use the resume key but
2146 * depend on the last file name instead.
2149 if(*resume_name && !continue_bit) {
2152 long current_pos = 0;
2154 * Remember, mangle_map is called by
2155 * get_lanman2_dir_entry(), so the resume name
2156 * could be mangled. Ensure we check the unmangled name.
2159 if (mangle_is_mangled(resume_name, conn->params)) {
2160 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2165 * Fix for NT redirector problem triggered by resume key indexes
2166 * changing between directory scans. We now return a resume key of 0
2167 * and instead look for the filename to continue from (also given
2168 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2169 * findfirst/findnext (as is usual) then the directory pointer
2170 * should already be at the correct place.
2173 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2174 } /* end if resume_name && !continue_bit */
2176 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2177 BOOL got_exact_match = False;
2179 /* this is a heuristic to avoid seeking the dirptr except when
2180 absolutely necessary. It allows for a filename of about 40 chars */
2181 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2182 out_of_space = True;
2185 finished = !get_lanman2_dir_entry(conn,
2187 mask,dirtype,info_level,
2188 requires_resume_key,dont_descend,
2189 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2190 &last_entry_off, ea_list, ea_ctx);
2193 if (finished && out_of_space)
2196 if (!finished && !out_of_space)
2200 * As an optimisation if we know we aren't looking
2201 * for a wildcard name (ie. the name matches the wildcard exactly)
2202 * then we can finish on any (first) match.
2203 * This speeds up large directory searches. JRA.
2209 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2212 talloc_destroy(ea_ctx);
2214 /* Check if we can close the dirptr */
2215 if(close_after_request || (finished && close_if_end)) {
2216 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2217 dptr_close(&dptr_num); /* This frees up the saved mask */
2220 /* Set up the return parameter block */
2221 SSVAL(params,0,numentries);
2222 SSVAL(params,2,finished);
2223 SSVAL(params,4,0); /* Never an EA error */
2224 SSVAL(params,6,last_entry_off);
2226 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2228 if ((! *directory) && dptr_path(dptr_num))
2229 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2231 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2232 smb_fn_name(CVAL(inbuf,smb_com)),
2233 mask, directory, dirtype, numentries ) );
2238 /****************************************************************************
2239 Reply to a TRANS2_QFSINFO (query filesystem info).
2240 ****************************************************************************/
2242 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2243 char **pparams, int total_params, char **ppdata, int total_data,
2244 unsigned int max_data_bytes)
2247 char *params = *pparams;
2251 const char *vname = volume_label(SNUM(conn));
2252 int snum = SNUM(conn);
2253 char *fstype = lp_fstype(SNUM(conn));
2256 if (total_params < 2) {
2257 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2260 info_level = SVAL(params,0);
2262 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2264 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2265 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2266 return ERROR_DOS(ERRSRV,ERRinvdevice);
2269 *ppdata = (char *)SMB_REALLOC(
2270 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2271 if (*ppdata == NULL ) {
2272 return ERROR_NT(NT_STATUS_NO_MEMORY);
2276 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2278 switch (info_level) {
2279 case SMB_INFO_ALLOCATION:
2281 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2283 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2284 return(UNIXERROR(ERRHRD,ERRgeneral));
2287 block_size = lp_block_size(snum);
2288 if (bsize < block_size) {
2289 SMB_BIG_UINT factor = block_size/bsize;
2294 if (bsize > block_size) {
2295 SMB_BIG_UINT factor = bsize/block_size;
2300 bytes_per_sector = 512;
2301 sectors_per_unit = bsize/bytes_per_sector;
2303 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2304 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2305 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2307 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2308 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2309 SIVAL(pdata,l1_cUnit,dsize);
2310 SIVAL(pdata,l1_cUnitAvail,dfree);
2311 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2315 case SMB_INFO_VOLUME:
2316 /* Return volume name */
2318 * Add volume serial number - hash of a combination of
2319 * the called hostname and the service name.
2321 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2323 * Win2k3 and previous mess this up by sending a name length
2324 * one byte short. I believe only older clients (OS/2 Win9x) use
2325 * this call so try fixing this by adding a terminating null to
2326 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2328 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2329 SCVAL(pdata,l2_vol_cch,len);
2330 data_len = l2_vol_szVolLabel + len;
2331 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2332 (unsigned)st.st_ctime, len, vname));
2335 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2336 case SMB_FS_ATTRIBUTE_INFORMATION:
2339 #if defined(HAVE_SYS_QUOTAS)
2340 quota_flag = FILE_VOLUME_QUOTAS;
2343 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2344 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2345 quota_flag); /* FS ATTRIBUTES */
2347 SIVAL(pdata,4,255); /* Max filename component length */
2348 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2349 and will think we can't do long filenames */
2350 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2352 data_len = 12 + len;
2355 case SMB_QUERY_FS_LABEL_INFO:
2356 case SMB_FS_LABEL_INFORMATION:
2357 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2362 case SMB_QUERY_FS_VOLUME_INFO:
2363 case SMB_FS_VOLUME_INFORMATION:
2366 * Add volume serial number - hash of a combination of
2367 * the called hostname and the service name.
2369 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2370 (str_checksum(get_local_machine_name())<<16));
2372 /* Max label len is 32 characters. */
2373 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2374 SIVAL(pdata,12,len);
2377 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2378 (int)strlen(vname),vname, lp_servicename(snum)));
2381 case SMB_QUERY_FS_SIZE_INFO:
2382 case SMB_FS_SIZE_INFORMATION:
2384 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2386 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2387 return(UNIXERROR(ERRHRD,ERRgeneral));
2389 block_size = lp_block_size(snum);
2390 if (bsize < block_size) {
2391 SMB_BIG_UINT factor = block_size/bsize;
2396 if (bsize > block_size) {
2397 SMB_BIG_UINT factor = bsize/block_size;
2402 bytes_per_sector = 512;
2403 sectors_per_unit = bsize/bytes_per_sector;
2404 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2405 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2406 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2407 SBIG_UINT(pdata,0,dsize);
2408 SBIG_UINT(pdata,8,dfree);
2409 SIVAL(pdata,16,sectors_per_unit);
2410 SIVAL(pdata,20,bytes_per_sector);
2414 case SMB_FS_FULL_SIZE_INFORMATION:
2416 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2418 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2419 return(UNIXERROR(ERRHRD,ERRgeneral));
2421 block_size = lp_block_size(snum);
2422 if (bsize < block_size) {
2423 SMB_BIG_UINT factor = block_size/bsize;
2428 if (bsize > block_size) {
2429 SMB_BIG_UINT factor = bsize/block_size;
2434 bytes_per_sector = 512;
2435 sectors_per_unit = bsize/bytes_per_sector;
2436 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2437 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2438 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2439 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2440 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2441 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2442 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2443 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2447 case SMB_QUERY_FS_DEVICE_INFO:
2448 case SMB_FS_DEVICE_INFORMATION:
2450 SIVAL(pdata,0,0); /* dev type */
2451 SIVAL(pdata,4,0); /* characteristics */
2454 #ifdef HAVE_SYS_QUOTAS
2455 case SMB_FS_QUOTA_INFORMATION:
2457 * what we have to send --metze:
2459 * Unknown1: 24 NULL bytes
2460 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2461 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2462 * Quota Flags: 2 byte :
2463 * Unknown3: 6 NULL bytes
2467 * details for Quota Flags:
2469 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2470 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2471 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2472 * 0x0001 Enable Quotas: enable quota for this fs
2476 /* we need to fake up a fsp here,
2477 * because its not send in this call
2480 SMB_NTQUOTA_STRUCT quotas;
2483 ZERO_STRUCT(quotas);
2489 if (current_user.ut.uid != 0) {
2490 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2491 lp_servicename(SNUM(conn)),conn->user));
2492 return ERROR_DOS(ERRDOS,ERRnoaccess);
2495 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2496 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2497 return ERROR_DOS(ERRSRV,ERRerror);
2502 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2504 /* Unknown1 24 NULL bytes*/
2505 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2506 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2507 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2509 /* Default Soft Quota 8 bytes */
2510 SBIG_UINT(pdata,24,quotas.softlim);
2512 /* Default Hard Quota 8 bytes */
2513 SBIG_UINT(pdata,32,quotas.hardlim);
2515 /* Quota flag 2 bytes */
2516 SSVAL(pdata,40,quotas.qflags);
2518 /* Unknown3 6 NULL bytes */
2524 #endif /* HAVE_SYS_QUOTAS */
2525 case SMB_FS_OBJECTID_INFORMATION:
2530 * Query the version and capabilities of the CIFS UNIX extensions
2534 case SMB_QUERY_CIFS_UNIX_INFO:
2535 if (!lp_unix_extensions()) {
2536 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2539 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2540 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2541 /* We have POSIX ACLs, pathname and locking capability. */
2542 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2543 CIFS_UNIX_POSIX_ACLS_CAP|
2544 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2545 CIFS_UNIX_FCNTL_LOCKS_CAP|
2546 CIFS_UNIX_EXTATTR_CAP|
2547 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2550 case SMB_QUERY_POSIX_FS_INFO:
2553 vfs_statvfs_struct svfs;
2555 if (!lp_unix_extensions()) {
2556 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2559 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2563 SIVAL(pdata,0,svfs.OptimalTransferSize);
2564 SIVAL(pdata,4,svfs.BlockSize);
2565 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2566 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2567 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2568 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2569 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2570 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2571 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2573 } else if (rc == EOPNOTSUPP) {
2574 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2575 #endif /* EOPNOTSUPP */
2577 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2578 return ERROR_DOS(ERRSRV,ERRerror);
2583 case SMB_QUERY_POSIX_WHOAMI:
2589 if (!lp_unix_extensions()) {
2590 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2593 if (max_data_bytes < 40) {
2594 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2597 /* We ARE guest if global_sid_Builtin_Guests is
2598 * in our list of SIDs.
2600 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2601 current_user.nt_user_token)) {
2602 flags |= SMB_WHOAMI_GUEST;
2605 /* We are NOT guest if global_sid_Authenticated_Users
2606 * is in our list of SIDs.
2608 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2609 current_user.nt_user_token)) {
2610 flags &= ~SMB_WHOAMI_GUEST;
2613 /* NOTE: 8 bytes for UID/GID, irrespective of native
2614 * platform size. This matches
2615 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2617 data_len = 4 /* flags */
2624 + 4 /* pad/reserved */
2625 + (current_user.ut.ngroups * 8)
2627 + (current_user.nt_user_token->num_sids *
2631 SIVAL(pdata, 0, flags);
2632 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2633 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2634 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2637 if (data_len >= max_data_bytes) {
2638 /* Potential overflow, skip the GIDs and SIDs. */
2640 SIVAL(pdata, 24, 0); /* num_groups */
2641 SIVAL(pdata, 28, 0); /* num_sids */
2642 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2643 SIVAL(pdata, 36, 0); /* reserved */
2649 SIVAL(pdata, 24, current_user.ut.ngroups);
2651 current_user.nt_user_token->num_sids);
2653 /* We walk the SID list twice, but this call is fairly
2654 * infrequent, and I don't expect that it's performance
2655 * sensitive -- jpeach
2657 for (i = 0, sid_bytes = 0;
2658 i < current_user.nt_user_token->num_sids; ++i) {
2660 sid_size(¤t_user.nt_user_token->user_sids[i]);
2663 /* SID list byte count */
2664 SIVAL(pdata, 32, sid_bytes);
2666 /* 4 bytes pad/reserved - must be zero */
2667 SIVAL(pdata, 36, 0);
2671 for (i = 0; i < current_user.ut.ngroups; ++i) {
2672 SBIG_UINT(pdata, data_len,
2673 (SMB_BIG_UINT)current_user.ut.groups[i]);
2679 i < current_user.nt_user_token->num_sids; ++i) {
2681 sid_size(¤t_user.nt_user_token->user_sids[i]);
2683 sid_linearize(pdata + data_len, sid_len,
2684 ¤t_user.nt_user_token->user_sids[i]);
2685 data_len += sid_len;
2691 case SMB_MAC_QUERY_FS_INFO:
2693 * Thursby MAC extension... ONLY on NTFS filesystems
2694 * once we do streams then we don't need this
2696 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2698 SIVAL(pdata,84,0x100); /* Don't support mac... */
2703 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2707 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2709 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2714 /****************************************************************************
2715 Reply to a TRANS2_SETFSINFO (set filesystem info).
2716 ****************************************************************************/
2718 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2719 char **pparams, int total_params, char **ppdata, int total_data,
2720 unsigned int max_data_bytes)
2722 char *pdata = *ppdata;
2723 char *params = *pparams;
2727 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2730 if (total_params < 4) {
2731 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2733 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2736 info_level = SVAL(params,2);
2738 switch(info_level) {
2739 case SMB_SET_CIFS_UNIX_INFO:
2741 uint16 client_unix_major;
2742 uint16 client_unix_minor;
2743 uint32 client_unix_cap_low;
2744 uint32 client_unix_cap_high;
2746 if (!lp_unix_extensions()) {
2747 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2750 /* There should be 12 bytes of capabilities set. */
2751 if (total_data < 8) {
2752 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2754 client_unix_major = SVAL(pdata,0);
2755 client_unix_minor = SVAL(pdata,2);
2756 client_unix_cap_low = IVAL(pdata,4);
2757 client_unix_cap_high = IVAL(pdata,8);
2758 /* Just print these values for now. */
2759 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2760 cap_low = 0x%x, cap_high = 0x%x\n",
2761 (unsigned int)client_unix_major,
2762 (unsigned int)client_unix_minor,
2763 (unsigned int)client_unix_cap_low,
2764 (unsigned int)client_unix_cap_high ));
2766 /* Here is where we must switch to posix pathname processing... */
2767 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2768 lp_set_posix_pathnames();
2769 mangle_change_to_posix();
2772 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2773 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2774 /* Client that knows how to do posix locks,
2775 * but not posix open/mkdir operations. Set a
2776 * default type for read/write checks. */
2778 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2783 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2786 size_t param_len = 0;
2787 size_t data_len = total_data;
2789 if (!lp_unix_extensions()) {
2790 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2793 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2795 status = srv_request_encryption_setup(conn,
2796 (unsigned char **)ppdata,
2798 (unsigned char **)pparams,
2802 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2803 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2804 } else if (!NT_STATUS_IS_OK(status)) {
2805 return ERROR_NT(status);
2808 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2810 if (NT_STATUS_IS_OK(status)) {
2811 /* Server-side transport encryption is now *on*. */
2812 status = srv_encryption_start(conn);
2813 if (!NT_STATUS_IS_OK(status)) {
2814 exit_server_cleanly("Failure in setting up encrypted transport");
2819 case SMB_FS_QUOTA_INFORMATION:
2821 files_struct *fsp = NULL;
2822 SMB_NTQUOTA_STRUCT quotas;
2824 ZERO_STRUCT(quotas);
2827 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2828 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2829 lp_servicename(SNUM(conn)),conn->user));
2830 return ERROR_DOS(ERRSRV,ERRaccess);
2833 /* note: normaly there're 48 bytes,
2834 * but we didn't use the last 6 bytes for now
2837 fsp = file_fsp(params,0);
2838 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2839 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2840 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2843 if (total_data < 42) {
2844 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2846 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2849 /* unknown_1 24 NULL bytes in pdata*/
2851 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2852 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2853 #ifdef LARGE_SMB_OFF_T
2854 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2855 #else /* LARGE_SMB_OFF_T */
2856 if ((IVAL(pdata,28) != 0)&&
2857 ((quotas.softlim != 0xFFFFFFFF)||
2858 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2859 /* more than 32 bits? */
2860 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2862 #endif /* LARGE_SMB_OFF_T */
2864 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2865 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2866 #ifdef LARGE_SMB_OFF_T
2867 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2868 #else /* LARGE_SMB_OFF_T */
2869 if ((IVAL(pdata,36) != 0)&&
2870 ((quotas.hardlim != 0xFFFFFFFF)||
2871 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2872 /* more than 32 bits? */
2873 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2875 #endif /* LARGE_SMB_OFF_T */
2877 /* quota_flags 2 bytes **/
2878 quotas.qflags = SVAL(pdata,40);
2880 /* unknown_2 6 NULL bytes follow*/
2882 /* now set the quotas */
2883 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2884 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2885 return ERROR_DOS(ERRSRV,ERRerror);
2891 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2893 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2898 * sending this reply works fine,
2899 * but I'm not sure it's the same
2900 * like windows do...
2903 outsize = set_message(inbuf, outbuf,10,0,True);
2908 #if defined(HAVE_POSIX_ACLS)
2909 /****************************************************************************
2910 Utility function to count the number of entries in a POSIX acl.
2911 ****************************************************************************/
2913 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2915 unsigned int ace_count = 0;
2916 int entry_id = SMB_ACL_FIRST_ENTRY;
2917 SMB_ACL_ENTRY_T entry;
2919 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2921 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2922 entry_id = SMB_ACL_NEXT_ENTRY;
2929 /****************************************************************************
2930 Utility function to marshall a POSIX acl into wire format.
2931 ****************************************************************************/
2933 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2935 int entry_id = SMB_ACL_FIRST_ENTRY;
2936 SMB_ACL_ENTRY_T entry;
2938 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2939 SMB_ACL_TAG_T tagtype;
2940 SMB_ACL_PERMSET_T permset;
2941 unsigned char perms = 0;
2942 unsigned int own_grp;
2945 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2946 entry_id = SMB_ACL_NEXT_ENTRY;
2949 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2950 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2954 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2955 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2959 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2960 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2961 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2963 SCVAL(pdata,1,perms);
2966 case SMB_ACL_USER_OBJ:
2967 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2968 own_grp = (unsigned int)pst->st_uid;
2969 SIVAL(pdata,2,own_grp);
2974 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2976 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2978 own_grp = (unsigned int)*puid;
2979 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2980 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2981 SIVAL(pdata,2,own_grp);
2985 case SMB_ACL_GROUP_OBJ:
2986 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2987 own_grp = (unsigned int)pst->st_gid;
2988 SIVAL(pdata,2,own_grp);
2993 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2995 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2997 own_grp = (unsigned int)*pgid;
2998 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2999 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3000 SIVAL(pdata,2,own_grp);
3005 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3006 SIVAL(pdata,2,0xFFFFFFFF);
3007 SIVAL(pdata,6,0xFFFFFFFF);
3010 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3011 SIVAL(pdata,2,0xFFFFFFFF);
3012 SIVAL(pdata,6,0xFFFFFFFF);
3015 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3018 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3025 /****************************************************************************
3026 Store the FILE_UNIX_BASIC info.
3027 ****************************************************************************/
3029 static char *store_file_unix_basic(connection_struct *conn,
3032 const SMB_STRUCT_STAT *psbuf)
3034 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3035 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3037 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3040 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3043 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3044 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3045 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3048 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3052 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3056 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3059 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3063 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3067 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3070 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3074 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3081 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3082 * the chflags(2) (or equivalent) flags.
3084 * XXX: this really should be behind the VFS interface. To do this, we would
3085 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3086 * Each VFS module could then implement it's own mapping as appropriate for the
3087 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3089 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3093 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3097 { UF_IMMUTABLE, EXT_IMMUTABLE },
3101 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3105 { UF_HIDDEN, EXT_HIDDEN },
3108 /* Do not remove. We need to guarantee that this array has at least one
3109 * entry to build on HP-UX.
3115 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3116 uint32 *smb_fflags, uint32 *smb_fmask)
3118 #ifdef HAVE_STAT_ST_FLAGS
3121 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3122 *smb_fmask |= info2_flags_map[i].smb_fflag;
3123 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3124 *smb_fflags |= info2_flags_map[i].smb_fflag;
3127 #endif /* HAVE_STAT_ST_FLAGS */
3130 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3131 const uint32 smb_fflags,
3132 const uint32 smb_fmask,
3135 #ifdef HAVE_STAT_ST_FLAGS
3136 uint32 max_fmask = 0;
3139 *stat_fflags = psbuf->st_flags;
3141 /* For each flags requested in smb_fmask, check the state of the
3142 * corresponding flag in smb_fflags and set or clear the matching
3146 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3147 max_fmask |= info2_flags_map[i].smb_fflag;
3148 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3149 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3150 *stat_fflags |= info2_flags_map[i].stat_fflag;
3152 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3157 /* If smb_fmask is asking to set any bits that are not supported by
3158 * our flag mappings, we should fail.
3160 if ((smb_fmask & max_fmask) != smb_fmask) {
3167 #endif /* HAVE_STAT_ST_FLAGS */
3171 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3172 * of file flags and birth (create) time.
3174 static char *store_file_unix_basic_info2(connection_struct *conn,
3177 const SMB_STRUCT_STAT *psbuf)
3179 uint32 file_flags = 0;
3180 uint32 flags_mask = 0;
3182 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3184 /* Create (birth) time 64 bit */
3185 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3188 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3189 SIVAL(pdata, 0, file_flags); /* flags */
3190 SIVAL(pdata, 4, flags_mask); /* mask */
3196 /****************************************************************************
3197 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3198 file name or file id).
3199 ****************************************************************************/
3201 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3202 unsigned int tran_call,
3203 char **pparams, int total_params, char **ppdata, int total_data,
3204 unsigned int max_data_bytes)
3206 char *params = *pparams;
3207 char *pdata = *ppdata;
3211 SMB_OFF_T file_size=0;
3212 SMB_BIG_UINT allocation_size=0;
3213 unsigned int data_size = 0;
3214 unsigned int param_size = 2;
3215 SMB_STRUCT_STAT sbuf;
3216 pstring fname, dos_fname;
3221 BOOL delete_pending = False;
3223 time_t create_time, mtime, atime;
3224 struct timespec create_time_ts, mtime_ts, atime_ts;
3225 files_struct *fsp = NULL;
3226 TALLOC_CTX *data_ctx = NULL;
3227 struct ea_list *ea_list = NULL;
3228 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3229 char *lock_data = NULL;
3232 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3236 if (tran_call == TRANSACT2_QFILEINFO) {
3237 if (total_params < 4) {
3238 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3241 fsp = file_fsp(params,0);
3242 info_level = SVAL(params,2);
3244 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3246 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3247 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3250 if(fsp && (fsp->fake_file_handle)) {
3252 * This is actually for the QUOTA_FAKE_FILE --metze
3255 pstrcpy(fname, fsp->fsp_name);
3256 /* We know this name is ok, it's already passed the checks. */
3258 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3260 * This is actually a QFILEINFO on a directory
3261 * handle (returned from an NT SMB). NT5.0 seems
3262 * to do this call. JRA.
3264 /* We know this name is ok, it's already passed the checks. */
3265 pstrcpy(fname, fsp->fsp_name);
3267 if (INFO_LEVEL_IS_UNIX(info_level)) {
3268 /* Always do lstat for UNIX calls. */
3269 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3270 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3271 return UNIXERROR(ERRDOS,ERRbadpath);
3273 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3274 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3275 return UNIXERROR(ERRDOS,ERRbadpath);
3278 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3281 * Original code - this is an open file.
3283 CHECK_FSP(fsp,conn);
3285 pstrcpy(fname, fsp->fsp_name);
3286 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3287 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3288 return(UNIXERROR(ERRDOS,ERRbadfid));
3290 pos = fsp->fh->position_information;
3291 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3292 access_mask = fsp->access_mask;
3295 NTSTATUS status = NT_STATUS_OK;
3298 if (total_params < 7) {
3299 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3302 info_level = SVAL(params,0);
3304 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3306 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3307 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3310 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3311 if (!NT_STATUS_IS_OK(status)) {
3312 return ERROR_NT(status);
3315 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3316 if (!NT_STATUS_IS_OK(status)) {
3317 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3318 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3320 return ERROR_NT(status);
3323 status = unix_convert(conn, fname, False, NULL, &sbuf);
3324 if (!NT_STATUS_IS_OK(status)) {
3325 return ERROR_NT(status);
3327 status = check_name(conn, fname);
3328 if (!NT_STATUS_IS_OK(status)) {
3329 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3330 return ERROR_NT(status);
3333 if (INFO_LEVEL_IS_UNIX(info_level)) {
3334 /* Always do lstat for UNIX calls. */
3335 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3336 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3337 return UNIXERROR(ERRDOS,ERRbadpath);
3339 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3340 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3341 return UNIXERROR(ERRDOS,ERRbadpath);
3344 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3345 if (delete_pending) {
3346 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3350 nlink = sbuf.st_nlink;
3352 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3353 /* NTFS does not seem to count ".." */
3357 if ((nlink > 0) && delete_pending) {
3361 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3362 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3365 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3366 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3368 p = strrchr_m(fname,'/');
3374 mode = dos_mode(conn,fname,&sbuf);
3376 mode = FILE_ATTRIBUTE_NORMAL;
3378 fullpathname = fname;
3380 file_size = get_file_size(sbuf);
3382 /* Pull out any data sent here before we realloc. */
3383 switch (info_level) {
3384 case SMB_INFO_QUERY_EAS_FROM_LIST:
3386 /* Pull any EA list from the data portion. */
3389 if (total_data < 4) {
3390 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3392 ea_size = IVAL(pdata,0);
3394 if (total_data > 0 && ea_size != total_data) {
3395 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3396 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3397 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3400 if (!lp_ea_support(SNUM(conn))) {
3401 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3404 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3405 return ERROR_NT(NT_STATUS_NO_MEMORY);
3408 /* Pull out the list of names. */
3409 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3411 talloc_destroy(data_ctx);
3412 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3417 case SMB_QUERY_POSIX_LOCK:
3419 if (fsp == NULL || fsp->fh->fd == -1) {
3420 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3423 if (total_data != POSIX_LOCK_DATA_SIZE) {
3424 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3427 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3428 return ERROR_NT(NT_STATUS_NO_MEMORY);
3431 /* Copy the lock range data. */
3432 lock_data = (char *)talloc_memdup(
3433 data_ctx, pdata, total_data);
3435 talloc_destroy(data_ctx);
3436 return ERROR_NT(NT_STATUS_NO_MEMORY);
3443 *pparams = (char *)SMB_REALLOC(*pparams,2);
3444 if (*pparams == NULL) {
3445 talloc_destroy(data_ctx);
3446 return ERROR_NT(NT_STATUS_NO_MEMORY);
3450 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3451 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3452 if (*ppdata == NULL ) {
3453 talloc_destroy(data_ctx);
3454 return ERROR_NT(NT_STATUS_NO_MEMORY);
3458 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3459 mtime_ts = get_mtimespec(&sbuf);
3460 atime_ts = get_atimespec(&sbuf);
3462 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3465 if (!null_timespec(fsp->pending_modtime)) {
3466 /* the pending modtime overrides the current modtime */
3467 mtime_ts = fsp->pending_modtime;
3470 /* Do we have this path open ? */
3471 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3472 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3473 /* the pending modtime overrides the current modtime */
3474 mtime_ts = fsp1->pending_modtime;
3476 if (fsp1 && fsp1->initial_allocation_size) {
3477 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3481 if (lp_dos_filetime_resolution(SNUM(conn))) {
3482 dos_filetime_timespec(&create_time_ts);
3483 dos_filetime_timespec(&mtime_ts);
3484 dos_filetime_timespec(&atime_ts);
3487 create_time = convert_timespec_to_time_t(create_time_ts);
3488 mtime = convert_timespec_to_time_t(mtime_ts);
3489 atime = convert_timespec_to_time_t(atime_ts);
3491 /* NT expects the name to be in an exact form of the *full*
3492 filename. See the trans2 torture test */
3493 if (strequal(base_name,".")) {
3494 pstrcpy(dos_fname, "\\");
3496 pstr_sprintf(dos_fname, "\\%s", fname);
3497 string_replace(dos_fname, '/', '\\');
3500 switch (info_level) {
3501 case SMB_INFO_STANDARD:
3502 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3504 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3505 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3506 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3507 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3508 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3509 SSVAL(pdata,l1_attrFile,mode);
3512 case SMB_INFO_QUERY_EA_SIZE:
3514 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3515 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3517 srv_put_dos_date2(pdata,0,create_time);
3518 srv_put_dos_date2(pdata,4,atime);
3519 srv_put_dos_date2(pdata,8,mtime); /* write time */
3520 SIVAL(pdata,12,(uint32)file_size);
3521 SIVAL(pdata,16,(uint32)allocation_size);
3522 SSVAL(pdata,20,mode);
3523 SIVAL(pdata,22,ea_size);
3527 case SMB_INFO_IS_NAME_VALID:
3528 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3529 if (tran_call == TRANSACT2_QFILEINFO) {
3530 /* os/2 needs this ? really ?*/
3531 return ERROR_DOS(ERRDOS,ERRbadfunc);
3537 case SMB_INFO_QUERY_EAS_FROM_LIST:
3539 size_t total_ea_len = 0;
3540 struct ea_list *ea_file_list = NULL;
3542 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3544 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3545 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3547 if (!ea_list || (total_ea_len > data_size)) {
3548 talloc_destroy(data_ctx);
3550 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3554 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3555 talloc_destroy(data_ctx);
3559 case SMB_INFO_QUERY_ALL_EAS:
3561 /* We have data_size bytes to put EA's into. */
3562 size_t total_ea_len = 0;
3564 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3566 data_ctx = talloc_init("ea_ctx");
3568 return ERROR_NT(NT_STATUS_NO_MEMORY);
3571 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3572 if (!ea_list || (total_ea_len > data_size)) {
3573 talloc_destroy(data_ctx);
3575 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3579 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3580 talloc_destroy(data_ctx);
3584 case SMB_FILE_BASIC_INFORMATION:
3585 case SMB_QUERY_FILE_BASIC_INFO:
3587 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3588 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3589 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3591 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3595 put_long_date_timespec(pdata,create_time_ts);
3596 put_long_date_timespec(pdata+8,atime_ts);
3597 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3598 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3599 SIVAL(pdata,32,mode);
3601 DEBUG(5,("SMB_QFBI - "));
3602 DEBUG(5,("create: %s ", ctime(&create_time)));
3603 DEBUG(5,("access: %s ", ctime(&atime)));
3604 DEBUG(5,("write: %s ", ctime(&mtime)));
3605 DEBUG(5,("change: %s ", ctime(&mtime)));
3606 DEBUG(5,("mode: %x\n", mode));
3609 case SMB_FILE_STANDARD_INFORMATION:
3610 case SMB_QUERY_FILE_STANDARD_INFO:
3612 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3614 SOFF_T(pdata,0,allocation_size);
3615 SOFF_T(pdata,8,file_size);
3616 SIVAL(pdata,16,nlink);
3617 SCVAL(pdata,20,delete_pending?1:0);
3618 SCVAL(pdata,21,(mode&aDIR)?1:0);
3619 SSVAL(pdata,22,0); /* Padding. */
3622 case SMB_FILE_EA_INFORMATION:
3623 case SMB_QUERY_FILE_EA_INFO:
3625 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3626 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3628 SIVAL(pdata,0,ea_size);
3632 /* Get the 8.3 name - used if NT SMB was negotiated. */
3633 case SMB_QUERY_FILE_ALT_NAME_INFO:
3634 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3638 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3639 pstrcpy(short_name,base_name);
3640 /* Mangle if not already 8.3 */
3641 if(!mangle_is_8_3(short_name, True, conn->params)) {
3642 mangle_map(short_name,True,True,conn->params);
3644 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3645 data_size = 4 + len;
3650 case SMB_QUERY_FILE_NAME_INFO:
3652 this must be *exactly* right for ACLs on mapped drives to work
3654 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3655 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3656 data_size = 4 + len;
3660 case SMB_FILE_ALLOCATION_INFORMATION:
3661 case SMB_QUERY_FILE_ALLOCATION_INFO:
3662 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3664 SOFF_T(pdata,0,allocation_size);
3667 case SMB_FILE_END_OF_FILE_INFORMATION:
3668 case SMB_QUERY_FILE_END_OF_FILEINFO:
3669 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3671 SOFF_T(pdata,0,file_size);
3674 case SMB_QUERY_FILE_ALL_INFO:
3675 case SMB_FILE_ALL_INFORMATION:
3677 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3678 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3679 put_long_date_timespec(pdata,create_time_ts);
3680 put_long_date_timespec(pdata+8,atime_ts);
3681 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3682 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3683 SIVAL(pdata,32,mode);
3684 SIVAL(pdata,36,0); /* padding. */
3686 SOFF_T(pdata,0,allocation_size);
3687 SOFF_T(pdata,8,file_size);
3688 SIVAL(pdata,16,nlink);
3689 SCVAL(pdata,20,delete_pending);
3690 SCVAL(pdata,21,(mode&aDIR)?1:0);
3693 SIVAL(pdata,0,ea_size);
3694 pdata += 4; /* EA info */
3695 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3698 data_size = PTR_DIFF(pdata,(*ppdata));
3701 case SMB_FILE_INTERNAL_INFORMATION:
3702 /* This should be an index number - looks like
3705 I think this causes us to fail the IFSKIT
3706 BasicFileInformationTest. -tpot */
3708 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3709 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3710 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3714 case SMB_FILE_ACCESS_INFORMATION:
3715 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3716 SIVAL(pdata,0,access_mask);
3720 case SMB_FILE_NAME_INFORMATION:
3721 /* Pathname with leading '\'. */
3724 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3725 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3726 SIVAL(pdata,0,byte_len);
3727 data_size = 4 + byte_len;
3731 case SMB_FILE_DISPOSITION_INFORMATION:
3732 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3734 SCVAL(pdata,0,delete_pending);
3737 case SMB_FILE_POSITION_INFORMATION:
3738 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3740 SOFF_T(pdata,0,pos);
3743 case SMB_FILE_MODE_INFORMATION:
3744 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3745 SIVAL(pdata,0,mode);
3749 case SMB_FILE_ALIGNMENT_INFORMATION:
3750 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3751 SIVAL(pdata,0,0); /* No alignment needed. */
3757 * NT4 server just returns "invalid query" to this - if we try to answer
3758 * it then NTws gets a BSOD! (tridge).
3759 * W2K seems to want this. JRA.
3761 case SMB_QUERY_FILE_STREAM_INFO:
3763 case SMB_FILE_STREAM_INFORMATION:
3764 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3768 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3769 SIVAL(pdata,0,0); /* ??? */
3770 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3771 SOFF_T(pdata,8,file_size);
3772 SIVAL(pdata,16,allocation_size);
3773 SIVAL(pdata,20,0); /* ??? */
3774 data_size = 24 + byte_len;
3778 case SMB_QUERY_COMPRESSION_INFO:
3779 case SMB_FILE_COMPRESSION_INFORMATION:
3780 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3781 SOFF_T(pdata,0,file_size);
3782 SIVAL(pdata,8,0); /* ??? */
3783 SIVAL(pdata,12,0); /* ??? */
3787 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3788 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3789 put_long_date_timespec(pdata,create_time_ts);
3790 put_long_date_timespec(pdata+8,atime_ts);
3791 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3792 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3793 SIVAL(pdata,32,allocation_size);
3794 SOFF_T(pdata,40,file_size);
3795 SIVAL(pdata,48,mode);
3796 SIVAL(pdata,52,0); /* ??? */
3800 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3801 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3802 SIVAL(pdata,0,mode);
3808 * CIFS UNIX Extensions.
3811 case SMB_QUERY_FILE_UNIX_BASIC:
3813 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3814 data_size = PTR_DIFF(pdata,(*ppdata));
3818 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3820 for (i=0; i<100; i++)
3821 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3827 case SMB_QUERY_FILE_UNIX_INFO2:
3829 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3830 data_size = PTR_DIFF(pdata,(*ppdata));
3834 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3836 for (i=0; i<100; i++)
3837 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3843 case SMB_QUERY_FILE_UNIX_LINK:
3847 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3849 if(!S_ISLNK(sbuf.st_mode))
3850 return(UNIXERROR(ERRSRV,ERRbadlink));
3852 return(UNIXERROR(ERRDOS,ERRbadlink));
3854 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3856 return(UNIXERROR(ERRDOS,ERRnoaccess));
3858 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3860 data_size = PTR_DIFF(pdata,(*ppdata));
3865 #if defined(HAVE_POSIX_ACLS)
3866 case SMB_QUERY_POSIX_ACL:
3868 SMB_ACL_T file_acl = NULL;
3869 SMB_ACL_T def_acl = NULL;
3870 uint16 num_file_acls = 0;
3871 uint16 num_def_acls = 0;
3873 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3874 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3876 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3879 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3880 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3882 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3885 if (S_ISDIR(sbuf.st_mode)) {
3886 if (fsp && fsp->is_directory) {
3887 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3889 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3891 def_acl = free_empty_sys_acl(conn, def_acl);
3894 num_file_acls = count_acl_entries(conn, file_acl);
3895 num_def_acls = count_acl_entries(conn, def_acl);
3897 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3898 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3900 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3901 SMB_POSIX_ACL_HEADER_SIZE) ));
3903 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3906 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3908 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3911 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3912 SSVAL(pdata,2,num_file_acls);
3913 SSVAL(pdata,4,num_def_acls);
3914 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3916 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3919 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3921 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3923 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3925 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3928 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3930 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3934 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3937 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3939 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3945 case SMB_QUERY_POSIX_LOCK:
3947 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3949 SMB_BIG_UINT offset;
3951 enum brl_type lock_type;
3953 if (total_data != POSIX_LOCK_DATA_SIZE) {
3954 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3957 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3958 case POSIX_LOCK_TYPE_READ:
3959 lock_type = READ_LOCK;
3961 case POSIX_LOCK_TYPE_WRITE:
3962 lock_type = WRITE_LOCK;
3964 case POSIX_LOCK_TYPE_UNLOCK:
3966 /* There's no point in asking for an unlock... */
3967 talloc_destroy(data_ctx);
3968 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3971 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3972 #if defined(HAVE_LONGLONG)
3973 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3974 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3975 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3976 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3977 #else /* HAVE_LONGLONG */
3978 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3979 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3980 #endif /* HAVE_LONGLONG */
3982 status = query_lock(fsp,
3989 if (ERROR_WAS_LOCK_DENIED(status)) {
3990 /* Here we need to report who has it locked... */
3991 data_size = POSIX_LOCK_DATA_SIZE;
3993 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3994 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3995 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3996 #if defined(HAVE_LONGLONG)
3997 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3998 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3999 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4000 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4001 #else /* HAVE_LONGLONG */
4002 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4003 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4004 #endif /* HAVE_LONGLONG */
4006 } else if (NT_STATUS_IS_OK(status)) {
4007 /* For success we just return a copy of what we sent
4008 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4009 data_size = POSIX_LOCK_DATA_SIZE;
4010 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4011 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4013 return ERROR_NT(status);
4019 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4022 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4027 /****************************************************************************
4028 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4030 ****************************************************************************/
4032 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4034 SMB_STRUCT_STAT sbuf1, sbuf2;
4035 pstring last_component_oldname;
4036 pstring last_component_newname;
4037 NTSTATUS status = NT_STATUS_OK;
4042 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4043 if (!NT_STATUS_IS_OK(status)) {
4047 status = check_name(conn, oldname);
4048 if (!NT_STATUS_IS_OK(status)) {
4052 /* source must already exist. */
4053 if (!VALID_STAT(sbuf1)) {
4054 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4057 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4058 if (!NT_STATUS_IS_OK(status)) {
4062 status = check_name(conn, newname);
4063 if (!NT_STATUS_IS_OK(status)) {
4067 /* Disallow if newname already exists. */
4068 if (VALID_STAT(sbuf2)) {
4069 return NT_STATUS_OBJECT_NAME_COLLISION;
4072 /* No links from a directory. */
4073 if (S_ISDIR(sbuf1.st_mode)) {
4074 return NT_STATUS_FILE_IS_A_DIRECTORY;
4077 /* Ensure this is within the share. */
4078 status = reduce_name(conn, oldname);
4079 if (!NT_STATUS_IS_OK(status)) {
4083 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4085 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4086 status = map_nt_error_from_unix(errno);
4087 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4088 nt_errstr(status), newname, oldname));
4094 /****************************************************************************
4095 Deal with setting the time from any of the setfilepathinfo functions.
4096 ****************************************************************************/
4098 static NTSTATUS smb_set_file_time(connection_struct *conn,
4101 const SMB_STRUCT_STAT *psbuf,
4102 struct timespec ts[2])
4105 FILE_NOTIFY_CHANGE_LAST_ACCESS
4106 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4109 if (!VALID_STAT(*psbuf)) {
4110 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4113 /* get some defaults (no modifications) if any info is zero or -1. */
4114 if (null_timespec(ts[0])) {
4115 ts[0] = get_atimespec(psbuf);
4116 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4119 if (null_timespec(ts[1])) {
4120 ts[1] = get_mtimespec(psbuf);
4121 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4124 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4125 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4128 * Try and set the times of this file if
4129 * they are different from the current values.
4133 struct timespec mts = get_mtimespec(psbuf);
4134 struct timespec ats = get_atimespec(psbuf);
4135 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4136 return NT_STATUS_OK;
4142 * This was a setfileinfo on an open file.
4143 * NT does this a lot. We also need to
4144 * set the time here, as it can be read by
4145 * FindFirst/FindNext and with the patch for bug #2045
4146 * in smbd/fileio.c it ensures that this timestamp is
4147 * kept sticky even after a write. We save the request
4148 * away and will set it on file close and after a write. JRA.
4151 if (!null_timespec(ts[1])) {
4152 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4153 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4154 fsp_set_pending_modtime(fsp, ts[1]);
4158 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4160 if(file_ntimes(conn, fname, ts)!=0) {
4161 return map_nt_error_from_unix(errno);
4164 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4166 return NT_STATUS_OK;
4169 /****************************************************************************
4170 Deal with setting the dosmode from any of the setfilepathinfo functions.
4171 ****************************************************************************/
4173 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4175 SMB_STRUCT_STAT *psbuf,
4178 if (!VALID_STAT(*psbuf)) {
4179 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4183 if (S_ISDIR(psbuf->st_mode)) {
4190 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4192 /* check the mode isn't different, before changing it */
4193 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4195 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4196 fname, (unsigned int)dosmode ));
4198 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4199 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4200 fname, strerror(errno)));
4201 return map_nt_error_from_unix(errno);
4204 return NT_STATUS_OK;
4207 /****************************************************************************
4208 Deal with setting the size from any of the setfilepathinfo functions.
4209 ****************************************************************************/
4211 static NTSTATUS smb_set_file_size(connection_struct *conn,
4214 SMB_STRUCT_STAT *psbuf,
4217 NTSTATUS status = NT_STATUS_OK;
4218 files_struct *new_fsp = NULL;
4220 if (!VALID_STAT(*psbuf)) {
4221 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4224 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4226 if (size == get_file_size(*psbuf)) {
4227 return NT_STATUS_OK;
4230 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4231 fname, (double)size ));
4233 if (fsp && fsp->fh->fd != -1) {
4234 /* Handle based call. */
4235 if (vfs_set_filelen(fsp, size) == -1) {
4236 return map_nt_error_from_unix(errno);
4238 return NT_STATUS_OK;
4241 status = open_file_ntcreate(conn, fname, psbuf,
4243 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4246 FILE_ATTRIBUTE_NORMAL,
4247 FORCE_OPLOCK_BREAK_TO_NONE,
4250 if (!NT_STATUS_IS_OK(status)) {
4251 /* NB. We check for open_was_deferred in the caller. */
4255 if (vfs_set_filelen(new_fsp, size) == -1) {
4256 status = map_nt_error_from_unix(errno);
4257 close_file(new_fsp,NORMAL_CLOSE);
4261 close_file(new_fsp,NORMAL_CLOSE);
4262 return NT_STATUS_OK;
4265 /****************************************************************************
4266 Deal with SMB_INFO_SET_EA.
4267 ****************************************************************************/
4269 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4275 struct ea_list *ea_list = NULL;
4276 TALLOC_CTX *ctx = NULL;
4277 NTSTATUS status = NT_STATUS_OK;
4279 if (total_data < 10) {
4281 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4282 length. They seem to have no effect. Bug #3212. JRA */
4284 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4285 /* We're done. We only get EA info in this call. */
4286 return NT_STATUS_OK;
4289 return NT_STATUS_INVALID_PARAMETER;
4292 if (IVAL(pdata,0) > total_data) {
4293 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4294 IVAL(pdata,0), (unsigned int)total_data));
4295 return NT_STATUS_INVALID_PARAMETER;
4298 ctx = talloc_init("SMB_INFO_SET_EA");
4300 return NT_STATUS_NO_MEMORY;
4302 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4304 talloc_destroy(ctx);
4305 return NT_STATUS_INVALID_PARAMETER;
4307 status = set_ea(conn, fsp, fname, ea_list);
4308 talloc_destroy(ctx);
4313 /****************************************************************************
4314 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4315 ****************************************************************************/
4317 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4322 SMB_STRUCT_STAT *psbuf)
4324 NTSTATUS status = NT_STATUS_OK;
4325 BOOL delete_on_close;
4328 if (total_data < 1) {
4329 return NT_STATUS_INVALID_PARAMETER;
4333 return NT_STATUS_INVALID_HANDLE;
4336 delete_on_close = (CVAL(pdata,0) ? True : False);
4337 dosmode = dos_mode(conn, fname, psbuf);
4339 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4340 "delete_on_close = %u\n",
4342 (unsigned int)dosmode,
4343 (unsigned int)delete_on_close ));
4345 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4347 if (!NT_STATUS_IS_OK(status)) {
4351 /* The set is across all open files on this dev/inode pair. */
4352 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4353 return NT_STATUS_ACCESS_DENIED;
4355 return NT_STATUS_OK;
4358 /****************************************************************************
4359 Deal with SMB_FILE_POSITION_INFORMATION.
4360 ****************************************************************************/
4362 static NTSTATUS smb_file_position_information(connection_struct *conn,
4367 SMB_BIG_UINT position_information;
4369 if (total_data < 8) {
4370 return NT_STATUS_INVALID_PARAMETER;
4374 /* Ignore on pathname based set. */
4375 return NT_STATUS_OK;
4378 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4379 #ifdef LARGE_SMB_OFF_T
4380 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4381 #else /* LARGE_SMB_OFF_T */
4382 if (IVAL(pdata,4) != 0) {
4383 /* more than 32 bits? */
4384 return NT_STATUS_INVALID_PARAMETER;
4386 #endif /* LARGE_SMB_OFF_T */
4388 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4389 fsp->fsp_name, (double)position_information ));
4390 fsp->fh->position_information = position_information;
4391 return NT_STATUS_OK;
4394 /****************************************************************************
4395 Deal with SMB_FILE_MODE_INFORMATION.
4396 ****************************************************************************/
4398 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4404 if (total_data < 4) {
4405 return NT_STATUS_INVALID_PARAMETER;
4407 mode = IVAL(pdata,0);
4408 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4409 return NT_STATUS_INVALID_PARAMETER;
4411 return NT_STATUS_OK;
4414 /****************************************************************************
4415 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4416 ****************************************************************************/
4418 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4424 pstring link_target;
4425 const char *newname = fname;
4426 NTSTATUS status = NT_STATUS_OK;
4428 /* Set a symbolic link. */
4429 /* Don't allow this if follow links is false. */
4431 if (total_data == 0) {
4432 return NT_STATUS_INVALID_PARAMETER;
4435 if (!lp_symlinks(SNUM(conn))) {
4436 return NT_STATUS_ACCESS_DENIED;
4439 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4441 /* !widelinks forces the target path to be within the share. */
4442 /* This means we can interpret the target as a pathname. */
4443 if (!lp_widelinks(SNUM(conn))) {
4445 char *last_dirp = NULL;
4447 if (*link_target == '/') {
4448 /* No absolute paths allowed. */
4449 return NT_STATUS_ACCESS_DENIED;
4451 pstrcpy(rel_name, newname);
4452 last_dirp = strrchr_m(rel_name, '/');
4454 last_dirp[1] = '\0';
4456 pstrcpy(rel_name, "./");
4458 pstrcat(rel_name, link_target);
4460 status = check_name(conn, rel_name);
4461 if (!NT_STATUS_IS_OK(status)) {
4466 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4467 newname, link_target ));
4469 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4470 return map_nt_error_from_unix(errno);
4473 return NT_STATUS_OK;
4476 /****************************************************************************
4477 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4478 ****************************************************************************/
4480 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4488 NTSTATUS status = NT_STATUS_OK;
4490 /* Set a hard link. */
4491 if (total_data == 0) {
4492 return NT_STATUS_INVALID_PARAMETER;
4495 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4496 if (!NT_STATUS_IS_OK(status)) {
4500 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4501 if (!NT_STATUS_IS_OK(status)) {
4505 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4508 return hardlink_internals(conn, oldname, fname);
4511 /****************************************************************************
4512 Deal with SMB_FILE_RENAME_INFORMATION.
4513 ****************************************************************************/
4515 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4524 /* uint32 root_fid; */ /* Not used */
4528 BOOL dest_has_wcard = False;
4529 NTSTATUS status = NT_STATUS_OK;
4532 if (total_data < 13) {
4533 return NT_STATUS_INVALID_PARAMETER;
4536 overwrite = (CVAL(pdata,0) ? True : False);
4537 /* root_fid = IVAL(pdata,4); */
4538 len = IVAL(pdata,8);
4540 if (len > (total_data - 12) || (len == 0)) {
4541 return NT_STATUS_INVALID_PARAMETER;
4544 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4545 if (!NT_STATUS_IS_OK(status)) {
4549 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4550 if (!NT_STATUS_IS_OK(status)) {
4554 /* Check the new name has no '/' characters. */
4555 if (strchr_m(newname, '/')) {
4556 return NT_STATUS_NOT_SUPPORTED;
4559 /* Create the base directory. */
4560 pstrcpy(base_name, fname);
4561 p = strrchr_m(base_name, '/');
4565 /* Append the new name. */
4566 pstrcat(base_name, "/");
4567 pstrcat(base_name, newname);
4570 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4571 fsp->fnum, fsp->fsp_name, base_name ));
4572 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4574 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4576 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4582 /****************************************************************************
4583 Deal with SMB_SET_POSIX_ACL.
4584 ****************************************************************************/
4586 #if defined(HAVE_POSIX_ACLS)
4587 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4592 SMB_STRUCT_STAT *psbuf)
4594 uint16 posix_acl_version;
4595 uint16 num_file_acls;
4596 uint16 num_def_acls;
4597 BOOL valid_file_acls = True;
4598 BOOL valid_def_acls = True;
4600 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4601 return NT_STATUS_INVALID_PARAMETER;
4603 posix_acl_version = SVAL(pdata,0);
4604 num_file_acls = SVAL(pdata,2);
4605 num_def_acls = SVAL(pdata,4);
4607 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4608 valid_file_acls = False;
4612 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4613 valid_def_acls = False;
4617 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4618 return NT_STATUS_INVALID_PARAMETER;
4621 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4622 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4623 return NT_STATUS_INVALID_PARAMETER;
4626 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4627 fname ? fname : fsp->fsp_name,
4628 (unsigned int)num_file_acls,
4629 (unsigned int)num_def_acls));
4631 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4632 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4633 return map_nt_error_from_unix(errno);
4636 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4637 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4638 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4639 return map_nt_error_from_unix(errno);
4641 return NT_STATUS_OK;
4645 /****************************************************************************
4646 Deal with SMB_SET_POSIX_LOCK.
4647 ****************************************************************************/
4649 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4657 SMB_BIG_UINT offset;
4659 BOOL blocking_lock = False;
4660 enum brl_type lock_type;
4661 NTSTATUS status = NT_STATUS_OK;
4663 if (fsp == NULL || fsp->fh->fd == -1) {
4664 return NT_STATUS_INVALID_HANDLE;
4667 if (total_data != POSIX_LOCK_DATA_SIZE) {
4668 return NT_STATUS_INVALID_PARAMETER;
4671 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4672 case POSIX_LOCK_TYPE_READ:
4673 lock_type = READ_LOCK;
4675 case POSIX_LOCK_TYPE_WRITE:
4676 /* Return the right POSIX-mappable error code for files opened read-only. */
4677 if (!fsp->can_write) {
4678 return NT_STATUS_INVALID_HANDLE;
4680 lock_type = WRITE_LOCK;
4682 case POSIX_LOCK_TYPE_UNLOCK:
4683 lock_type = UNLOCK_LOCK;
4686 return NT_STATUS_INVALID_PARAMETER;
4689 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4690 blocking_lock = False;
4691 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4692 blocking_lock = True;
4694 return NT_STATUS_INVALID_PARAMETER;
4697 if (!lp_blocking_locks(SNUM(conn))) {
4698 blocking_lock = False;
4701 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4702 #if defined(HAVE_LONGLONG)
4703 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4704 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4705 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4706 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4707 #else /* HAVE_LONGLONG */
4708 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4709 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4710 #endif /* HAVE_LONGLONG */
4712 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4713 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4715 (unsigned int)lock_type,
4716 (unsigned int)lock_pid,
4720 if (lock_type == UNLOCK_LOCK) {
4721 status = do_unlock(fsp,
4727 struct byte_range_lock *br_lck = do_lock(fsp,
4736 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4738 * A blocking lock was requested. Package up
4739 * this smb into a queued request and push it
4740 * onto the blocking lock queue.
4742 if(push_blocking_lock_request(br_lck,
4745 -1, /* infinite timeout. */
4752 TALLOC_FREE(br_lck);
4756 TALLOC_FREE(br_lck);
4762 /****************************************************************************
4763 Deal with SMB_INFO_STANDARD.
4764 ****************************************************************************/
4766 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4771 const SMB_STRUCT_STAT *psbuf)
4773 struct timespec ts[2];
4775 if (total_data < 12) {
4776 return NT_STATUS_INVALID_PARAMETER;
4780 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4782 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4784 DEBUG(10,("smb_set_info_standard: file %s\n",
4785 fname ? fname : fsp->fsp_name ));
4787 return smb_set_file_time(conn,
4794 /****************************************************************************
4795 Deal with SMB_SET_FILE_BASIC_INFO.
4796 ****************************************************************************/
4798 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4803 SMB_STRUCT_STAT *psbuf)
4805 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4806 struct timespec write_time;
4807 struct timespec changed_time;
4809 struct timespec ts[2];
4810 NTSTATUS status = NT_STATUS_OK;
4812 if (total_data < 36) {
4813 return NT_STATUS_INVALID_PARAMETER;
4816 /* Set the attributes */
4817 dosmode = IVAL(pdata,32);
4818 status = smb_set_file_dosmode(conn,
4822 if (!NT_STATUS_IS_OK(status)) {
4826 /* Ignore create time at offset pdata. */
4829 ts[0] = interpret_long_date(pdata+8);
4831 write_time = interpret_long_date(pdata+16);
4832 changed_time = interpret_long_date(pdata+24);
4835 ts[1] = timespec_min(&write_time, &changed_time);
4837 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4841 /* Prefer a defined time to an undefined one. */
4842 if (null_timespec(ts[1])) {
4843 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4846 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4847 fname ? fname : fsp->fsp_name ));
4849 return smb_set_file_time(conn,
4856 /****************************************************************************
4857 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4858 ****************************************************************************/
4860 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4865 SMB_STRUCT_STAT *psbuf)
4867 SMB_BIG_UINT allocation_size = 0;
4868 NTSTATUS status = NT_STATUS_OK;
4869 files_struct *new_fsp = NULL;
4871 if (!VALID_STAT(*psbuf)) {
4872 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4875 if (total_data < 8) {
4876 return NT_STATUS_INVALID_PARAMETER;
4879 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4880 #ifdef LARGE_SMB_OFF_T
4881 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4882 #else /* LARGE_SMB_OFF_T */
4883 if (IVAL(pdata,4) != 0) {
4884 /* more than 32 bits? */
4885 return NT_STATUS_INVALID_PARAMETER;
4887 #endif /* LARGE_SMB_OFF_T */
4889 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4890 fname, (double)allocation_size ));
4892 if (allocation_size) {
4893 allocation_size = smb_roundup(conn, allocation_size);
4896 if(allocation_size == get_file_size(*psbuf)) {
4897 return NT_STATUS_OK;
4900 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4901 fname, (double)allocation_size ));
4903 if (fsp && fsp->fh->fd != -1) {
4904 /* Open file handle. */
4905 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4906 return map_nt_error_from_unix(errno);
4908 return NT_STATUS_OK;
4911 /* Pathname or stat or directory file. */
4913 status = open_file_ntcreate(conn, fname, psbuf,
4915 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4918 FILE_ATTRIBUTE_NORMAL,
4919 FORCE_OPLOCK_BREAK_TO_NONE,
4922 if (!NT_STATUS_IS_OK(status)) {
4923 /* NB. We check for open_was_deferred in the caller. */
4926 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4927 status = map_nt_error_from_unix(errno);
4928 close_file(new_fsp,NORMAL_CLOSE);
4932 close_file(new_fsp,NORMAL_CLOSE);
4933 return NT_STATUS_OK;
4936 /****************************************************************************
4937 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4938 ****************************************************************************/
4940 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4945 SMB_STRUCT_STAT *psbuf)
4949 if (total_data < 8) {
4950 return NT_STATUS_INVALID_PARAMETER;
4953 size = IVAL(pdata,0);
4954 #ifdef LARGE_SMB_OFF_T
4955 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4956 #else /* LARGE_SMB_OFF_T */
4957 if (IVAL(pdata,4) != 0) {
4958 /* more than 32 bits? */
4959 return NT_STATUS_INVALID_PARAMETER;
4961 #endif /* LARGE_SMB_OFF_T */
4962 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4963 "file %s to %.0f\n", fname, (double)size ));
4965 return smb_set_file_size(conn,
4972 /****************************************************************************
4973 Allow a UNIX info mknod.
4974 ****************************************************************************/
4976 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4980 SMB_STRUCT_STAT *psbuf)
4982 uint32 file_type = IVAL(pdata,56);
4983 #if defined(HAVE_MAKEDEV)
4984 uint32 dev_major = IVAL(pdata,60);
4985 uint32 dev_minor = IVAL(pdata,68);
4987 SMB_DEV_T dev = (SMB_DEV_T)0;
4988 uint32 raw_unixmode = IVAL(pdata,84);
4992 if (total_data < 100) {
4993 return NT_STATUS_INVALID_PARAMETER;
4996 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4997 if (!NT_STATUS_IS_OK(status)) {
5001 #if defined(HAVE_MAKEDEV)
5002 dev = makedev(dev_major, dev_minor);
5005 switch (file_type) {
5006 #if defined(S_IFIFO)
5007 case UNIX_TYPE_FIFO:
5008 unixmode |= S_IFIFO;
5011 #if defined(S_IFSOCK)
5012 case UNIX_TYPE_SOCKET:
5013 unixmode |= S_IFSOCK;
5016 #if defined(S_IFCHR)
5017 case UNIX_TYPE_CHARDEV:
5018 unixmode |= S_IFCHR;
5021 #if defined(S_IFBLK)
5022 case UNIX_TYPE_BLKDEV:
5023 unixmode |= S_IFBLK;
5027 return NT_STATUS_INVALID_PARAMETER;
5030 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5031 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5033 /* Ok - do the mknod. */
5034 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5035 return map_nt_error_from_unix(errno);
5038 /* If any of the other "set" calls fail we
5039 * don't want to end up with a half-constructed mknod.
5042 if (lp_inherit_perms(SNUM(conn))) {
5044 conn, parent_dirname(fname),
5048 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5049 status = map_nt_error_from_unix(errno);
5050 SMB_VFS_UNLINK(conn,fname);
5053 return NT_STATUS_OK;
5056 /****************************************************************************
5057 Deal with SMB_SET_FILE_UNIX_BASIC.
5058 ****************************************************************************/
5060 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5065 SMB_STRUCT_STAT *psbuf)
5067 struct timespec ts[2];
5068 uint32 raw_unixmode;
5071 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5072 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5073 NTSTATUS status = NT_STATUS_OK;
5074 BOOL delete_on_fail = False;
5075 enum perm_type ptype;
5077 if (total_data < 100) {
5078 return NT_STATUS_INVALID_PARAMETER;
5081 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5082 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5083 size=IVAL(pdata,0); /* first 8 Bytes are size */
5084 #ifdef LARGE_SMB_OFF_T
5085 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5086 #else /* LARGE_SMB_OFF_T */
5087 if (IVAL(pdata,4) != 0) {
5088 /* more than 32 bits? */
5089 return NT_STATUS_INVALID_PARAMETER;
5091 #endif /* LARGE_SMB_OFF_T */
5094 ts[0] = interpret_long_date(pdata+24); /* access_time */
5095 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5096 set_owner = (uid_t)IVAL(pdata,40);
5097 set_grp = (gid_t)IVAL(pdata,48);
5098 raw_unixmode = IVAL(pdata,84);
5100 if (VALID_STAT(*psbuf)) {
5101 if (S_ISDIR(psbuf->st_mode)) {
5102 ptype = PERM_EXISTING_DIR;
5104 ptype = PERM_EXISTING_FILE;
5107 ptype = PERM_NEW_FILE;
5110 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5111 if (!NT_STATUS_IS_OK(status)) {
5115 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5116 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5117 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5119 if (!VALID_STAT(*psbuf)) {
5121 * The only valid use of this is to create character and block
5122 * devices, and named pipes. This is deprecated (IMHO) and
5123 * a new info level should be used for mknod. JRA.
5126 status = smb_unix_mknod(conn,
5131 if (!NT_STATUS_IS_OK(status)) {
5135 /* Ensure we don't try and change anything else. */
5136 raw_unixmode = SMB_MODE_NO_CHANGE;
5137 size = get_file_size(*psbuf);
5138 ts[0] = get_atimespec(psbuf);
5139 ts[1] = get_mtimespec(psbuf);
5141 * We continue here as we might want to change the
5144 delete_on_fail = True;
5148 /* Horrible backwards compatibility hack as an old server bug
5149 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5153 size = get_file_size(*psbuf);
5158 * Deal with the UNIX specific mode set.
5161 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5162 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5163 (unsigned int)unixmode, fname ));
5164 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5165 return map_nt_error_from_unix(errno);
5170 * Deal with the UNIX specific uid set.
5173 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5174 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5175 (unsigned int)set_owner, fname ));
5176 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5177 status = map_nt_error_from_unix(errno);
5178 if (delete_on_fail) {
5179 SMB_VFS_UNLINK(conn,fname);
5186 * Deal with the UNIX specific gid set.
5189 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5190 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5191 (unsigned int)set_owner, fname ));
5192 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5193 status = map_nt_error_from_unix(errno);
5194 if (delete_on_fail) {
5195 SMB_VFS_UNLINK(conn,fname);
5201 /* Deal with any size changes. */
5203 status = smb_set_file_size(conn,
5208 if (!NT_STATUS_IS_OK(status)) {
5212 /* Deal with any time changes. */
5214 return smb_set_file_time(conn,
5221 /****************************************************************************
5222 Deal with SMB_SET_FILE_UNIX_INFO2.
5223 ****************************************************************************/
5225 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5230 SMB_STRUCT_STAT *psbuf)
5236 if (total_data < 116) {
5237 return NT_STATUS_INVALID_PARAMETER;
5240 /* Start by setting all the fields that are common between UNIX_BASIC
5243 status = smb_set_file_unix_basic(conn, pdata, total_data,
5245 if (!NT_STATUS_IS_OK(status)) {
5249 smb_fflags = IVAL(pdata, 108);
5250 smb_fmask = IVAL(pdata, 112);
5252 /* NB: We should only attempt to alter the file flags if the client
5253 * sends a non-zero mask.
5255 if (smb_fmask != 0) {
5256 int stat_fflags = 0;
5258 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5260 /* Client asked to alter a flag we don't understand. */
5261 return NT_STATUS_INVALID_PARAMETER;
5264 if (fsp && fsp->fh->fd != -1) {
5265 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5266 return NT_STATUS_NOT_SUPPORTED;
5268 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5269 return map_nt_error_from_unix(errno);
5274 /* XXX: need to add support for changing the create_time here. You
5275 * can do this for paths on Darwin with setattrlist(2). The right way
5276 * to hook this up is probably by extending the VFS utimes interface.
5279 return NT_STATUS_OK;
5282 /****************************************************************************
5283 Create a directory with POSIX semantics.
5284 ****************************************************************************/
5286 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5290 SMB_STRUCT_STAT *psbuf,
5291 int *pdata_return_size)
5293 NTSTATUS status = NT_STATUS_OK;
5294 uint32 raw_unixmode = 0;
5295 uint32 mod_unixmode = 0;
5296 mode_t unixmode = (mode_t)0;
5297 files_struct *fsp = NULL;
5298 uint16 info_level_return = 0;
5300 char *pdata = *ppdata;
5302 if (total_data < 18) {
5303 return NT_STATUS_INVALID_PARAMETER;
5306 raw_unixmode = IVAL(pdata,8);
5307 /* Next 4 bytes are not yet defined. */
5309 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5310 if (!NT_STATUS_IS_OK(status)) {
5314 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5316 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5317 fname, (unsigned int)unixmode ));
5319 status = open_directory(conn,
5322 FILE_READ_ATTRIBUTES, /* Just a stat open */
5323 FILE_SHARE_NONE, /* Ignored for stat opens */
5330 if (NT_STATUS_IS_OK(status)) {
5331 close_file(fsp, NORMAL_CLOSE);
5334 info_level_return = SVAL(pdata,16);
5336 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5337 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5338 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5339 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5341 *pdata_return_size = 12;
5344 /* Realloc the data size */
5345 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5346 if (*ppdata == NULL) {
5347 *pdata_return_size = 0;
5348 return NT_STATUS_NO_MEMORY;
5351 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5352 SSVAL(pdata,2,0); /* No fnum. */
5353 SIVAL(pdata,4,info); /* Was directory created. */
5355 switch (info_level_return) {
5356 case SMB_QUERY_FILE_UNIX_BASIC:
5357 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5358 SSVAL(pdata,10,0); /* Padding. */
5359 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5361 case SMB_QUERY_FILE_UNIX_INFO2:
5362 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5363 SSVAL(pdata,10,0); /* Padding. */
5364 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5367 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5368 SSVAL(pdata,10,0); /* Padding. */
5375 /****************************************************************************
5376 Open/Create a file with POSIX semantics.
5377 ****************************************************************************/
5379 static NTSTATUS smb_posix_open(connection_struct *conn,
5383 SMB_STRUCT_STAT *psbuf,
5384 int *pdata_return_size)
5386 BOOL extended_oplock_granted = False;
5387 char *pdata = *ppdata;
5389 uint32 wire_open_mode = 0;
5390 uint32 raw_unixmode = 0;
5391 uint32 mod_unixmode = 0;
5392 uint32 create_disp = 0;
5393 uint32 access_mask = 0;
5394 uint32 create_options = 0;
5395 NTSTATUS status = NT_STATUS_OK;
5396 mode_t unixmode = (mode_t)0;
5397 files_struct *fsp = NULL;
5398 int oplock_request = 0;
5400 uint16 info_level_return = 0;
5402 if (total_data < 18) {
5403 return NT_STATUS_INVALID_PARAMETER;
5406 flags = IVAL(pdata,0);
5407 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5408 if (oplock_request) {
5409 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5412 wire_open_mode = IVAL(pdata,4);
5414 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5415 return smb_posix_mkdir(conn,
5423 switch (wire_open_mode & SMB_ACCMODE) {
5425 access_mask = FILE_READ_DATA;
5428 access_mask = FILE_WRITE_DATA;
5431 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5434 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5435 (unsigned int)wire_open_mode ));
5436 return NT_STATUS_INVALID_PARAMETER;
5439 wire_open_mode &= ~SMB_ACCMODE;
5441 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5442 create_disp = FILE_CREATE;
5443 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5444 create_disp = FILE_OVERWRITE_IF;
5445 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5446 create_disp = FILE_OPEN_IF;
5448 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5449 (unsigned int)wire_open_mode ));
5450 return NT_STATUS_INVALID_PARAMETER;
5453 raw_unixmode = IVAL(pdata,8);
5454 /* Next 4 bytes are not yet defined. */
5456 status = unix_perms_from_wire(conn,
5459 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5462 if (!NT_STATUS_IS_OK(status)) {
5466 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5468 if (wire_open_mode & SMB_O_SYNC) {
5469 create_options |= FILE_WRITE_THROUGH;
5471 if (wire_open_mode & SMB_O_APPEND) {
5472 access_mask |= FILE_APPEND_DATA;
5474 if (wire_open_mode & SMB_O_DIRECT) {
5475 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5478 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5480 (unsigned int)wire_open_mode,
5481 (unsigned int)unixmode ));
5483 status = open_file_ntcreate(conn,
5487 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5489 0, /* no create options yet. */
5495 if (!NT_STATUS_IS_OK(status)) {
5499 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5500 extended_oplock_granted = True;
5503 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5504 extended_oplock_granted = True;
5507 info_level_return = SVAL(pdata,16);
5509 /* Allocate the correct return size. */
5511 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5512 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5513 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5514 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5516 *pdata_return_size = 12;
5519 /* Realloc the data size */
5520 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5521 if (*ppdata == NULL) {
5522 close_file(fsp,ERROR_CLOSE);
5523 *pdata_return_size = 0;
5524 return NT_STATUS_NO_MEMORY;
5527 if (extended_oplock_granted) {
5528 if (flags & REQUEST_BATCH_OPLOCK) {
5529 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5531 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5533 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5534 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5536 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5539 SSVAL(pdata,2,fsp->fnum);
5540 SIVAL(pdata,4,info); /* Was file created etc. */
5542 switch (info_level_return) {
5543 case SMB_QUERY_FILE_UNIX_BASIC:
5544 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5545 SSVAL(pdata,10,0); /* padding. */
5546 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5548 case SMB_QUERY_FILE_UNIX_INFO2:
5549 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5550 SSVAL(pdata,10,0); /* padding. */
5551 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5554 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5555 SSVAL(pdata,10,0); /* padding. */
5558 return NT_STATUS_OK;
5561 /****************************************************************************
5562 Delete a file with POSIX semantics.
5563 ****************************************************************************/
5565 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5569 SMB_STRUCT_STAT *psbuf)
5571 NTSTATUS status = NT_STATUS_OK;
5572 files_struct *fsp = NULL;
5576 if (total_data < 2) {
5577 return NT_STATUS_INVALID_PARAMETER;
5580 flags = SVAL(pdata,0);
5582 if (!VALID_STAT(*psbuf)) {
5583 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5586 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5587 !VALID_STAT_OF_DIR(*psbuf)) {
5588 return NT_STATUS_NOT_A_DIRECTORY;
5591 DEBUG(10,("smb_posix_unlink: %s %s\n",
5592 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5595 if (VALID_STAT_OF_DIR(*psbuf)) {
5596 status = open_directory(conn,
5600 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5602 FILE_DELETE_ON_CLOSE,
5603 FILE_FLAG_POSIX_SEMANTICS|0777,
5609 status = open_file_ntcreate(conn,
5613 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5616 FILE_FLAG_POSIX_SEMANTICS|0777,
5617 0, /* No oplock, but break existing ones. */
5621 * For file opens we must set the delete on close
5625 if (!NT_STATUS_IS_OK(status)) {
5629 status = smb_set_file_disposition_info(conn,
5637 if (!NT_STATUS_IS_OK(status)) {
5640 return close_file(fsp, NORMAL_CLOSE);
5643 /****************************************************************************
5644 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5645 ****************************************************************************/
5647 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5648 unsigned int tran_call,
5649 char **pparams, int total_params, char **ppdata, int total_data,
5650 unsigned int max_data_bytes)
5652 char *params = *pparams;
5653 char *pdata = *ppdata;
5655 SMB_STRUCT_STAT sbuf;
5657 files_struct *fsp = NULL;
5658 NTSTATUS status = NT_STATUS_OK;
5659 int data_return_size = 0;
5662 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5667 if (tran_call == TRANSACT2_SETFILEINFO) {
5668 if (total_params < 4) {
5669 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5672 fsp = file_fsp(params,0);
5673 info_level = SVAL(params,2);
5675 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5677 * This is actually a SETFILEINFO on a directory
5678 * handle (returned from an NT SMB). NT5.0 seems
5679 * to do this call. JRA.
5681 pstrcpy(fname, fsp->fsp_name);
5682 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5683 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5684 return UNIXERROR(ERRDOS,ERRbadpath);
5686 } else if (fsp && fsp->print_file) {
5688 * Doing a DELETE_ON_CLOSE should cancel a print job.
5690 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5691 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5693 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5696 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5699 return (UNIXERROR(ERRDOS,ERRbadpath));
5702 * Original code - this is an open file.
5704 CHECK_FSP(fsp,conn);
5706 pstrcpy(fname, fsp->fsp_name);
5708 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5709 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5710 return(UNIXERROR(ERRDOS,ERRbadfid));
5715 if (total_params < 7) {
5716 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5719 info_level = SVAL(params,0);
5720 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5721 if (!NT_STATUS_IS_OK(status)) {
5722 return ERROR_NT(status);
5725 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5726 if (!NT_STATUS_IS_OK(status)) {
5727 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5728 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5730 return ERROR_NT(status);
5733 status = unix_convert(conn, fname, False, NULL, &sbuf);
5734 if (!NT_STATUS_IS_OK(status)) {
5735 return ERROR_NT(status);
5738 status = check_name(conn, fname);
5739 if (!NT_STATUS_IS_OK(status)) {
5740 return ERROR_NT(status);
5744 * For CIFS UNIX extensions the target name may not exist.
5747 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5748 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5749 return UNIXERROR(ERRDOS,ERRbadpath);
5753 if (!CAN_WRITE(conn)) {
5754 return ERROR_DOS(ERRSRV,ERRaccess);
5757 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5758 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5761 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5762 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5764 /* Realloc the parameter size */
5765 *pparams = (char *)SMB_REALLOC(*pparams,2);
5766 if (*pparams == NULL) {
5767 return ERROR_NT(NT_STATUS_NO_MEMORY);
5773 if (fsp && !null_timespec(fsp->pending_modtime)) {
5774 /* the pending modtime overrides the current modtime */
5775 set_mtimespec(&sbuf, fsp->pending_modtime);
5778 switch (info_level) {
5780 case SMB_INFO_STANDARD:
5782 status = smb_set_info_standard(conn,
5791 case SMB_INFO_SET_EA:
5793 status = smb_info_set_ea(conn,
5801 case SMB_SET_FILE_BASIC_INFO:
5802 case SMB_FILE_BASIC_INFORMATION:
5804 status = smb_set_file_basic_info(conn,
5813 case SMB_FILE_ALLOCATION_INFORMATION:
5814 case SMB_SET_FILE_ALLOCATION_INFO:
5816 status = smb_set_file_allocation_info(conn,
5825 case SMB_FILE_END_OF_FILE_INFORMATION:
5826 case SMB_SET_FILE_END_OF_FILE_INFO:
5828 status = smb_set_file_end_of_file_info(conn,
5837 case SMB_FILE_DISPOSITION_INFORMATION:
5838 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5841 /* JRA - We used to just ignore this on a path ?
5842 * Shouldn't this be invalid level on a pathname
5845 if (tran_call != TRANSACT2_SETFILEINFO) {
5846 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5849 status = smb_set_file_disposition_info(conn,
5858 case SMB_FILE_POSITION_INFORMATION:
5860 status = smb_file_position_information(conn,
5867 /* From tridge Samba4 :
5868 * MODE_INFORMATION in setfileinfo (I have no
5869 * idea what "mode information" on a file is - it takes a value of 0,
5870 * 2, 4 or 6. What could it be?).
5873 case SMB_FILE_MODE_INFORMATION:
5875 status = smb_file_mode_information(conn,
5882 * CIFS UNIX extensions.
5885 case SMB_SET_FILE_UNIX_BASIC:
5887 status = smb_set_file_unix_basic(conn,
5896 case SMB_SET_FILE_UNIX_INFO2:
5898 status = smb_set_file_unix_info2(conn,
5907 case SMB_SET_FILE_UNIX_LINK:
5909 if (tran_call != TRANSACT2_SETPATHINFO) {
5910 /* We must have a pathname for this. */
5911 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5913 status = smb_set_file_unix_link(conn,
5921 case SMB_SET_FILE_UNIX_HLINK:
5923 if (tran_call != TRANSACT2_SETPATHINFO) {
5924 /* We must have a pathname for this. */
5925 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5927 status = smb_set_file_unix_hlink(conn,
5936 case SMB_FILE_RENAME_INFORMATION:
5938 status = smb_file_rename_information(conn,
5948 #if defined(HAVE_POSIX_ACLS)
5949 case SMB_SET_POSIX_ACL:
5951 status = smb_set_posix_acl(conn,
5961 case SMB_SET_POSIX_LOCK:
5963 if (tran_call != TRANSACT2_SETFILEINFO) {
5964 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5966 status = smb_set_posix_lock(conn,
5975 case SMB_POSIX_PATH_OPEN:
5977 if (tran_call != TRANSACT2_SETPATHINFO) {
5978 /* We must have a pathname for this. */
5979 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5982 status = smb_posix_open(conn,
5991 case SMB_POSIX_PATH_UNLINK:
5993 if (tran_call != TRANSACT2_SETPATHINFO) {
5994 /* We must have a pathname for this. */
5995 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5998 status = smb_posix_unlink(conn,
6007 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6011 if (!NT_STATUS_IS_OK(status)) {
6012 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6013 /* We have re-scheduled this call. */
6016 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6017 /* We have re-scheduled this call. */
6020 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6021 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6023 return ERROR_NT(status);
6027 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6032 /****************************************************************************
6033 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6034 ****************************************************************************/
6036 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6037 char **pparams, int total_params, char **ppdata, int total_data,
6038 unsigned int max_data_bytes)
6040 char *params = *pparams;
6041 char *pdata = *ppdata;
6043 SMB_STRUCT_STAT sbuf;
6044 NTSTATUS status = NT_STATUS_OK;
6045 struct ea_list *ea_list = NULL;
6047 if (!CAN_WRITE(conn))
6048 return ERROR_DOS(ERRSRV,ERRaccess);
6050 if (total_params < 5) {
6051 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6054 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6055 if (!NT_STATUS_IS_OK(status)) {
6056 return ERROR_NT(status);
6059 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6061 status = unix_convert(conn, directory, False, NULL, &sbuf);
6062 if (!NT_STATUS_IS_OK(status)) {
6063 return ERROR_NT(status);
6066 status = check_name(conn, directory);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6069 return ERROR_NT(status);
6072 /* Any data in this call is an EA list. */
6073 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6074 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6078 * OS/2 workplace shell seems to send SET_EA requests of "null"
6079 * length (4 bytes containing IVAL 4).
6080 * They seem to have no effect. Bug #3212. JRA.
6083 if (total_data != 4) {
6084 if (total_data < 10) {
6085 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6088 if (IVAL(pdata,0) > total_data) {
6089 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6090 IVAL(pdata,0), (unsigned int)total_data));
6091 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6094 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6097 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6099 } else if (IVAL(pdata,0) != 4) {
6100 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6103 status = create_directory(conn, directory);
6105 if (!NT_STATUS_IS_OK(status)) {
6106 return ERROR_NT(status);
6109 /* Try and set any given EA. */
6111 status = set_ea(conn, NULL, directory, ea_list);
6112 if (!NT_STATUS_IS_OK(status)) {
6113 return ERROR_NT(status);
6117 /* Realloc the parameter and data sizes */
6118 *pparams = (char *)SMB_REALLOC(*pparams,2);
6119 if(*pparams == NULL) {
6120 return ERROR_NT(NT_STATUS_NO_MEMORY);
6126 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6131 /****************************************************************************
6132 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6133 We don't actually do this - we just send a null response.
6134 ****************************************************************************/
6136 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6137 char **pparams, int total_params, char **ppdata, int total_data,
6138 unsigned int max_data_bytes)
6140 static uint16 fnf_handle = 257;
6141 char *params = *pparams;
6144 if (total_params < 6) {
6145 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6148 info_level = SVAL(params,4);
6149 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6151 switch (info_level) {
6156 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6159 /* Realloc the parameter and data sizes */
6160 *pparams = (char *)SMB_REALLOC(*pparams,6);
6161 if (*pparams == NULL) {
6162 return ERROR_NT(NT_STATUS_NO_MEMORY);
6166 SSVAL(params,0,fnf_handle);
6167 SSVAL(params,2,0); /* No changes */
6168 SSVAL(params,4,0); /* No EA errors */
6175 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6180 /****************************************************************************
6181 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6182 changes). Currently this does nothing.
6183 ****************************************************************************/
6185 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6186 char **pparams, int total_params, char **ppdata, int total_data,
6187 unsigned int max_data_bytes)
6189 char *params = *pparams;
6191 DEBUG(3,("call_trans2findnotifynext\n"));
6193 /* Realloc the parameter and data sizes */
6194 *pparams = (char *)SMB_REALLOC(*pparams,4);
6195 if (*pparams == NULL) {
6196 return ERROR_NT(NT_STATUS_NO_MEMORY);
6200 SSVAL(params,0,0); /* No changes */
6201 SSVAL(params,2,0); /* No EA errors */
6203 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6208 /****************************************************************************
6209 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6210 ****************************************************************************/
6212 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6213 char **pparams, int total_params, char **ppdata, int total_data,
6214 unsigned int max_data_bytes)
6216 char *params = *pparams;
6219 int max_referral_level;
6220 NTSTATUS status = NT_STATUS_OK;
6222 DEBUG(10,("call_trans2getdfsreferral\n"));
6224 if (total_params < 3) {
6225 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6228 max_referral_level = SVAL(params,0);
6230 if(!lp_host_msdfs())
6231 return ERROR_DOS(ERRDOS,ERRbadfunc);
6233 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6234 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6235 return ERROR_NT(status);
6237 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6238 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6243 #define LMCAT_SPL 0x53
6244 #define LMFUNC_GETJOBID 0x60
6246 /****************************************************************************
6247 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6248 ****************************************************************************/
6250 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6251 char **pparams, int total_params, char **ppdata, int total_data,
6252 unsigned int max_data_bytes)
6254 char *pdata = *ppdata;
6255 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6257 /* check for an invalid fid before proceeding */
6260 return(ERROR_DOS(ERRDOS,ERRbadfid));
6262 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6263 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6264 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6265 if (*ppdata == NULL) {
6266 return ERROR_NT(NT_STATUS_NO_MEMORY);
6270 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6271 CAN ACCEPT THIS IN UNICODE. JRA. */
6273 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6274 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6275 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6276 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6279 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6280 return ERROR_DOS(ERRSRV,ERRerror);
6284 /****************************************************************************
6285 Reply to a SMBfindclose (stop trans2 directory search).
6286 ****************************************************************************/
6288 int reply_findclose(connection_struct *conn,
6289 char *inbuf,char *outbuf,int length,int bufsize)
6292 int dptr_num=SVALS(inbuf,smb_vwv0);
6293 START_PROFILE(SMBfindclose);
6295 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6297 dptr_close(&dptr_num);
6299 outsize = set_message(inbuf, outbuf,0,0,False);
6301 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6303 END_PROFILE(SMBfindclose);
6307 /****************************************************************************
6308 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6309 ****************************************************************************/
6311 int reply_findnclose(connection_struct *conn,
6312 char *inbuf,char *outbuf,int length,int bufsize)
6316 START_PROFILE(SMBfindnclose);
6318 dptr_num = SVAL(inbuf,smb_vwv0);
6320 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6322 /* We never give out valid handles for a
6323 findnotifyfirst - so any dptr_num is ok here.
6326 outsize = set_message(inbuf, outbuf,0,0,False);
6328 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6330 END_PROFILE(SMBfindnclose);
6334 int handle_trans2(connection_struct *conn,
6335 struct trans_state *state,
6336 char *inbuf, char *outbuf, int size, int bufsize)
6340 if (Protocol >= PROTOCOL_NT1) {
6341 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6344 /* Now we must call the relevant TRANS2 function */
6345 switch(state->call) {
6346 case TRANSACT2_OPEN:
6348 START_PROFILE(Trans2_open);
6349 outsize = call_trans2open(
6350 conn, inbuf, outbuf, bufsize,
6351 &state->param, state->total_param,
6352 &state->data, state->total_data,
6353 state->max_data_return);
6354 END_PROFILE(Trans2_open);
6358 case TRANSACT2_FINDFIRST:
6360 START_PROFILE(Trans2_findfirst);
6361 outsize = call_trans2findfirst(
6362 conn, inbuf, outbuf, bufsize,
6363 &state->param, state->total_param,
6364 &state->data, state->total_data,
6365 state->max_data_return);
6366 END_PROFILE(Trans2_findfirst);
6370 case TRANSACT2_FINDNEXT:
6372 START_PROFILE(Trans2_findnext);
6373 outsize = call_trans2findnext(
6374 conn, inbuf, outbuf, size, bufsize,
6375 &state->param, state->total_param,
6376 &state->data, state->total_data,
6377 state->max_data_return);
6378 END_PROFILE(Trans2_findnext);
6382 case TRANSACT2_QFSINFO:
6384 START_PROFILE(Trans2_qfsinfo);
6385 outsize = call_trans2qfsinfo(
6386 conn, inbuf, outbuf, size, bufsize,
6387 &state->param, state->total_param,
6388 &state->data, state->total_data,
6389 state->max_data_return);
6390 END_PROFILE(Trans2_qfsinfo);
6394 case TRANSACT2_SETFSINFO:
6396 START_PROFILE(Trans2_setfsinfo);
6397 outsize = call_trans2setfsinfo(
6398 conn, inbuf, outbuf, size, bufsize,
6399 &state->param, state->total_param,
6400 &state->data, state->total_data,
6401 state->max_data_return);
6402 END_PROFILE(Trans2_setfsinfo);
6406 case TRANSACT2_QPATHINFO:
6407 case TRANSACT2_QFILEINFO:
6409 START_PROFILE(Trans2_qpathinfo);
6410 outsize = call_trans2qfilepathinfo(
6411 conn, inbuf, outbuf, size, bufsize, state->call,
6412 &state->param, state->total_param,
6413 &state->data, state->total_data,
6414 state->max_data_return);
6415 END_PROFILE(Trans2_qpathinfo);
6419 case TRANSACT2_SETPATHINFO:
6420 case TRANSACT2_SETFILEINFO:
6422 START_PROFILE(Trans2_setpathinfo);
6423 outsize = call_trans2setfilepathinfo(
6424 conn, inbuf, outbuf, size, bufsize, state->call,
6425 &state->param, state->total_param,
6426 &state->data, state->total_data,
6427 state->max_data_return);
6428 END_PROFILE(Trans2_setpathinfo);
6432 case TRANSACT2_FINDNOTIFYFIRST:
6434 START_PROFILE(Trans2_findnotifyfirst);
6435 outsize = call_trans2findnotifyfirst(
6436 conn, inbuf, outbuf, size, bufsize,
6437 &state->param, state->total_param,
6438 &state->data, state->total_data,
6439 state->max_data_return);
6440 END_PROFILE(Trans2_findnotifyfirst);
6444 case TRANSACT2_FINDNOTIFYNEXT:
6446 START_PROFILE(Trans2_findnotifynext);
6447 outsize = call_trans2findnotifynext(
6448 conn, inbuf, outbuf, size, bufsize,
6449 &state->param, state->total_param,
6450 &state->data, state->total_data,
6451 state->max_data_return);
6452 END_PROFILE(Trans2_findnotifynext);
6456 case TRANSACT2_MKDIR:
6458 START_PROFILE(Trans2_mkdir);
6459 outsize = call_trans2mkdir(
6460 conn, inbuf, outbuf, size, bufsize,
6461 &state->param, state->total_param,
6462 &state->data, state->total_data,
6463 state->max_data_return);
6464 END_PROFILE(Trans2_mkdir);
6468 case TRANSACT2_GET_DFS_REFERRAL:
6470 START_PROFILE(Trans2_get_dfs_referral);
6471 outsize = call_trans2getdfsreferral(
6472 conn, inbuf, outbuf, size, bufsize,
6473 &state->param, state->total_param,
6474 &state->data, state->total_data,
6475 state->max_data_return);
6476 END_PROFILE(Trans2_get_dfs_referral);
6480 case TRANSACT2_IOCTL:
6482 START_PROFILE(Trans2_ioctl);
6483 outsize = call_trans2ioctl(
6484 conn, inbuf, outbuf, size, bufsize,
6485 &state->param, state->total_param,
6486 &state->data, state->total_data,
6487 state->max_data_return);
6488 END_PROFILE(Trans2_ioctl);
6493 /* Error in request */
6494 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6495 outsize = ERROR_DOS(ERRSRV,ERRerror);
6501 /****************************************************************************
6502 Reply to a SMBtrans2.
6503 ****************************************************************************/
6505 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6506 int size, int bufsize)
6509 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6510 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6511 unsigned int psoff = SVAL(inbuf, smb_psoff);
6512 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6513 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6514 struct trans_state *state;
6517 START_PROFILE(SMBtrans2);
6519 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6520 if (!NT_STATUS_IS_OK(result)) {
6521 DEBUG(2, ("Got invalid trans2 request: %s\n",
6522 nt_errstr(result)));
6523 END_PROFILE(SMBtrans2);
6524 return ERROR_NT(result);
6527 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6528 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6529 END_PROFILE(SMBtrans2);
6530 return ERROR_DOS(ERRSRV,ERRaccess);
6533 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6534 DEBUG(0, ("talloc failed\n"));
6535 END_PROFILE(SMBtrans2);
6536 return ERROR_NT(NT_STATUS_NO_MEMORY);
6539 state->cmd = SMBtrans2;
6541 state->mid = SVAL(inbuf, smb_mid);
6542 state->vuid = SVAL(inbuf, smb_uid);
6543 state->setup_count = SVAL(inbuf, smb_suwcnt);
6544 state->setup = NULL;
6545 state->total_param = SVAL(inbuf, smb_tpscnt);
6546 state->param = NULL;
6547 state->total_data = SVAL(inbuf, smb_tdscnt);
6549 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6550 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6551 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6552 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6553 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6555 state->call = tran_call;
6557 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6558 is so as a sanity check */
6559 if (state->setup_count != 1) {
6561 * Need to have rc=0 for ioctl to get job id for OS/2.
6562 * Network printing will fail if function is not successful.
6563 * Similar function in reply.c will be used if protocol
6564 * is LANMAN1.0 instead of LM1.2X002.
6565 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6566 * outbuf doesn't have to be set(only job id is used).
6568 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6569 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6570 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6571 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6573 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6574 DEBUG(2,("Transaction is %d\n",tran_call));
6576 END_PROFILE(SMBtrans2);
6577 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6581 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6584 if (state->total_data) {
6585 /* Can't use talloc here, the core routines do realloc on the
6586 * params and data. */
6587 state->data = (char *)SMB_MALLOC(state->total_data);
6588 if (state->data == NULL) {
6589 DEBUG(0,("reply_trans2: data malloc fail for %u "
6590 "bytes !\n", (unsigned int)state->total_data));
6592 END_PROFILE(SMBtrans2);
6593 return(ERROR_DOS(ERRDOS,ERRnomem));
6595 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6597 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6598 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6601 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6604 if (state->total_param) {
6605 /* Can't use talloc here, the core routines do realloc on the
6606 * params and data. */
6607 state->param = (char *)SMB_MALLOC(state->total_param);
6608 if (state->param == NULL) {
6609 DEBUG(0,("reply_trans: param malloc fail for %u "
6610 "bytes !\n", (unsigned int)state->total_param));
6611 SAFE_FREE(state->data);
6613 END_PROFILE(SMBtrans2);
6614 return(ERROR_DOS(ERRDOS,ERRnomem));
6616 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6618 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6619 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6622 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6625 state->received_data = dscnt;
6626 state->received_param = pscnt;
6628 if ((state->received_param == state->total_param) &&
6629 (state->received_data == state->total_data)) {
6631 outsize = handle_trans2(conn, state, inbuf, outbuf,
6633 SAFE_FREE(state->data);
6634 SAFE_FREE(state->param);
6636 END_PROFILE(SMBtrans2);
6640 DLIST_ADD(conn->pending_trans, state);
6642 /* We need to send an interim response then receive the rest
6643 of the parameter/data bytes */
6644 outsize = set_message(inbuf, outbuf,0,0,False);
6646 END_PROFILE(SMBtrans2);
6651 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6652 SAFE_FREE(state->data);
6653 SAFE_FREE(state->param);
6655 END_PROFILE(SMBtrans2);
6656 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6660 /****************************************************************************
6661 Reply to a SMBtranss2
6662 ****************************************************************************/
6664 int reply_transs2(connection_struct *conn,
6665 char *inbuf,char *outbuf,int size,int bufsize)
6668 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6669 struct trans_state *state;
6671 START_PROFILE(SMBtranss2);
6675 for (state = conn->pending_trans; state != NULL;
6676 state = state->next) {
6677 if (state->mid == SVAL(inbuf,smb_mid)) {
6682 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6683 END_PROFILE(SMBtranss2);
6684 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6687 /* Revise state->total_param and state->total_data in case they have
6688 changed downwards */
6690 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6691 state->total_param = SVAL(inbuf, smb_tpscnt);
6692 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6693 state->total_data = SVAL(inbuf, smb_tdscnt);
6695 pcnt = SVAL(inbuf, smb_spscnt);
6696 poff = SVAL(inbuf, smb_spsoff);
6697 pdisp = SVAL(inbuf, smb_spsdisp);
6699 dcnt = SVAL(inbuf, smb_sdscnt);
6700 doff = SVAL(inbuf, smb_sdsoff);
6701 ddisp = SVAL(inbuf, smb_sdsdisp);
6703 state->received_param += pcnt;
6704 state->received_data += dcnt;
6706 if ((state->received_data > state->total_data) ||
6707 (state->received_param > state->total_param))
6711 if (pdisp+pcnt > state->total_param)
6713 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6715 if (pdisp > state->total_param)
6717 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6718 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6720 if (state->param + pdisp < state->param)
6723 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6728 if (ddisp+dcnt > state->total_data)
6730 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6732 if (ddisp > state->total_data)
6734 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6735 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6737 if (state->data + ddisp < state->data)
6740 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6744 if ((state->received_param < state->total_param) ||
6745 (state->received_data < state->total_data)) {
6746 END_PROFILE(SMBtranss2);
6750 /* construct_reply_common has done us the favor to pre-fill the
6751 * command field with SMBtranss2 which is wrong :-)
6753 SCVAL(outbuf,smb_com,SMBtrans2);
6755 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6757 DLIST_REMOVE(conn->pending_trans, state);
6758 SAFE_FREE(state->data);
6759 SAFE_FREE(state->param);
6763 END_PROFILE(SMBtranss2);
6764 return(ERROR_DOS(ERRSRV,ERRnosupport));
6767 END_PROFILE(SMBtranss2);
6772 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6773 DLIST_REMOVE(conn->pending_trans, state);
6774 SAFE_FREE(state->data);
6775 SAFE_FREE(state->param);
6777 END_PROFILE(SMBtranss2);
6778 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);