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,
744 struct smb_request *req,
745 char *inbuf, char *outbuf, int bufsize,
746 char **pparams, int total_params,
747 char **ppdata, int total_data,
748 unsigned int max_data_bytes)
750 char *params = *pparams;
751 char *pdata = *ppdata;
756 BOOL return_additional_info;
767 SMB_STRUCT_STAT sbuf;
770 struct ea_list *ea_list = NULL;
775 uint32 create_disposition;
776 uint32 create_options = 0;
779 * Ensure we have enough parameters to perform the operation.
782 if (total_params < 29) {
783 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
786 flags = SVAL(params, 0);
787 deny_mode = SVAL(params, 2);
788 open_attr = SVAL(params,6);
789 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
790 if (oplock_request) {
791 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
795 return_additional_info = BITSETW(params,0);
796 open_sattr = SVAL(params, 4);
797 open_time = make_unix_date3(params+8);
799 open_ofun = SVAL(params,12);
800 open_size = IVAL(params,14);
804 return(ERROR_DOS(ERRSRV,ERRaccess));
807 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
808 if (!NT_STATUS_IS_OK(status)) {
809 return ERROR_NT(status);
812 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
813 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
814 (unsigned int)open_ofun, open_size));
816 /* XXXX we need to handle passed times, sattr and flags */
818 status = unix_convert(conn, fname, False, NULL, &sbuf);
819 if (!NT_STATUS_IS_OK(status)) {
820 return ERROR_NT(status);
823 status = check_name(conn, fname);
824 if (!NT_STATUS_IS_OK(status)) {
825 return ERROR_NT(status);
828 if (open_ofun == 0) {
829 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
832 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
837 return ERROR_DOS(ERRDOS, ERRbadaccess);
840 /* Any data in this call is an EA list. */
841 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
842 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
845 if (total_data != 4) {
846 if (total_data < 10) {
847 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
850 if (IVAL(pdata,0) > total_data) {
851 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
852 IVAL(pdata,0), (unsigned int)total_data));
853 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
856 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
859 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
861 } else if (IVAL(pdata,0) != 4) {
862 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
865 status = open_file_ntcreate(conn, req, fname, &sbuf,
874 if (!NT_STATUS_IS_OK(status)) {
875 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
876 /* We have re-scheduled this call. */
879 return ERROR_NT(status);
882 size = get_file_size(sbuf);
883 fattr = dos_mode(conn,fname,&sbuf);
884 mtime = sbuf.st_mtime;
887 close_file(fsp,ERROR_CLOSE);
888 return(ERROR_DOS(ERRDOS,ERRnoaccess));
891 /* Save the requested allocation size. */
892 /* Allocate space for the file if a size hint is supplied */
893 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
894 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
895 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
896 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
897 if (fsp->is_directory) {
898 close_file(fsp,ERROR_CLOSE);
899 /* Can't set allocation size on a directory. */
900 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
902 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
903 close_file(fsp,ERROR_CLOSE);
904 return ERROR_NT(NT_STATUS_DISK_FULL);
907 /* Adjust size here to return the right size in the reply.
908 Windows does it this way. */
909 size = fsp->initial_allocation_size;
911 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
915 if (ea_list && smb_action == FILE_WAS_CREATED) {
916 status = set_ea(conn, fsp, fname, ea_list);
917 if (!NT_STATUS_IS_OK(status)) {
918 close_file(fsp,ERROR_CLOSE);
919 return ERROR_NT(status);
923 /* Realloc the size of parameters and data we will return */
924 *pparams = (char *)SMB_REALLOC(*pparams, 30);
925 if(*pparams == NULL ) {
926 return ERROR_NT(NT_STATUS_NO_MEMORY);
930 SSVAL(params,0,fsp->fnum);
931 SSVAL(params,2,fattr);
932 srv_put_dos_date2(params,4, mtime);
933 SIVAL(params,8, (uint32)size);
934 SSVAL(params,12,deny_mode);
935 SSVAL(params,14,0); /* open_type - file or directory. */
936 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
938 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
939 smb_action |= EXTENDED_OPLOCK_GRANTED;
942 SSVAL(params,18,smb_action);
945 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
947 SIVAL(params,20,inode);
948 SSVAL(params,24,0); /* Padding. */
950 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
951 SIVAL(params, 26, ea_size);
953 SIVAL(params, 26, 0);
956 /* Send the required number of replies */
957 send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
962 /*********************************************************
963 Routine to check if a given string matches exactly.
964 as a special case a mask of "." does NOT match. That
965 is required for correct wildcard semantics
966 Case can be significant or not.
967 **********************************************************/
969 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
971 if (mask[0] == '.' && mask[1] == 0)
973 if (conn->case_sensitive)
974 return strcmp(str,mask)==0;
975 if (StrCaseCmp(str,mask) != 0) {
978 if (dptr_has_wild(conn->dirptr)) {
984 /****************************************************************************
985 Return the filetype for UNIX extensions.
986 ****************************************************************************/
988 static uint32 unix_filetype(mode_t mode)
991 return UNIX_TYPE_FILE;
992 else if(S_ISDIR(mode))
993 return UNIX_TYPE_DIR;
995 else if(S_ISLNK(mode))
996 return UNIX_TYPE_SYMLINK;
999 else if(S_ISCHR(mode))
1000 return UNIX_TYPE_CHARDEV;
1003 else if(S_ISBLK(mode))
1004 return UNIX_TYPE_BLKDEV;
1007 else if(S_ISFIFO(mode))
1008 return UNIX_TYPE_FIFO;
1011 else if(S_ISSOCK(mode))
1012 return UNIX_TYPE_SOCKET;
1015 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1016 return UNIX_TYPE_UNKNOWN;
1019 /****************************************************************************
1020 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1021 ****************************************************************************/
1023 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1025 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1026 SMB_STRUCT_STAT *psbuf,
1028 enum perm_type ptype,
1033 if (perms == SMB_MODE_NO_CHANGE) {
1034 if (!VALID_STAT(*psbuf)) {
1035 return NT_STATUS_INVALID_PARAMETER;
1037 *ret_perms = psbuf->st_mode;
1038 return NT_STATUS_OK;
1042 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1043 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1044 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1045 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1046 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1047 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1048 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1049 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1050 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1052 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1055 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1058 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1063 /* Apply mode mask */
1064 ret &= lp_create_mask(SNUM(conn));
1065 /* Add in force bits */
1066 ret |= lp_force_create_mode(SNUM(conn));
1069 ret &= lp_dir_mask(SNUM(conn));
1070 /* Add in force bits */
1071 ret |= lp_force_dir_mode(SNUM(conn));
1073 case PERM_EXISTING_FILE:
1074 /* Apply mode mask */
1075 ret &= lp_security_mask(SNUM(conn));
1076 /* Add in force bits */
1077 ret |= lp_force_security_mode(SNUM(conn));
1079 case PERM_EXISTING_DIR:
1080 /* Apply mode mask */
1081 ret &= lp_dir_security_mask(SNUM(conn));
1082 /* Add in force bits */
1083 ret |= lp_force_dir_security_mode(SNUM(conn));
1088 return NT_STATUS_OK;
1091 /****************************************************************************
1092 Get a level dependent lanman2 dir entry.
1093 ****************************************************************************/
1095 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1096 void *inbuf, char *outbuf,
1097 char *path_mask,uint32 dirtype,int info_level,
1098 int requires_resume_key,
1099 BOOL dont_descend,char **ppdata,
1100 char *base_data, int space_remaining,
1101 BOOL *out_of_space, BOOL *got_exact_match,
1102 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1106 SMB_STRUCT_STAT sbuf;
1110 char *p, *q, *pdata = *ppdata;
1114 SMB_OFF_T file_size = 0;
1115 SMB_BIG_UINT allocation_size = 0;
1117 struct timespec mdate_ts, adate_ts, create_date_ts;
1118 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1120 char *last_entry_ptr;
1122 uint32 nt_extmode; /* Used for NT connections instead of mode */
1123 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1124 BOOL check_mangled_names = lp_manglednames(conn->params);
1127 *out_of_space = False;
1128 *got_exact_match = False;
1130 ZERO_STRUCT(mdate_ts);
1131 ZERO_STRUCT(adate_ts);
1132 ZERO_STRUCT(create_date_ts);
1137 p = strrchr_m(path_mask,'/');
1140 pstrcpy(mask,"*.*");
1144 pstrcpy(mask, path_mask);
1149 BOOL ms_dfs_link = False;
1151 /* Needed if we run out of space */
1152 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1153 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1156 * Due to bugs in NT client redirectors we are not using
1157 * resume keys any more - set them to zero.
1158 * Check out the related comments in findfirst/findnext.
1164 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1165 (long)conn->dirptr,curr_dirpos));
1172 * fname may get mangled, dname is never mangled.
1173 * Whenever we're accessing the filesystem we use
1174 * pathreal which is composed from dname.
1177 pstrcpy(fname,dname);
1179 /* This will mangle fname if it's an illegal name. */
1180 mangle_map(fname,False,True,conn->params);
1182 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1183 got_match = mask_match(fname, mask, conn->case_sensitive);
1186 if(!got_match && check_mangled_names &&
1187 !mangle_is_8_3(fname, False, conn->params)) {
1188 pstring mangled_name;
1191 * It turns out that NT matches wildcards against
1192 * both long *and* short names. This may explain some
1193 * of the wildcard wierdness from old DOS clients
1194 * that some people have been seeing.... JRA.
1197 pstrcpy(mangled_name, fname);
1199 /* Force the mangling into 8.3. */
1200 mangle_map( mangled_name, True, False, conn->params);
1201 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1202 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1207 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1208 if (dont_descend && !isdots) {
1212 pstrcpy(pathreal,conn->dirpath);
1214 pstrcat(pathreal,"/");
1216 pstrcat(pathreal,dname);
1218 if (INFO_LEVEL_IS_UNIX(info_level)) {
1219 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1220 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1221 pathreal,strerror(errno)));
1224 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1225 pstring link_target;
1227 /* Needed to show the msdfs symlinks as
1230 if(lp_host_msdfs() &&
1231 lp_msdfs_root(SNUM(conn)) &&
1232 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1233 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1236 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1240 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1241 pathreal,strerror(errno)));
1247 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1249 mode = dos_mode(conn,pathreal,&sbuf);
1252 if (!dir_check_ftype(conn,mode,dirtype)) {
1253 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1257 if (!(mode & aDIR)) {
1258 file_size = get_file_size(sbuf);
1260 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1262 mdate_ts = get_mtimespec(&sbuf);
1263 adate_ts = get_atimespec(&sbuf);
1264 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1266 if (lp_dos_filetime_resolution(SNUM(conn))) {
1267 dos_filetime_timespec(&create_date_ts);
1268 dos_filetime_timespec(&mdate_ts);
1269 dos_filetime_timespec(&adate_ts);
1272 create_date = convert_timespec_to_time_t(create_date_ts);
1273 mdate = convert_timespec_to_time_t(mdate_ts);
1274 adate = convert_timespec_to_time_t(adate_ts);
1276 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1280 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1287 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1289 switch (info_level) {
1290 case SMB_FIND_INFO_STANDARD:
1291 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1292 if(requires_resume_key) {
1296 srv_put_dos_date2(p,0,create_date);
1297 srv_put_dos_date2(p,4,adate);
1298 srv_put_dos_date2(p,8,mdate);
1299 SIVAL(p,12,(uint32)file_size);
1300 SIVAL(p,16,(uint32)allocation_size);
1304 p += align_string(outbuf, p, 0);
1305 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1306 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1308 SCVAL(nameptr, -1, len - 2);
1310 SCVAL(nameptr, -1, 0);
1314 SCVAL(nameptr, -1, len - 1);
1316 SCVAL(nameptr, -1, 0);
1322 case SMB_FIND_EA_SIZE:
1323 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1324 if(requires_resume_key) {
1328 srv_put_dos_date2(p,0,create_date);
1329 srv_put_dos_date2(p,4,adate);
1330 srv_put_dos_date2(p,8,mdate);
1331 SIVAL(p,12,(uint32)file_size);
1332 SIVAL(p,16,(uint32)allocation_size);
1335 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1336 SIVAL(p,22,ea_size); /* Extended attributes */
1340 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1341 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1354 SCVAL(nameptr,0,len);
1356 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1359 case SMB_FIND_EA_LIST:
1361 struct ea_list *file_list = NULL;
1364 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1368 if(requires_resume_key) {
1372 srv_put_dos_date2(p,0,create_date);
1373 srv_put_dos_date2(p,4,adate);
1374 srv_put_dos_date2(p,8,mdate);
1375 SIVAL(p,12,(uint32)file_size);
1376 SIVAL(p,16,(uint32)allocation_size);
1378 p += 22; /* p now points to the EA area. */
1380 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1381 name_list = ea_list_union(name_list, file_list, &ea_len);
1383 /* We need to determine if this entry will fit in the space available. */
1384 /* Max string size is 255 bytes. */
1385 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1386 /* Move the dirptr back to prev_dirpos */
1387 dptr_SeekDir(conn->dirptr, prev_dirpos);
1388 *out_of_space = True;
1389 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1390 return False; /* Not finished - just out of space */
1393 /* Push the ea_data followed by the name. */
1394 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1396 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1397 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1410 SCVAL(nameptr,0,len);
1412 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1416 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1417 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1418 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1420 SIVAL(p,0,reskey); p += 4;
1421 put_long_date_timespec(p,create_date_ts); p += 8;
1422 put_long_date_timespec(p,adate_ts); p += 8;
1423 put_long_date_timespec(p,mdate_ts); p += 8;
1424 put_long_date_timespec(p,mdate_ts); p += 8;
1425 SOFF_T(p,0,file_size); p += 8;
1426 SOFF_T(p,0,allocation_size); p += 8;
1427 SIVAL(p,0,nt_extmode); p += 4;
1428 q = p; p += 4; /* q is placeholder for name length. */
1430 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1431 SIVAL(p,0,ea_size); /* Extended attributes */
1434 /* Clear the short name buffer. This is
1435 * IMPORTANT as not doing so will trigger
1436 * a Win2k client bug. JRA.
1438 if (!was_8_3 && check_mangled_names) {
1439 pstring mangled_name;
1440 pstrcpy(mangled_name, fname);
1441 mangle_map(mangled_name,True,True,
1443 mangled_name[12] = 0;
1444 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1446 memset(p + 2 + len,'\0',24 - len);
1453 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1456 SIVAL(p,0,0); /* Ensure any padding is null. */
1457 len = PTR_DIFF(p, pdata);
1458 len = (len + 3) & ~3;
1463 case SMB_FIND_FILE_DIRECTORY_INFO:
1464 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1466 SIVAL(p,0,reskey); p += 4;
1467 put_long_date_timespec(p,create_date_ts); p += 8;
1468 put_long_date_timespec(p,adate_ts); p += 8;
1469 put_long_date_timespec(p,mdate_ts); p += 8;
1470 put_long_date_timespec(p,mdate_ts); p += 8;
1471 SOFF_T(p,0,file_size); p += 8;
1472 SOFF_T(p,0,allocation_size); p += 8;
1473 SIVAL(p,0,nt_extmode); p += 4;
1474 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1477 SIVAL(p,0,0); /* Ensure any padding is null. */
1478 len = PTR_DIFF(p, pdata);
1479 len = (len + 3) & ~3;
1484 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1485 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1487 SIVAL(p,0,reskey); p += 4;
1488 put_long_date_timespec(p,create_date_ts); p += 8;
1489 put_long_date_timespec(p,adate_ts); p += 8;
1490 put_long_date_timespec(p,mdate_ts); p += 8;
1491 put_long_date_timespec(p,mdate_ts); p += 8;
1492 SOFF_T(p,0,file_size); p += 8;
1493 SOFF_T(p,0,allocation_size); p += 8;
1494 SIVAL(p,0,nt_extmode); p += 4;
1495 q = p; p += 4; /* q is placeholder for name length. */
1497 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1498 SIVAL(p,0,ea_size); /* Extended attributes */
1501 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1505 SIVAL(p,0,0); /* Ensure any padding is null. */
1506 len = PTR_DIFF(p, pdata);
1507 len = (len + 3) & ~3;
1512 case SMB_FIND_FILE_NAMES_INFO:
1513 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1515 SIVAL(p,0,reskey); p += 4;
1517 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1518 acl on a dir (tridge) */
1519 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1522 SIVAL(p,0,0); /* Ensure any padding is null. */
1523 len = PTR_DIFF(p, pdata);
1524 len = (len + 3) & ~3;
1529 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1530 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1532 SIVAL(p,0,reskey); p += 4;
1533 put_long_date_timespec(p,create_date_ts); p += 8;
1534 put_long_date_timespec(p,adate_ts); p += 8;
1535 put_long_date_timespec(p,mdate_ts); p += 8;
1536 put_long_date_timespec(p,mdate_ts); p += 8;
1537 SOFF_T(p,0,file_size); p += 8;
1538 SOFF_T(p,0,allocation_size); p += 8;
1539 SIVAL(p,0,nt_extmode); p += 4;
1540 q = p; p += 4; /* q is placeholder for name length. */
1542 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1543 SIVAL(p,0,ea_size); /* Extended attributes */
1546 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1547 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1548 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1549 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1552 SIVAL(p,0,0); /* Ensure any padding is null. */
1553 len = PTR_DIFF(p, pdata);
1554 len = (len + 3) & ~3;
1559 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1560 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1561 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1563 SIVAL(p,0,reskey); p += 4;
1564 put_long_date_timespec(p,create_date_ts); p += 8;
1565 put_long_date_timespec(p,adate_ts); p += 8;
1566 put_long_date_timespec(p,mdate_ts); p += 8;
1567 put_long_date_timespec(p,mdate_ts); p += 8;
1568 SOFF_T(p,0,file_size); p += 8;
1569 SOFF_T(p,0,allocation_size); p += 8;
1570 SIVAL(p,0,nt_extmode); p += 4;
1571 q = p; p += 4; /* q is placeholder for name length */
1573 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1574 SIVAL(p,0,ea_size); /* Extended attributes */
1577 /* Clear the short name buffer. This is
1578 * IMPORTANT as not doing so will trigger
1579 * a Win2k client bug. JRA.
1581 if (!was_8_3 && check_mangled_names) {
1582 pstring mangled_name;
1583 pstrcpy(mangled_name, fname);
1584 mangle_map(mangled_name,True,True,
1586 mangled_name[12] = 0;
1587 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1590 memset(p + 2 + len,'\0',24 - len);
1597 SSVAL(p,0,0); p += 2; /* Reserved ? */
1598 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1599 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1600 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1603 SIVAL(p,0,0); /* Ensure any padding is null. */
1604 len = PTR_DIFF(p, pdata);
1605 len = (len + 3) & ~3;
1610 /* CIFS UNIX Extension. */
1612 case SMB_FIND_FILE_UNIX:
1613 case SMB_FIND_FILE_UNIX_INFO2:
1615 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1617 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1619 if (info_level == SMB_FIND_FILE_UNIX) {
1620 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1621 p = store_file_unix_basic(conn, p,
1623 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1625 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1626 p = store_file_unix_basic_info2(conn, p,
1630 len = srvstr_push(outbuf, p, fname, -1, 0);
1631 SIVAL(nameptr, 0, len);
1635 SIVAL(p,0,0); /* Ensure any padding is null. */
1637 len = PTR_DIFF(p, pdata);
1638 len = (len + 3) & ~3;
1639 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1641 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1650 if (PTR_DIFF(p,pdata) > space_remaining) {
1651 /* Move the dirptr back to prev_dirpos */
1652 dptr_SeekDir(conn->dirptr, prev_dirpos);
1653 *out_of_space = True;
1654 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1655 return False; /* Not finished - just out of space */
1658 /* Setup the last entry pointer, as an offset from base_data */
1659 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1660 /* Advance the data pointer to the next slot */
1666 /****************************************************************************
1667 Reply to a TRANS2_FINDFIRST.
1668 ****************************************************************************/
1670 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1671 char **pparams, int total_params, char **ppdata, int total_data,
1672 unsigned int max_data_bytes)
1674 /* We must be careful here that we don't return more than the
1675 allowed number of data bytes. If this means returning fewer than
1676 maxentries then so be it. We assume that the redirector has
1677 enough room for the fixed number of parameter bytes it has
1679 char *params = *pparams;
1680 char *pdata = *ppdata;
1683 uint16 findfirst_flags;
1684 BOOL close_after_first;
1686 BOOL requires_resume_key;
1691 int last_entry_off=0;
1695 BOOL finished = False;
1696 BOOL dont_descend = False;
1697 BOOL out_of_space = False;
1698 int space_remaining;
1699 BOOL mask_contains_wcard = False;
1700 SMB_STRUCT_STAT sbuf;
1701 TALLOC_CTX *ea_ctx = NULL;
1702 struct ea_list *ea_list = NULL;
1703 NTSTATUS ntstatus = NT_STATUS_OK;
1705 if (total_params < 13) {
1706 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1709 dirtype = SVAL(params,0);
1710 maxentries = SVAL(params,2);
1711 findfirst_flags = SVAL(params,4);
1712 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1713 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1714 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1715 info_level = SVAL(params,6);
1717 *directory = *mask = 0;
1719 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1720 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1721 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1722 info_level, max_data_bytes));
1725 /* W2K3 seems to treat zero as 1. */
1729 switch (info_level) {
1730 case SMB_FIND_INFO_STANDARD:
1731 case SMB_FIND_EA_SIZE:
1732 case SMB_FIND_EA_LIST:
1733 case SMB_FIND_FILE_DIRECTORY_INFO:
1734 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1735 case SMB_FIND_FILE_NAMES_INFO:
1736 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1737 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1738 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1740 case SMB_FIND_FILE_UNIX:
1741 case SMB_FIND_FILE_UNIX_INFO2:
1742 if (!lp_unix_extensions()) {
1743 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1747 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1750 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1751 if (!NT_STATUS_IS_OK(ntstatus)) {
1752 return ERROR_NT(ntstatus);
1755 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1756 if (!NT_STATUS_IS_OK(ntstatus)) {
1757 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1758 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1760 return ERROR_NT(ntstatus);
1763 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1764 if (!NT_STATUS_IS_OK(ntstatus)) {
1765 return ERROR_NT(ntstatus);
1767 ntstatus = check_name(conn, directory);
1768 if (!NT_STATUS_IS_OK(ntstatus)) {
1769 return ERROR_NT(ntstatus);
1772 p = strrchr_m(directory,'/');
1774 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1775 if((directory[0] == '.') && (directory[1] == '\0')) {
1777 mask_contains_wcard = True;
1779 pstrcpy(mask,directory);
1781 pstrcpy(directory,"./");
1787 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1789 if (info_level == SMB_FIND_EA_LIST) {
1792 if (total_data < 4) {
1793 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1796 ea_size = IVAL(pdata,0);
1797 if (ea_size != total_data) {
1798 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1799 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1800 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1803 if (!lp_ea_support(SNUM(conn))) {
1804 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1807 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1808 return ERROR_NT(NT_STATUS_NO_MEMORY);
1811 /* Pull out the list of names. */
1812 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1814 talloc_destroy(ea_ctx);
1815 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1819 *ppdata = (char *)SMB_REALLOC(
1820 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1821 if(*ppdata == NULL ) {
1822 talloc_destroy(ea_ctx);
1823 return ERROR_NT(NT_STATUS_NO_MEMORY);
1827 /* Realloc the params space */
1828 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1829 if (*pparams == NULL) {
1830 talloc_destroy(ea_ctx);
1831 return ERROR_NT(NT_STATUS_NO_MEMORY);
1835 /* Save the wildcard match and attribs we are using on this directory -
1836 needed as lanman2 assumes these are being saved between calls */
1838 ntstatus = dptr_create(conn,
1842 SVAL(inbuf,smb_pid),
1844 mask_contains_wcard,
1848 if (!NT_STATUS_IS_OK(ntstatus)) {
1849 talloc_destroy(ea_ctx);
1850 return ERROR_NT(ntstatus);
1853 dptr_num = dptr_dnum(conn->dirptr);
1854 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1856 /* We don't need to check for VOL here as this is returned by
1857 a different TRANS2 call. */
1859 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1860 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1861 dont_descend = True;
1864 space_remaining = max_data_bytes;
1865 out_of_space = False;
1867 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1868 BOOL got_exact_match = False;
1870 /* this is a heuristic to avoid seeking the dirptr except when
1871 absolutely necessary. It allows for a filename of about 40 chars */
1872 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1873 out_of_space = True;
1876 finished = !get_lanman2_dir_entry(conn,
1878 mask,dirtype,info_level,
1879 requires_resume_key,dont_descend,
1880 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1881 &last_entry_off, ea_list, ea_ctx);
1884 if (finished && out_of_space)
1887 if (!finished && !out_of_space)
1891 * As an optimisation if we know we aren't looking
1892 * for a wildcard name (ie. the name matches the wildcard exactly)
1893 * then we can finish on any (first) match.
1894 * This speeds up large directory searches. JRA.
1900 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1903 talloc_destroy(ea_ctx);
1905 /* Check if we can close the dirptr */
1906 if(close_after_first || (finished && close_if_end)) {
1907 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1908 dptr_close(&dptr_num);
1912 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1913 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1914 * the protocol level is less than NT1. Tested with smbclient. JRA.
1915 * This should fix the OS/2 client bug #2335.
1918 if(numentries == 0) {
1919 dptr_close(&dptr_num);
1920 if (Protocol < PROTOCOL_NT1) {
1921 return ERROR_DOS(ERRDOS,ERRnofiles);
1923 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1927 /* At this point pdata points to numentries directory entries. */
1929 /* Set up the return parameter block */
1930 SSVAL(params,0,dptr_num);
1931 SSVAL(params,2,numentries);
1932 SSVAL(params,4,finished);
1933 SSVAL(params,6,0); /* Never an EA error */
1934 SSVAL(params,8,last_entry_off);
1936 send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1938 if ((! *directory) && dptr_path(dptr_num))
1939 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1941 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1942 smb_fn_name(CVAL(inbuf,smb_com)),
1943 mask, directory, dirtype, numentries ) );
1946 * Force a name mangle here to ensure that the
1947 * mask as an 8.3 name is top of the mangled cache.
1948 * The reasons for this are subtle. Don't remove
1949 * this code unless you know what you are doing
1950 * (see PR#13758). JRA.
1953 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1954 mangle_map(mask, True, True, conn->params);
1959 /****************************************************************************
1960 Reply to a TRANS2_FINDNEXT.
1961 ****************************************************************************/
1963 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1964 char **pparams, int total_params, char **ppdata, int total_data,
1965 unsigned int max_data_bytes)
1967 /* We must be careful here that we don't return more than the
1968 allowed number of data bytes. If this means returning fewer than
1969 maxentries then so be it. We assume that the redirector has
1970 enough room for the fixed number of parameter bytes it has
1972 char *params = *pparams;
1973 char *pdata = *ppdata;
1978 uint16 findnext_flags;
1979 BOOL close_after_request;
1981 BOOL requires_resume_key;
1983 BOOL mask_contains_wcard = False;
1984 pstring resume_name;
1990 int i, last_entry_off=0;
1991 BOOL finished = False;
1992 BOOL dont_descend = False;
1993 BOOL out_of_space = False;
1994 int space_remaining;
1995 TALLOC_CTX *ea_ctx = NULL;
1996 struct ea_list *ea_list = NULL;
1997 NTSTATUS ntstatus = NT_STATUS_OK;
1999 if (total_params < 13) {
2000 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2003 dptr_num = SVAL(params,0);
2004 maxentries = SVAL(params,2);
2005 info_level = SVAL(params,4);
2006 resume_key = IVAL(params,6);
2007 findnext_flags = SVAL(params,10);
2008 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2009 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2010 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2011 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2013 *mask = *directory = *resume_name = 0;
2015 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2016 if (!NT_STATUS_IS_OK(ntstatus)) {
2017 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2018 complain (it thinks we're asking for the directory above the shared
2019 path or an invalid name). Catch this as the resume name is only compared, never used in
2020 a file access. JRA. */
2021 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2022 pstrcpy(resume_name, "..");
2023 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2024 pstrcpy(resume_name, ".");
2026 return ERROR_NT(ntstatus);
2030 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2031 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2032 resume_key = %d resume name = %s continue=%d level = %d\n",
2033 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2034 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2037 /* W2K3 seems to treat zero as 1. */
2041 switch (info_level) {
2042 case SMB_FIND_INFO_STANDARD:
2043 case SMB_FIND_EA_SIZE:
2044 case SMB_FIND_EA_LIST:
2045 case SMB_FIND_FILE_DIRECTORY_INFO:
2046 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2047 case SMB_FIND_FILE_NAMES_INFO:
2048 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2049 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2050 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2052 case SMB_FIND_FILE_UNIX:
2053 case SMB_FIND_FILE_UNIX_INFO2:
2054 if (!lp_unix_extensions()) {
2055 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2059 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2062 if (info_level == SMB_FIND_EA_LIST) {
2065 if (total_data < 4) {
2066 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2069 ea_size = IVAL(pdata,0);
2070 if (ea_size != total_data) {
2071 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2072 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2073 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2076 if (!lp_ea_support(SNUM(conn))) {
2077 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2080 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2081 return ERROR_NT(NT_STATUS_NO_MEMORY);
2084 /* Pull out the list of names. */
2085 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2087 talloc_destroy(ea_ctx);
2088 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2092 *ppdata = (char *)SMB_REALLOC(
2093 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2094 if(*ppdata == NULL) {
2095 talloc_destroy(ea_ctx);
2096 return ERROR_NT(NT_STATUS_NO_MEMORY);
2101 /* Realloc the params space */
2102 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2103 if(*pparams == NULL ) {
2104 talloc_destroy(ea_ctx);
2105 return ERROR_NT(NT_STATUS_NO_MEMORY);
2110 /* Check that the dptr is valid */
2111 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2112 talloc_destroy(ea_ctx);
2113 return ERROR_DOS(ERRDOS,ERRnofiles);
2116 string_set(&conn->dirpath,dptr_path(dptr_num));
2118 /* Get the wildcard mask from the dptr */
2119 if((p = dptr_wcard(dptr_num))== NULL) {
2120 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2121 talloc_destroy(ea_ctx);
2122 return ERROR_DOS(ERRDOS,ERRnofiles);
2126 pstrcpy(directory,conn->dirpath);
2128 /* Get the attr mask from the dptr */
2129 dirtype = dptr_attr(dptr_num);
2131 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2132 dptr_num, mask, dirtype,
2134 dptr_TellDir(conn->dirptr)));
2136 /* We don't need to check for VOL here as this is returned by
2137 a different TRANS2 call. */
2139 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2140 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2141 dont_descend = True;
2144 space_remaining = max_data_bytes;
2145 out_of_space = False;
2148 * Seek to the correct position. We no longer use the resume key but
2149 * depend on the last file name instead.
2152 if(*resume_name && !continue_bit) {
2155 long current_pos = 0;
2157 * Remember, mangle_map is called by
2158 * get_lanman2_dir_entry(), so the resume name
2159 * could be mangled. Ensure we check the unmangled name.
2162 if (mangle_is_mangled(resume_name, conn->params)) {
2163 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2168 * Fix for NT redirector problem triggered by resume key indexes
2169 * changing between directory scans. We now return a resume key of 0
2170 * and instead look for the filename to continue from (also given
2171 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2172 * findfirst/findnext (as is usual) then the directory pointer
2173 * should already be at the correct place.
2176 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2177 } /* end if resume_name && !continue_bit */
2179 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2180 BOOL got_exact_match = False;
2182 /* this is a heuristic to avoid seeking the dirptr except when
2183 absolutely necessary. It allows for a filename of about 40 chars */
2184 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2185 out_of_space = True;
2188 finished = !get_lanman2_dir_entry(conn,
2190 mask,dirtype,info_level,
2191 requires_resume_key,dont_descend,
2192 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2193 &last_entry_off, ea_list, ea_ctx);
2196 if (finished && out_of_space)
2199 if (!finished && !out_of_space)
2203 * As an optimisation if we know we aren't looking
2204 * for a wildcard name (ie. the name matches the wildcard exactly)
2205 * then we can finish on any (first) match.
2206 * This speeds up large directory searches. JRA.
2212 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2215 talloc_destroy(ea_ctx);
2217 /* Check if we can close the dirptr */
2218 if(close_after_request || (finished && close_if_end)) {
2219 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2220 dptr_close(&dptr_num); /* This frees up the saved mask */
2223 /* Set up the return parameter block */
2224 SSVAL(params,0,numentries);
2225 SSVAL(params,2,finished);
2226 SSVAL(params,4,0); /* Never an EA error */
2227 SSVAL(params,6,last_entry_off);
2229 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2231 if ((! *directory) && dptr_path(dptr_num))
2232 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2234 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2235 smb_fn_name(CVAL(inbuf,smb_com)),
2236 mask, directory, dirtype, numentries ) );
2241 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2243 E_md4hash(lp_servicename(SNUM(conn)),objid);
2247 /****************************************************************************
2248 Reply to a TRANS2_QFSINFO (query filesystem info).
2249 ****************************************************************************/
2251 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2252 char **pparams, int total_params, char **ppdata, int total_data,
2253 unsigned int max_data_bytes)
2256 char *params = *pparams;
2260 const char *vname = volume_label(SNUM(conn));
2261 int snum = SNUM(conn);
2262 char *fstype = lp_fstype(SNUM(conn));
2265 if (total_params < 2) {
2266 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2269 info_level = SVAL(params,0);
2271 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2273 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2274 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2275 return ERROR_DOS(ERRSRV,ERRinvdevice);
2278 *ppdata = (char *)SMB_REALLOC(
2279 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2280 if (*ppdata == NULL ) {
2281 return ERROR_NT(NT_STATUS_NO_MEMORY);
2285 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2287 switch (info_level) {
2288 case SMB_INFO_ALLOCATION:
2290 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2292 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2293 return(UNIXERROR(ERRHRD,ERRgeneral));
2296 block_size = lp_block_size(snum);
2297 if (bsize < block_size) {
2298 SMB_BIG_UINT factor = block_size/bsize;
2303 if (bsize > block_size) {
2304 SMB_BIG_UINT factor = bsize/block_size;
2309 bytes_per_sector = 512;
2310 sectors_per_unit = bsize/bytes_per_sector;
2312 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2313 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2314 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2316 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2317 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2318 SIVAL(pdata,l1_cUnit,dsize);
2319 SIVAL(pdata,l1_cUnitAvail,dfree);
2320 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2324 case SMB_INFO_VOLUME:
2325 /* Return volume name */
2327 * Add volume serial number - hash of a combination of
2328 * the called hostname and the service name.
2330 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2332 * Win2k3 and previous mess this up by sending a name length
2333 * one byte short. I believe only older clients (OS/2 Win9x) use
2334 * this call so try fixing this by adding a terminating null to
2335 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2337 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2338 SCVAL(pdata,l2_vol_cch,len);
2339 data_len = l2_vol_szVolLabel + len;
2340 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2341 (unsigned)st.st_ctime, len, vname));
2344 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2345 case SMB_FS_ATTRIBUTE_INFORMATION:
2348 #if defined(HAVE_SYS_QUOTAS)
2349 quota_flag = FILE_VOLUME_QUOTAS;
2352 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2353 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2354 FILE_SUPPORTS_OBJECT_IDS|
2355 FILE_UNICODE_ON_DISK|
2356 quota_flag); /* FS ATTRIBUTES */
2358 SIVAL(pdata,4,255); /* Max filename component length */
2359 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2360 and will think we can't do long filenames */
2361 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2363 data_len = 12 + len;
2366 case SMB_QUERY_FS_LABEL_INFO:
2367 case SMB_FS_LABEL_INFORMATION:
2368 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2373 case SMB_QUERY_FS_VOLUME_INFO:
2374 case SMB_FS_VOLUME_INFORMATION:
2377 * Add volume serial number - hash of a combination of
2378 * the called hostname and the service name.
2380 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2381 (str_checksum(get_local_machine_name())<<16));
2383 /* Max label len is 32 characters. */
2384 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2385 SIVAL(pdata,12,len);
2388 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2389 (int)strlen(vname),vname, lp_servicename(snum)));
2392 case SMB_QUERY_FS_SIZE_INFO:
2393 case SMB_FS_SIZE_INFORMATION:
2395 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2397 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2398 return(UNIXERROR(ERRHRD,ERRgeneral));
2400 block_size = lp_block_size(snum);
2401 if (bsize < block_size) {
2402 SMB_BIG_UINT factor = block_size/bsize;
2407 if (bsize > block_size) {
2408 SMB_BIG_UINT factor = bsize/block_size;
2413 bytes_per_sector = 512;
2414 sectors_per_unit = bsize/bytes_per_sector;
2415 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2416 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2417 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2418 SBIG_UINT(pdata,0,dsize);
2419 SBIG_UINT(pdata,8,dfree);
2420 SIVAL(pdata,16,sectors_per_unit);
2421 SIVAL(pdata,20,bytes_per_sector);
2425 case SMB_FS_FULL_SIZE_INFORMATION:
2427 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2429 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2430 return(UNIXERROR(ERRHRD,ERRgeneral));
2432 block_size = lp_block_size(snum);
2433 if (bsize < block_size) {
2434 SMB_BIG_UINT factor = block_size/bsize;
2439 if (bsize > block_size) {
2440 SMB_BIG_UINT factor = bsize/block_size;
2445 bytes_per_sector = 512;
2446 sectors_per_unit = bsize/bytes_per_sector;
2447 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2448 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2449 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2450 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2451 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2452 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2453 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2454 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2458 case SMB_QUERY_FS_DEVICE_INFO:
2459 case SMB_FS_DEVICE_INFORMATION:
2461 SIVAL(pdata,0,0); /* dev type */
2462 SIVAL(pdata,4,0); /* characteristics */
2465 #ifdef HAVE_SYS_QUOTAS
2466 case SMB_FS_QUOTA_INFORMATION:
2468 * what we have to send --metze:
2470 * Unknown1: 24 NULL bytes
2471 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2472 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2473 * Quota Flags: 2 byte :
2474 * Unknown3: 6 NULL bytes
2478 * details for Quota Flags:
2480 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2481 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2482 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2483 * 0x0001 Enable Quotas: enable quota for this fs
2487 /* we need to fake up a fsp here,
2488 * because its not send in this call
2491 SMB_NTQUOTA_STRUCT quotas;
2494 ZERO_STRUCT(quotas);
2500 if (current_user.ut.uid != 0) {
2501 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2502 lp_servicename(SNUM(conn)),conn->user));
2503 return ERROR_DOS(ERRDOS,ERRnoaccess);
2506 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2507 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2508 return ERROR_DOS(ERRSRV,ERRerror);
2513 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2515 /* Unknown1 24 NULL bytes*/
2516 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2517 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2518 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2520 /* Default Soft Quota 8 bytes */
2521 SBIG_UINT(pdata,24,quotas.softlim);
2523 /* Default Hard Quota 8 bytes */
2524 SBIG_UINT(pdata,32,quotas.hardlim);
2526 /* Quota flag 2 bytes */
2527 SSVAL(pdata,40,quotas.qflags);
2529 /* Unknown3 6 NULL bytes */
2535 #endif /* HAVE_SYS_QUOTAS */
2536 case SMB_FS_OBJECTID_INFORMATION:
2538 unsigned char objid[16];
2539 memcpy(pdata,create_volume_objectid(conn, objid),16);
2545 * Query the version and capabilities of the CIFS UNIX extensions
2549 case SMB_QUERY_CIFS_UNIX_INFO:
2550 if (!lp_unix_extensions()) {
2551 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2554 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2555 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2556 /* We have POSIX ACLs, pathname and locking capability. */
2557 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2558 CIFS_UNIX_POSIX_ACLS_CAP|
2559 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2560 CIFS_UNIX_FCNTL_LOCKS_CAP|
2561 CIFS_UNIX_EXTATTR_CAP|
2562 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2563 /* Ensure we don't do this on signed or sealed data. */
2564 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2568 case SMB_QUERY_POSIX_FS_INFO:
2571 vfs_statvfs_struct svfs;
2573 if (!lp_unix_extensions()) {
2574 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2577 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2581 SIVAL(pdata,0,svfs.OptimalTransferSize);
2582 SIVAL(pdata,4,svfs.BlockSize);
2583 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2584 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2585 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2586 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2587 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2588 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2589 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2591 } else if (rc == EOPNOTSUPP) {
2592 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2593 #endif /* EOPNOTSUPP */
2595 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2596 return ERROR_DOS(ERRSRV,ERRerror);
2601 case SMB_QUERY_POSIX_WHOAMI:
2607 if (!lp_unix_extensions()) {
2608 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2611 if (max_data_bytes < 40) {
2612 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2615 /* We ARE guest if global_sid_Builtin_Guests is
2616 * in our list of SIDs.
2618 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2619 current_user.nt_user_token)) {
2620 flags |= SMB_WHOAMI_GUEST;
2623 /* We are NOT guest if global_sid_Authenticated_Users
2624 * is in our list of SIDs.
2626 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2627 current_user.nt_user_token)) {
2628 flags &= ~SMB_WHOAMI_GUEST;
2631 /* NOTE: 8 bytes for UID/GID, irrespective of native
2632 * platform size. This matches
2633 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2635 data_len = 4 /* flags */
2642 + 4 /* pad/reserved */
2643 + (current_user.ut.ngroups * 8)
2645 + (current_user.nt_user_token->num_sids *
2649 SIVAL(pdata, 0, flags);
2650 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2651 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2652 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2655 if (data_len >= max_data_bytes) {
2656 /* Potential overflow, skip the GIDs and SIDs. */
2658 SIVAL(pdata, 24, 0); /* num_groups */
2659 SIVAL(pdata, 28, 0); /* num_sids */
2660 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2661 SIVAL(pdata, 36, 0); /* reserved */
2667 SIVAL(pdata, 24, current_user.ut.ngroups);
2669 current_user.nt_user_token->num_sids);
2671 /* We walk the SID list twice, but this call is fairly
2672 * infrequent, and I don't expect that it's performance
2673 * sensitive -- jpeach
2675 for (i = 0, sid_bytes = 0;
2676 i < current_user.nt_user_token->num_sids; ++i) {
2678 sid_size(¤t_user.nt_user_token->user_sids[i]);
2681 /* SID list byte count */
2682 SIVAL(pdata, 32, sid_bytes);
2684 /* 4 bytes pad/reserved - must be zero */
2685 SIVAL(pdata, 36, 0);
2689 for (i = 0; i < current_user.ut.ngroups; ++i) {
2690 SBIG_UINT(pdata, data_len,
2691 (SMB_BIG_UINT)current_user.ut.groups[i]);
2697 i < current_user.nt_user_token->num_sids; ++i) {
2699 sid_size(¤t_user.nt_user_token->user_sids[i]);
2701 sid_linearize(pdata + data_len, sid_len,
2702 ¤t_user.nt_user_token->user_sids[i]);
2703 data_len += sid_len;
2709 case SMB_MAC_QUERY_FS_INFO:
2711 * Thursby MAC extension... ONLY on NTFS filesystems
2712 * once we do streams then we don't need this
2714 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2716 SIVAL(pdata,84,0x100); /* Don't support mac... */
2721 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2725 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2727 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2732 /****************************************************************************
2733 Reply to a TRANS2_SETFSINFO (set filesystem info).
2734 ****************************************************************************/
2736 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2737 char **pparams, int total_params, char **ppdata, int total_data,
2738 unsigned int max_data_bytes)
2740 char *pdata = *ppdata;
2741 char *params = *pparams;
2745 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2748 if (total_params < 4) {
2749 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2751 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2754 info_level = SVAL(params,2);
2756 switch(info_level) {
2757 case SMB_SET_CIFS_UNIX_INFO:
2759 uint16 client_unix_major;
2760 uint16 client_unix_minor;
2761 uint32 client_unix_cap_low;
2762 uint32 client_unix_cap_high;
2764 if (!lp_unix_extensions()) {
2765 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2768 /* There should be 12 bytes of capabilities set. */
2769 if (total_data < 8) {
2770 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2772 client_unix_major = SVAL(pdata,0);
2773 client_unix_minor = SVAL(pdata,2);
2774 client_unix_cap_low = IVAL(pdata,4);
2775 client_unix_cap_high = IVAL(pdata,8);
2776 /* Just print these values for now. */
2777 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2778 cap_low = 0x%x, cap_high = 0x%x\n",
2779 (unsigned int)client_unix_major,
2780 (unsigned int)client_unix_minor,
2781 (unsigned int)client_unix_cap_low,
2782 (unsigned int)client_unix_cap_high ));
2784 /* Here is where we must switch to posix pathname processing... */
2785 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2786 lp_set_posix_pathnames();
2787 mangle_change_to_posix();
2790 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2791 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2792 /* Client that knows how to do posix locks,
2793 * but not posix open/mkdir operations. Set a
2794 * default type for read/write checks. */
2796 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2801 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2804 size_t param_len = 0;
2805 size_t data_len = total_data;
2807 if (!lp_unix_extensions()) {
2808 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2811 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2813 status = srv_request_encryption_setup(conn,
2814 (unsigned char **)ppdata,
2816 (unsigned char **)pparams,
2820 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2821 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2822 } else if (!NT_STATUS_IS_OK(status)) {
2823 return ERROR_NT(status);
2826 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2828 if (NT_STATUS_IS_OK(status)) {
2829 /* Server-side transport encryption is now *on*. */
2830 status = srv_encryption_start(conn);
2831 if (!NT_STATUS_IS_OK(status)) {
2832 exit_server_cleanly("Failure in setting up encrypted transport");
2837 case SMB_FS_QUOTA_INFORMATION:
2839 files_struct *fsp = NULL;
2840 SMB_NTQUOTA_STRUCT quotas;
2842 ZERO_STRUCT(quotas);
2845 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2846 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2847 lp_servicename(SNUM(conn)),conn->user));
2848 return ERROR_DOS(ERRSRV,ERRaccess);
2851 /* note: normaly there're 48 bytes,
2852 * but we didn't use the last 6 bytes for now
2855 fsp = file_fsp(params,0);
2856 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2857 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2858 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2861 if (total_data < 42) {
2862 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2864 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2867 /* unknown_1 24 NULL bytes in pdata*/
2869 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2870 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2871 #ifdef LARGE_SMB_OFF_T
2872 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2873 #else /* LARGE_SMB_OFF_T */
2874 if ((IVAL(pdata,28) != 0)&&
2875 ((quotas.softlim != 0xFFFFFFFF)||
2876 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2877 /* more than 32 bits? */
2878 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2880 #endif /* LARGE_SMB_OFF_T */
2882 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2883 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2884 #ifdef LARGE_SMB_OFF_T
2885 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2886 #else /* LARGE_SMB_OFF_T */
2887 if ((IVAL(pdata,36) != 0)&&
2888 ((quotas.hardlim != 0xFFFFFFFF)||
2889 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2890 /* more than 32 bits? */
2891 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2893 #endif /* LARGE_SMB_OFF_T */
2895 /* quota_flags 2 bytes **/
2896 quotas.qflags = SVAL(pdata,40);
2898 /* unknown_2 6 NULL bytes follow*/
2900 /* now set the quotas */
2901 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2902 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2903 return ERROR_DOS(ERRSRV,ERRerror);
2909 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2911 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2916 * sending this reply works fine,
2917 * but I'm not sure it's the same
2918 * like windows do...
2921 outsize = set_message(inbuf, outbuf,10,0,True);
2926 #if defined(HAVE_POSIX_ACLS)
2927 /****************************************************************************
2928 Utility function to count the number of entries in a POSIX acl.
2929 ****************************************************************************/
2931 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2933 unsigned int ace_count = 0;
2934 int entry_id = SMB_ACL_FIRST_ENTRY;
2935 SMB_ACL_ENTRY_T entry;
2937 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2939 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2940 entry_id = SMB_ACL_NEXT_ENTRY;
2947 /****************************************************************************
2948 Utility function to marshall a POSIX acl into wire format.
2949 ****************************************************************************/
2951 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2953 int entry_id = SMB_ACL_FIRST_ENTRY;
2954 SMB_ACL_ENTRY_T entry;
2956 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2957 SMB_ACL_TAG_T tagtype;
2958 SMB_ACL_PERMSET_T permset;
2959 unsigned char perms = 0;
2960 unsigned int own_grp;
2963 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2964 entry_id = SMB_ACL_NEXT_ENTRY;
2967 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2968 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2972 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2973 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2977 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2978 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2979 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2981 SCVAL(pdata,1,perms);
2984 case SMB_ACL_USER_OBJ:
2985 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2986 own_grp = (unsigned int)pst->st_uid;
2987 SIVAL(pdata,2,own_grp);
2992 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2994 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2996 own_grp = (unsigned int)*puid;
2997 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2998 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2999 SIVAL(pdata,2,own_grp);
3003 case SMB_ACL_GROUP_OBJ:
3004 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3005 own_grp = (unsigned int)pst->st_gid;
3006 SIVAL(pdata,2,own_grp);
3011 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3013 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3015 own_grp = (unsigned int)*pgid;
3016 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3017 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3018 SIVAL(pdata,2,own_grp);
3023 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3024 SIVAL(pdata,2,0xFFFFFFFF);
3025 SIVAL(pdata,6,0xFFFFFFFF);
3028 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3029 SIVAL(pdata,2,0xFFFFFFFF);
3030 SIVAL(pdata,6,0xFFFFFFFF);
3033 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3036 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3043 /****************************************************************************
3044 Store the FILE_UNIX_BASIC info.
3045 ****************************************************************************/
3047 static char *store_file_unix_basic(connection_struct *conn,
3050 const SMB_STRUCT_STAT *psbuf)
3052 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3053 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3055 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3058 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3061 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3062 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3063 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3066 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3070 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3074 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3077 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3081 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3085 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3088 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3092 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3099 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3100 * the chflags(2) (or equivalent) flags.
3102 * XXX: this really should be behind the VFS interface. To do this, we would
3103 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3104 * Each VFS module could then implement it's own mapping as appropriate for the
3105 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3107 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3111 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3115 { UF_IMMUTABLE, EXT_IMMUTABLE },
3119 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3123 { UF_HIDDEN, EXT_HIDDEN },
3126 /* Do not remove. We need to guarantee that this array has at least one
3127 * entry to build on HP-UX.
3133 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3134 uint32 *smb_fflags, uint32 *smb_fmask)
3136 #ifdef HAVE_STAT_ST_FLAGS
3139 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3140 *smb_fmask |= info2_flags_map[i].smb_fflag;
3141 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3142 *smb_fflags |= info2_flags_map[i].smb_fflag;
3145 #endif /* HAVE_STAT_ST_FLAGS */
3148 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3149 const uint32 smb_fflags,
3150 const uint32 smb_fmask,
3153 #ifdef HAVE_STAT_ST_FLAGS
3154 uint32 max_fmask = 0;
3157 *stat_fflags = psbuf->st_flags;
3159 /* For each flags requested in smb_fmask, check the state of the
3160 * corresponding flag in smb_fflags and set or clear the matching
3164 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3165 max_fmask |= info2_flags_map[i].smb_fflag;
3166 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3167 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3168 *stat_fflags |= info2_flags_map[i].stat_fflag;
3170 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3175 /* If smb_fmask is asking to set any bits that are not supported by
3176 * our flag mappings, we should fail.
3178 if ((smb_fmask & max_fmask) != smb_fmask) {
3185 #endif /* HAVE_STAT_ST_FLAGS */
3189 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3190 * of file flags and birth (create) time.
3192 static char *store_file_unix_basic_info2(connection_struct *conn,
3195 const SMB_STRUCT_STAT *psbuf)
3197 uint32 file_flags = 0;
3198 uint32 flags_mask = 0;
3200 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3202 /* Create (birth) time 64 bit */
3203 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3206 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3207 SIVAL(pdata, 0, file_flags); /* flags */
3208 SIVAL(pdata, 4, flags_mask); /* mask */
3214 /****************************************************************************
3215 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3216 ****************************************************************************/
3218 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3219 unsigned int tran_call,
3220 char **pparams, int total_params, char **ppdata, int total_data,
3221 unsigned int max_data_bytes)
3223 char *params = *pparams;
3224 char *pdata = *ppdata;
3225 unsigned int data_size = 0;
3226 unsigned int param_size = 2;
3228 smb_np_struct *p_pipe = NULL;
3231 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3234 if (total_params < 4) {
3235 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3238 p_pipe = get_rpc_pipe_p(params,0);
3239 if (p_pipe == NULL) {
3240 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3243 info_level = SVAL(params,2);
3245 *pparams = (char *)SMB_REALLOC(*pparams,2);
3246 if (*pparams == NULL) {
3247 return ERROR_NT(NT_STATUS_NO_MEMORY);
3251 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3252 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3253 if (*ppdata == NULL ) {
3254 return ERROR_NT(NT_STATUS_NO_MEMORY);
3258 switch (info_level) {
3259 case SMB_FILE_STANDARD_INFORMATION:
3261 SOFF_T(pdata,0,4096LL);
3268 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3271 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3276 /****************************************************************************
3277 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3278 file name or file id).
3279 ****************************************************************************/
3281 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3282 unsigned int tran_call,
3283 char **pparams, int total_params, char **ppdata, int total_data,
3284 unsigned int max_data_bytes)
3286 char *params = *pparams;
3287 char *pdata = *ppdata;
3291 SMB_OFF_T file_size=0;
3292 SMB_BIG_UINT allocation_size=0;
3293 unsigned int data_size = 0;
3294 unsigned int param_size = 2;
3295 SMB_STRUCT_STAT sbuf;
3296 pstring fname, dos_fname;
3301 BOOL delete_pending = False;
3303 time_t create_time, mtime, atime;
3304 struct timespec create_time_ts, mtime_ts, atime_ts;
3305 files_struct *fsp = NULL;
3306 TALLOC_CTX *data_ctx = NULL;
3307 struct ea_list *ea_list = NULL;
3308 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3309 char *lock_data = NULL;
3312 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3316 if (tran_call == TRANSACT2_QFILEINFO) {
3317 if (total_params < 4) {
3318 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3322 return call_trans2qpipeinfo(conn,
3335 fsp = file_fsp(params,0);
3336 info_level = SVAL(params,2);
3338 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3340 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3341 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3344 if(fsp && (fsp->fake_file_handle)) {
3346 * This is actually for the QUOTA_FAKE_FILE --metze
3349 pstrcpy(fname, fsp->fsp_name);
3350 /* We know this name is ok, it's already passed the checks. */
3352 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3354 * This is actually a QFILEINFO on a directory
3355 * handle (returned from an NT SMB). NT5.0 seems
3356 * to do this call. JRA.
3358 /* We know this name is ok, it's already passed the checks. */
3359 pstrcpy(fname, fsp->fsp_name);
3361 if (INFO_LEVEL_IS_UNIX(info_level)) {
3362 /* Always do lstat for UNIX calls. */
3363 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3364 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3365 return UNIXERROR(ERRDOS,ERRbadpath);
3367 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3368 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3369 return UNIXERROR(ERRDOS,ERRbadpath);
3372 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3375 * Original code - this is an open file.
3377 CHECK_FSP(fsp,conn);
3379 pstrcpy(fname, fsp->fsp_name);
3380 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3381 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3382 return(UNIXERROR(ERRDOS,ERRbadfid));
3384 pos = fsp->fh->position_information;
3385 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3386 access_mask = fsp->access_mask;
3389 NTSTATUS status = NT_STATUS_OK;
3392 if (total_params < 7) {
3393 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3396 info_level = SVAL(params,0);
3398 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3400 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3401 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3404 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3405 if (!NT_STATUS_IS_OK(status)) {
3406 return ERROR_NT(status);
3409 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3410 if (!NT_STATUS_IS_OK(status)) {
3411 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3412 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3414 return ERROR_NT(status);
3417 status = unix_convert(conn, fname, False, NULL, &sbuf);
3418 if (!NT_STATUS_IS_OK(status)) {
3419 return ERROR_NT(status);
3421 status = check_name(conn, fname);
3422 if (!NT_STATUS_IS_OK(status)) {
3423 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3424 return ERROR_NT(status);
3427 if (INFO_LEVEL_IS_UNIX(info_level)) {
3428 /* Always do lstat for UNIX calls. */
3429 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3430 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3431 return UNIXERROR(ERRDOS,ERRbadpath);
3433 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3434 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3435 return UNIXERROR(ERRDOS,ERRbadpath);
3438 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3439 if (delete_pending) {
3440 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3444 nlink = sbuf.st_nlink;
3446 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3447 /* NTFS does not seem to count ".." */
3451 if ((nlink > 0) && delete_pending) {
3455 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3456 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3459 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3460 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3462 p = strrchr_m(fname,'/');
3468 mode = dos_mode(conn,fname,&sbuf);
3470 mode = FILE_ATTRIBUTE_NORMAL;
3472 fullpathname = fname;
3474 file_size = get_file_size(sbuf);
3476 /* Pull out any data sent here before we realloc. */
3477 switch (info_level) {
3478 case SMB_INFO_QUERY_EAS_FROM_LIST:
3480 /* Pull any EA list from the data portion. */
3483 if (total_data < 4) {
3484 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3486 ea_size = IVAL(pdata,0);
3488 if (total_data > 0 && ea_size != total_data) {
3489 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3490 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3491 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3494 if (!lp_ea_support(SNUM(conn))) {
3495 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3498 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3499 return ERROR_NT(NT_STATUS_NO_MEMORY);
3502 /* Pull out the list of names. */
3503 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3505 talloc_destroy(data_ctx);
3506 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3511 case SMB_QUERY_POSIX_LOCK:
3513 if (fsp == NULL || fsp->fh->fd == -1) {
3514 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3517 if (total_data != POSIX_LOCK_DATA_SIZE) {
3518 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3521 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3522 return ERROR_NT(NT_STATUS_NO_MEMORY);
3525 /* Copy the lock range data. */
3526 lock_data = (char *)TALLOC_MEMDUP(
3527 data_ctx, pdata, total_data);
3529 talloc_destroy(data_ctx);
3530 return ERROR_NT(NT_STATUS_NO_MEMORY);
3537 *pparams = (char *)SMB_REALLOC(*pparams,2);
3538 if (*pparams == NULL) {
3539 talloc_destroy(data_ctx);
3540 return ERROR_NT(NT_STATUS_NO_MEMORY);
3544 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3545 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3546 if (*ppdata == NULL ) {
3547 talloc_destroy(data_ctx);
3548 return ERROR_NT(NT_STATUS_NO_MEMORY);
3552 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3553 mtime_ts = get_mtimespec(&sbuf);
3554 atime_ts = get_atimespec(&sbuf);
3556 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3559 if (!null_timespec(fsp->pending_modtime)) {
3560 /* the pending modtime overrides the current modtime */
3561 mtime_ts = fsp->pending_modtime;
3564 /* Do we have this path open ? */
3565 files_struct *fsp1 = file_find_di_first(file_id_sbuf(&sbuf));
3566 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3567 /* the pending modtime overrides the current modtime */
3568 mtime_ts = fsp1->pending_modtime;
3570 if (fsp1 && fsp1->initial_allocation_size) {
3571 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3575 if (lp_dos_filetime_resolution(SNUM(conn))) {
3576 dos_filetime_timespec(&create_time_ts);
3577 dos_filetime_timespec(&mtime_ts);
3578 dos_filetime_timespec(&atime_ts);
3581 create_time = convert_timespec_to_time_t(create_time_ts);
3582 mtime = convert_timespec_to_time_t(mtime_ts);
3583 atime = convert_timespec_to_time_t(atime_ts);
3585 /* NT expects the name to be in an exact form of the *full*
3586 filename. See the trans2 torture test */
3587 if (strequal(base_name,".")) {
3588 pstrcpy(dos_fname, "\\");
3590 pstr_sprintf(dos_fname, "\\%s", fname);
3591 string_replace(dos_fname, '/', '\\');
3594 switch (info_level) {
3595 case SMB_INFO_STANDARD:
3596 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3598 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3599 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3600 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3601 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3602 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3603 SSVAL(pdata,l1_attrFile,mode);
3606 case SMB_INFO_QUERY_EA_SIZE:
3608 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3609 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3611 srv_put_dos_date2(pdata,0,create_time);
3612 srv_put_dos_date2(pdata,4,atime);
3613 srv_put_dos_date2(pdata,8,mtime); /* write time */
3614 SIVAL(pdata,12,(uint32)file_size);
3615 SIVAL(pdata,16,(uint32)allocation_size);
3616 SSVAL(pdata,20,mode);
3617 SIVAL(pdata,22,ea_size);
3621 case SMB_INFO_IS_NAME_VALID:
3622 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3623 if (tran_call == TRANSACT2_QFILEINFO) {
3624 /* os/2 needs this ? really ?*/
3625 return ERROR_DOS(ERRDOS,ERRbadfunc);
3631 case SMB_INFO_QUERY_EAS_FROM_LIST:
3633 size_t total_ea_len = 0;
3634 struct ea_list *ea_file_list = NULL;
3636 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3638 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3639 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3641 if (!ea_list || (total_ea_len > data_size)) {
3642 talloc_destroy(data_ctx);
3644 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3648 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3649 talloc_destroy(data_ctx);
3653 case SMB_INFO_QUERY_ALL_EAS:
3655 /* We have data_size bytes to put EA's into. */
3656 size_t total_ea_len = 0;
3658 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3660 data_ctx = talloc_init("ea_ctx");
3662 return ERROR_NT(NT_STATUS_NO_MEMORY);
3665 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3666 if (!ea_list || (total_ea_len > data_size)) {
3667 talloc_destroy(data_ctx);
3669 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3673 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3674 talloc_destroy(data_ctx);
3678 case SMB_FILE_BASIC_INFORMATION:
3679 case SMB_QUERY_FILE_BASIC_INFO:
3681 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3682 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3683 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3685 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3689 put_long_date_timespec(pdata,create_time_ts);
3690 put_long_date_timespec(pdata+8,atime_ts);
3691 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3692 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3693 SIVAL(pdata,32,mode);
3695 DEBUG(5,("SMB_QFBI - "));
3696 DEBUG(5,("create: %s ", ctime(&create_time)));
3697 DEBUG(5,("access: %s ", ctime(&atime)));
3698 DEBUG(5,("write: %s ", ctime(&mtime)));
3699 DEBUG(5,("change: %s ", ctime(&mtime)));
3700 DEBUG(5,("mode: %x\n", mode));
3703 case SMB_FILE_STANDARD_INFORMATION:
3704 case SMB_QUERY_FILE_STANDARD_INFO:
3706 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3708 SOFF_T(pdata,0,allocation_size);
3709 SOFF_T(pdata,8,file_size);
3710 SIVAL(pdata,16,nlink);
3711 SCVAL(pdata,20,delete_pending?1:0);
3712 SCVAL(pdata,21,(mode&aDIR)?1:0);
3713 SSVAL(pdata,22,0); /* Padding. */
3716 case SMB_FILE_EA_INFORMATION:
3717 case SMB_QUERY_FILE_EA_INFO:
3719 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3720 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3722 SIVAL(pdata,0,ea_size);
3726 /* Get the 8.3 name - used if NT SMB was negotiated. */
3727 case SMB_QUERY_FILE_ALT_NAME_INFO:
3728 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3732 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3733 pstrcpy(short_name,base_name);
3734 /* Mangle if not already 8.3 */
3735 if(!mangle_is_8_3(short_name, True, conn->params)) {
3736 mangle_map(short_name,True,True,conn->params);
3738 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3739 data_size = 4 + len;
3744 case SMB_QUERY_FILE_NAME_INFO:
3746 this must be *exactly* right for ACLs on mapped drives to work
3748 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3749 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3750 data_size = 4 + len;
3754 case SMB_FILE_ALLOCATION_INFORMATION:
3755 case SMB_QUERY_FILE_ALLOCATION_INFO:
3756 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3758 SOFF_T(pdata,0,allocation_size);
3761 case SMB_FILE_END_OF_FILE_INFORMATION:
3762 case SMB_QUERY_FILE_END_OF_FILEINFO:
3763 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3765 SOFF_T(pdata,0,file_size);
3768 case SMB_QUERY_FILE_ALL_INFO:
3769 case SMB_FILE_ALL_INFORMATION:
3771 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3772 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3773 put_long_date_timespec(pdata,create_time_ts);
3774 put_long_date_timespec(pdata+8,atime_ts);
3775 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3776 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3777 SIVAL(pdata,32,mode);
3778 SIVAL(pdata,36,0); /* padding. */
3780 SOFF_T(pdata,0,allocation_size);
3781 SOFF_T(pdata,8,file_size);
3782 SIVAL(pdata,16,nlink);
3783 SCVAL(pdata,20,delete_pending);
3784 SCVAL(pdata,21,(mode&aDIR)?1:0);
3787 SIVAL(pdata,0,ea_size);
3788 pdata += 4; /* EA info */
3789 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3792 data_size = PTR_DIFF(pdata,(*ppdata));
3795 case SMB_FILE_INTERNAL_INFORMATION:
3796 /* This should be an index number - looks like
3799 I think this causes us to fail the IFSKIT
3800 BasicFileInformationTest. -tpot */
3802 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3803 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3804 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3808 case SMB_FILE_ACCESS_INFORMATION:
3809 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3810 SIVAL(pdata,0,access_mask);
3814 case SMB_FILE_NAME_INFORMATION:
3815 /* Pathname with leading '\'. */
3818 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3819 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3820 SIVAL(pdata,0,byte_len);
3821 data_size = 4 + byte_len;
3825 case SMB_FILE_DISPOSITION_INFORMATION:
3826 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3828 SCVAL(pdata,0,delete_pending);
3831 case SMB_FILE_POSITION_INFORMATION:
3832 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3834 SOFF_T(pdata,0,pos);
3837 case SMB_FILE_MODE_INFORMATION:
3838 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3839 SIVAL(pdata,0,mode);
3843 case SMB_FILE_ALIGNMENT_INFORMATION:
3844 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3845 SIVAL(pdata,0,0); /* No alignment needed. */
3851 * NT4 server just returns "invalid query" to this - if we try to answer
3852 * it then NTws gets a BSOD! (tridge).
3853 * W2K seems to want this. JRA.
3855 case SMB_QUERY_FILE_STREAM_INFO:
3857 case SMB_FILE_STREAM_INFORMATION:
3858 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3862 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3863 SIVAL(pdata,0,0); /* ??? */
3864 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3865 SOFF_T(pdata,8,file_size);
3866 SOFF_T(pdata,16,allocation_size);
3867 data_size = 24 + byte_len;
3871 case SMB_QUERY_COMPRESSION_INFO:
3872 case SMB_FILE_COMPRESSION_INFORMATION:
3873 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3874 SOFF_T(pdata,0,file_size);
3875 SIVAL(pdata,8,0); /* ??? */
3876 SIVAL(pdata,12,0); /* ??? */
3880 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3881 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3882 put_long_date_timespec(pdata,create_time_ts);
3883 put_long_date_timespec(pdata+8,atime_ts);
3884 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3885 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3886 SOFF_T(pdata,32,allocation_size);
3887 SOFF_T(pdata,40,file_size);
3888 SIVAL(pdata,48,mode);
3889 SIVAL(pdata,52,0); /* ??? */
3893 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3894 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3895 SIVAL(pdata,0,mode);
3901 * CIFS UNIX Extensions.
3904 case SMB_QUERY_FILE_UNIX_BASIC:
3906 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3907 data_size = PTR_DIFF(pdata,(*ppdata));
3911 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3913 for (i=0; i<100; i++)
3914 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3920 case SMB_QUERY_FILE_UNIX_INFO2:
3922 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3923 data_size = PTR_DIFF(pdata,(*ppdata));
3927 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3929 for (i=0; i<100; i++)
3930 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3936 case SMB_QUERY_FILE_UNIX_LINK:
3940 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3942 if(!S_ISLNK(sbuf.st_mode))
3943 return(UNIXERROR(ERRSRV,ERRbadlink));
3945 return(UNIXERROR(ERRDOS,ERRbadlink));
3947 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3949 return(UNIXERROR(ERRDOS,ERRnoaccess));
3951 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3953 data_size = PTR_DIFF(pdata,(*ppdata));
3958 #if defined(HAVE_POSIX_ACLS)
3959 case SMB_QUERY_POSIX_ACL:
3961 SMB_ACL_T file_acl = NULL;
3962 SMB_ACL_T def_acl = NULL;
3963 uint16 num_file_acls = 0;
3964 uint16 num_def_acls = 0;
3966 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3967 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3969 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3972 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3973 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3975 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3978 if (S_ISDIR(sbuf.st_mode)) {
3979 if (fsp && fsp->is_directory) {
3980 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3982 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3984 def_acl = free_empty_sys_acl(conn, def_acl);
3987 num_file_acls = count_acl_entries(conn, file_acl);
3988 num_def_acls = count_acl_entries(conn, def_acl);
3990 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3991 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3993 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3994 SMB_POSIX_ACL_HEADER_SIZE) ));
3996 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3999 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4001 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4004 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4005 SSVAL(pdata,2,num_file_acls);
4006 SSVAL(pdata,4,num_def_acls);
4007 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4009 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4012 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4014 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4016 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4018 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4021 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4023 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4027 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4030 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4032 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4038 case SMB_QUERY_POSIX_LOCK:
4040 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4042 SMB_BIG_UINT offset;
4044 enum brl_type lock_type;
4046 if (total_data != POSIX_LOCK_DATA_SIZE) {
4047 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4050 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4051 case POSIX_LOCK_TYPE_READ:
4052 lock_type = READ_LOCK;
4054 case POSIX_LOCK_TYPE_WRITE:
4055 lock_type = WRITE_LOCK;
4057 case POSIX_LOCK_TYPE_UNLOCK:
4059 /* There's no point in asking for an unlock... */
4060 talloc_destroy(data_ctx);
4061 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4064 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4065 #if defined(HAVE_LONGLONG)
4066 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4067 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4068 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4069 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4070 #else /* HAVE_LONGLONG */
4071 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4072 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4073 #endif /* HAVE_LONGLONG */
4075 status = query_lock(fsp,
4082 if (ERROR_WAS_LOCK_DENIED(status)) {
4083 /* Here we need to report who has it locked... */
4084 data_size = POSIX_LOCK_DATA_SIZE;
4086 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4087 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4088 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4089 #if defined(HAVE_LONGLONG)
4090 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4091 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4092 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4093 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4094 #else /* HAVE_LONGLONG */
4095 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4096 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4097 #endif /* HAVE_LONGLONG */
4099 } else if (NT_STATUS_IS_OK(status)) {
4100 /* For success we just return a copy of what we sent
4101 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4102 data_size = POSIX_LOCK_DATA_SIZE;
4103 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4104 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4106 return ERROR_NT(status);
4112 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4115 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4120 /****************************************************************************
4121 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4123 ****************************************************************************/
4125 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4127 SMB_STRUCT_STAT sbuf1, sbuf2;
4128 pstring last_component_oldname;
4129 pstring last_component_newname;
4130 NTSTATUS status = NT_STATUS_OK;
4135 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4136 if (!NT_STATUS_IS_OK(status)) {
4140 status = check_name(conn, oldname);
4141 if (!NT_STATUS_IS_OK(status)) {
4145 /* source must already exist. */
4146 if (!VALID_STAT(sbuf1)) {
4147 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4150 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4151 if (!NT_STATUS_IS_OK(status)) {
4155 status = check_name(conn, newname);
4156 if (!NT_STATUS_IS_OK(status)) {
4160 /* Disallow if newname already exists. */
4161 if (VALID_STAT(sbuf2)) {
4162 return NT_STATUS_OBJECT_NAME_COLLISION;
4165 /* No links from a directory. */
4166 if (S_ISDIR(sbuf1.st_mode)) {
4167 return NT_STATUS_FILE_IS_A_DIRECTORY;
4170 /* Ensure this is within the share. */
4171 status = reduce_name(conn, oldname);
4172 if (!NT_STATUS_IS_OK(status)) {
4176 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4178 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4179 status = map_nt_error_from_unix(errno);
4180 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4181 nt_errstr(status), newname, oldname));
4187 /****************************************************************************
4188 Deal with setting the time from any of the setfilepathinfo functions.
4189 ****************************************************************************/
4191 static NTSTATUS smb_set_file_time(connection_struct *conn,
4194 const SMB_STRUCT_STAT *psbuf,
4195 struct timespec ts[2])
4198 FILE_NOTIFY_CHANGE_LAST_ACCESS
4199 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4202 if (!VALID_STAT(*psbuf)) {
4203 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4206 /* get some defaults (no modifications) if any info is zero or -1. */
4207 if (null_timespec(ts[0])) {
4208 ts[0] = get_atimespec(psbuf);
4209 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4212 if (null_timespec(ts[1])) {
4213 ts[1] = get_mtimespec(psbuf);
4214 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4217 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4218 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4221 * Try and set the times of this file if
4222 * they are different from the current values.
4226 struct timespec mts = get_mtimespec(psbuf);
4227 struct timespec ats = get_atimespec(psbuf);
4228 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4229 return NT_STATUS_OK;
4235 * This was a setfileinfo on an open file.
4236 * NT does this a lot. We also need to
4237 * set the time here, as it can be read by
4238 * FindFirst/FindNext and with the patch for bug #2045
4239 * in smbd/fileio.c it ensures that this timestamp is
4240 * kept sticky even after a write. We save the request
4241 * away and will set it on file close and after a write. JRA.
4244 if (!null_timespec(ts[1])) {
4245 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4246 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4247 fsp_set_pending_modtime(fsp, ts[1]);
4251 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4253 if(file_ntimes(conn, fname, ts)!=0) {
4254 return map_nt_error_from_unix(errno);
4257 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4259 return NT_STATUS_OK;
4262 /****************************************************************************
4263 Deal with setting the dosmode from any of the setfilepathinfo functions.
4264 ****************************************************************************/
4266 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4268 SMB_STRUCT_STAT *psbuf,
4271 if (!VALID_STAT(*psbuf)) {
4272 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4276 if (S_ISDIR(psbuf->st_mode)) {
4283 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4285 /* check the mode isn't different, before changing it */
4286 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4288 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4289 fname, (unsigned int)dosmode ));
4291 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4292 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4293 fname, strerror(errno)));
4294 return map_nt_error_from_unix(errno);
4297 return NT_STATUS_OK;
4300 /****************************************************************************
4301 Deal with setting the size from any of the setfilepathinfo functions.
4302 ****************************************************************************/
4304 static NTSTATUS smb_set_file_size(connection_struct *conn,
4305 struct smb_request *req,
4308 SMB_STRUCT_STAT *psbuf,
4311 NTSTATUS status = NT_STATUS_OK;
4312 files_struct *new_fsp = NULL;
4314 if (!VALID_STAT(*psbuf)) {
4315 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4318 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4320 if (size == get_file_size(*psbuf)) {
4321 return NT_STATUS_OK;
4324 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4325 fname, (double)size ));
4327 if (fsp && fsp->fh->fd != -1) {
4328 /* Handle based call. */
4329 if (vfs_set_filelen(fsp, size) == -1) {
4330 return map_nt_error_from_unix(errno);
4332 return NT_STATUS_OK;
4335 status = open_file_ntcreate(conn, req, fname, psbuf,
4337 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4340 FILE_ATTRIBUTE_NORMAL,
4341 FORCE_OPLOCK_BREAK_TO_NONE,
4344 if (!NT_STATUS_IS_OK(status)) {
4345 /* NB. We check for open_was_deferred in the caller. */
4349 if (vfs_set_filelen(new_fsp, size) == -1) {
4350 status = map_nt_error_from_unix(errno);
4351 close_file(new_fsp,NORMAL_CLOSE);
4355 close_file(new_fsp,NORMAL_CLOSE);
4356 return NT_STATUS_OK;
4359 /****************************************************************************
4360 Deal with SMB_INFO_SET_EA.
4361 ****************************************************************************/
4363 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4369 struct ea_list *ea_list = NULL;
4370 TALLOC_CTX *ctx = NULL;
4371 NTSTATUS status = NT_STATUS_OK;
4373 if (total_data < 10) {
4375 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4376 length. They seem to have no effect. Bug #3212. JRA */
4378 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4379 /* We're done. We only get EA info in this call. */
4380 return NT_STATUS_OK;
4383 return NT_STATUS_INVALID_PARAMETER;
4386 if (IVAL(pdata,0) > total_data) {
4387 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4388 IVAL(pdata,0), (unsigned int)total_data));
4389 return NT_STATUS_INVALID_PARAMETER;
4392 ctx = talloc_init("SMB_INFO_SET_EA");
4394 return NT_STATUS_NO_MEMORY;
4396 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4398 talloc_destroy(ctx);
4399 return NT_STATUS_INVALID_PARAMETER;
4401 status = set_ea(conn, fsp, fname, ea_list);
4402 talloc_destroy(ctx);
4407 /****************************************************************************
4408 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4409 ****************************************************************************/
4411 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4416 SMB_STRUCT_STAT *psbuf)
4418 NTSTATUS status = NT_STATUS_OK;
4419 BOOL delete_on_close;
4422 if (total_data < 1) {
4423 return NT_STATUS_INVALID_PARAMETER;
4427 return NT_STATUS_INVALID_HANDLE;
4430 delete_on_close = (CVAL(pdata,0) ? True : False);
4431 dosmode = dos_mode(conn, fname, psbuf);
4433 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4434 "delete_on_close = %u\n",
4436 (unsigned int)dosmode,
4437 (unsigned int)delete_on_close ));
4439 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4441 if (!NT_STATUS_IS_OK(status)) {
4445 /* The set is across all open files on this dev/inode pair. */
4446 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4447 return NT_STATUS_ACCESS_DENIED;
4449 return NT_STATUS_OK;
4452 /****************************************************************************
4453 Deal with SMB_FILE_POSITION_INFORMATION.
4454 ****************************************************************************/
4456 static NTSTATUS smb_file_position_information(connection_struct *conn,
4461 SMB_BIG_UINT position_information;
4463 if (total_data < 8) {
4464 return NT_STATUS_INVALID_PARAMETER;
4468 /* Ignore on pathname based set. */
4469 return NT_STATUS_OK;
4472 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4473 #ifdef LARGE_SMB_OFF_T
4474 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4475 #else /* LARGE_SMB_OFF_T */
4476 if (IVAL(pdata,4) != 0) {
4477 /* more than 32 bits? */
4478 return NT_STATUS_INVALID_PARAMETER;
4480 #endif /* LARGE_SMB_OFF_T */
4482 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4483 fsp->fsp_name, (double)position_information ));
4484 fsp->fh->position_information = position_information;
4485 return NT_STATUS_OK;
4488 /****************************************************************************
4489 Deal with SMB_FILE_MODE_INFORMATION.
4490 ****************************************************************************/
4492 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4498 if (total_data < 4) {
4499 return NT_STATUS_INVALID_PARAMETER;
4501 mode = IVAL(pdata,0);
4502 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4503 return NT_STATUS_INVALID_PARAMETER;
4505 return NT_STATUS_OK;
4508 /****************************************************************************
4509 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4510 ****************************************************************************/
4512 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4518 pstring link_target;
4519 const char *newname = fname;
4520 NTSTATUS status = NT_STATUS_OK;
4522 /* Set a symbolic link. */
4523 /* Don't allow this if follow links is false. */
4525 if (total_data == 0) {
4526 return NT_STATUS_INVALID_PARAMETER;
4529 if (!lp_symlinks(SNUM(conn))) {
4530 return NT_STATUS_ACCESS_DENIED;
4533 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4535 /* !widelinks forces the target path to be within the share. */
4536 /* This means we can interpret the target as a pathname. */
4537 if (!lp_widelinks(SNUM(conn))) {
4539 char *last_dirp = NULL;
4541 if (*link_target == '/') {
4542 /* No absolute paths allowed. */
4543 return NT_STATUS_ACCESS_DENIED;
4545 pstrcpy(rel_name, newname);
4546 last_dirp = strrchr_m(rel_name, '/');
4548 last_dirp[1] = '\0';
4550 pstrcpy(rel_name, "./");
4552 pstrcat(rel_name, link_target);
4554 status = check_name(conn, rel_name);
4555 if (!NT_STATUS_IS_OK(status)) {
4560 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4561 newname, link_target ));
4563 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4564 return map_nt_error_from_unix(errno);
4567 return NT_STATUS_OK;
4570 /****************************************************************************
4571 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4572 ****************************************************************************/
4574 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4582 NTSTATUS status = NT_STATUS_OK;
4584 /* Set a hard link. */
4585 if (total_data == 0) {
4586 return NT_STATUS_INVALID_PARAMETER;
4589 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4590 if (!NT_STATUS_IS_OK(status)) {
4594 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4595 if (!NT_STATUS_IS_OK(status)) {
4599 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4602 return hardlink_internals(conn, oldname, fname);
4605 /****************************************************************************
4606 Deal with SMB_FILE_RENAME_INFORMATION.
4607 ****************************************************************************/
4609 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4610 struct smb_request *req,
4623 BOOL dest_has_wcard = False;
4624 NTSTATUS status = NT_STATUS_OK;
4627 if (total_data < 13) {
4628 return NT_STATUS_INVALID_PARAMETER;
4631 overwrite = (CVAL(pdata,0) ? True : False);
4632 root_fid = IVAL(pdata,4);
4633 len = IVAL(pdata,8);
4635 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4636 return NT_STATUS_INVALID_PARAMETER;
4639 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4640 if (!NT_STATUS_IS_OK(status)) {
4644 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4645 if (!NT_STATUS_IS_OK(status)) {
4649 /* Check the new name has no '/' characters. */
4650 if (strchr_m(newname, '/')) {
4651 return NT_STATUS_NOT_SUPPORTED;
4654 /* Create the base directory. */
4655 pstrcpy(base_name, fname);
4656 p = strrchr_m(base_name, '/');
4660 pstrcpy(base_name, "./");
4662 /* Append the new name. */
4663 pstrcat(base_name, newname);
4666 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4667 fsp->fnum, fsp->fsp_name, base_name ));
4668 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4670 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4672 status = rename_internals(conn, req, fname, base_name, 0,
4673 overwrite, False, dest_has_wcard);
4679 /****************************************************************************
4680 Deal with SMB_SET_POSIX_ACL.
4681 ****************************************************************************/
4683 #if defined(HAVE_POSIX_ACLS)
4684 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4689 SMB_STRUCT_STAT *psbuf)
4691 uint16 posix_acl_version;
4692 uint16 num_file_acls;
4693 uint16 num_def_acls;
4694 BOOL valid_file_acls = True;
4695 BOOL valid_def_acls = True;
4697 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4698 return NT_STATUS_INVALID_PARAMETER;
4700 posix_acl_version = SVAL(pdata,0);
4701 num_file_acls = SVAL(pdata,2);
4702 num_def_acls = SVAL(pdata,4);
4704 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4705 valid_file_acls = False;
4709 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4710 valid_def_acls = False;
4714 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4715 return NT_STATUS_INVALID_PARAMETER;
4718 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4719 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4720 return NT_STATUS_INVALID_PARAMETER;
4723 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4724 fname ? fname : fsp->fsp_name,
4725 (unsigned int)num_file_acls,
4726 (unsigned int)num_def_acls));
4728 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4729 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4730 return map_nt_error_from_unix(errno);
4733 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4734 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4735 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4736 return map_nt_error_from_unix(errno);
4738 return NT_STATUS_OK;
4742 /****************************************************************************
4743 Deal with SMB_SET_POSIX_LOCK.
4744 ****************************************************************************/
4746 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4754 SMB_BIG_UINT offset;
4756 BOOL blocking_lock = False;
4757 enum brl_type lock_type;
4758 NTSTATUS status = NT_STATUS_OK;
4760 if (fsp == NULL || fsp->fh->fd == -1) {
4761 return NT_STATUS_INVALID_HANDLE;
4764 if (total_data != POSIX_LOCK_DATA_SIZE) {
4765 return NT_STATUS_INVALID_PARAMETER;
4768 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4769 case POSIX_LOCK_TYPE_READ:
4770 lock_type = READ_LOCK;
4772 case POSIX_LOCK_TYPE_WRITE:
4773 /* Return the right POSIX-mappable error code for files opened read-only. */
4774 if (!fsp->can_write) {
4775 return NT_STATUS_INVALID_HANDLE;
4777 lock_type = WRITE_LOCK;
4779 case POSIX_LOCK_TYPE_UNLOCK:
4780 lock_type = UNLOCK_LOCK;
4783 return NT_STATUS_INVALID_PARAMETER;
4786 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4787 blocking_lock = False;
4788 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4789 blocking_lock = True;
4791 return NT_STATUS_INVALID_PARAMETER;
4794 if (!lp_blocking_locks(SNUM(conn))) {
4795 blocking_lock = False;
4798 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4799 #if defined(HAVE_LONGLONG)
4800 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4801 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4802 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4803 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4804 #else /* HAVE_LONGLONG */
4805 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4806 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4807 #endif /* HAVE_LONGLONG */
4809 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4810 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4812 (unsigned int)lock_type,
4813 (unsigned int)lock_pid,
4817 if (lock_type == UNLOCK_LOCK) {
4818 status = do_unlock(smbd_messaging_context(),
4825 uint32 block_smbpid;
4827 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4838 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4840 * A blocking lock was requested. Package up
4841 * this smb into a queued request and push it
4842 * onto the blocking lock queue.
4844 if(push_blocking_lock_request(br_lck,
4847 -1, /* infinite timeout. */
4855 TALLOC_FREE(br_lck);
4859 TALLOC_FREE(br_lck);
4865 /****************************************************************************
4866 Deal with SMB_INFO_STANDARD.
4867 ****************************************************************************/
4869 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4874 const SMB_STRUCT_STAT *psbuf)
4876 struct timespec ts[2];
4878 if (total_data < 12) {
4879 return NT_STATUS_INVALID_PARAMETER;
4883 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4885 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4887 DEBUG(10,("smb_set_info_standard: file %s\n",
4888 fname ? fname : fsp->fsp_name ));
4890 return smb_set_file_time(conn,
4897 /****************************************************************************
4898 Deal with SMB_SET_FILE_BASIC_INFO.
4899 ****************************************************************************/
4901 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4906 SMB_STRUCT_STAT *psbuf)
4908 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4909 struct timespec write_time;
4910 struct timespec changed_time;
4912 struct timespec ts[2];
4913 NTSTATUS status = NT_STATUS_OK;
4915 if (total_data < 36) {
4916 return NT_STATUS_INVALID_PARAMETER;
4919 /* Set the attributes */
4920 dosmode = IVAL(pdata,32);
4921 status = smb_set_file_dosmode(conn,
4925 if (!NT_STATUS_IS_OK(status)) {
4929 /* Ignore create time at offset pdata. */
4932 ts[0] = interpret_long_date(pdata+8);
4934 write_time = interpret_long_date(pdata+16);
4935 changed_time = interpret_long_date(pdata+24);
4938 ts[1] = timespec_min(&write_time, &changed_time);
4940 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4944 /* Prefer a defined time to an undefined one. */
4945 if (null_timespec(ts[1])) {
4946 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4949 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4950 fname ? fname : fsp->fsp_name ));
4952 return smb_set_file_time(conn,
4959 /****************************************************************************
4960 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4961 ****************************************************************************/
4963 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4964 struct smb_request *req,
4969 SMB_STRUCT_STAT *psbuf)
4971 SMB_BIG_UINT allocation_size = 0;
4972 NTSTATUS status = NT_STATUS_OK;
4973 files_struct *new_fsp = NULL;
4975 if (!VALID_STAT(*psbuf)) {
4976 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4979 if (total_data < 8) {
4980 return NT_STATUS_INVALID_PARAMETER;
4983 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4984 #ifdef LARGE_SMB_OFF_T
4985 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4986 #else /* LARGE_SMB_OFF_T */
4987 if (IVAL(pdata,4) != 0) {
4988 /* more than 32 bits? */
4989 return NT_STATUS_INVALID_PARAMETER;
4991 #endif /* LARGE_SMB_OFF_T */
4993 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4994 fname, (double)allocation_size ));
4996 if (allocation_size) {
4997 allocation_size = smb_roundup(conn, allocation_size);
5000 if(allocation_size == get_file_size(*psbuf)) {
5001 return NT_STATUS_OK;
5004 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5005 fname, (double)allocation_size ));
5007 if (fsp && fsp->fh->fd != -1) {
5008 /* Open file handle. */
5009 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5010 return map_nt_error_from_unix(errno);
5012 return NT_STATUS_OK;
5015 /* Pathname or stat or directory file. */
5017 status = open_file_ntcreate(conn, req, fname, psbuf,
5019 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5022 FILE_ATTRIBUTE_NORMAL,
5023 FORCE_OPLOCK_BREAK_TO_NONE,
5026 if (!NT_STATUS_IS_OK(status)) {
5027 /* NB. We check for open_was_deferred in the caller. */
5030 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5031 status = map_nt_error_from_unix(errno);
5032 close_file(new_fsp,NORMAL_CLOSE);
5036 close_file(new_fsp,NORMAL_CLOSE);
5037 return NT_STATUS_OK;
5040 /****************************************************************************
5041 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5042 ****************************************************************************/
5044 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5045 struct smb_request *req,
5050 SMB_STRUCT_STAT *psbuf)
5054 if (total_data < 8) {
5055 return NT_STATUS_INVALID_PARAMETER;
5058 size = IVAL(pdata,0);
5059 #ifdef LARGE_SMB_OFF_T
5060 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5061 #else /* LARGE_SMB_OFF_T */
5062 if (IVAL(pdata,4) != 0) {
5063 /* more than 32 bits? */
5064 return NT_STATUS_INVALID_PARAMETER;
5066 #endif /* LARGE_SMB_OFF_T */
5067 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5068 "file %s to %.0f\n", fname, (double)size ));
5070 return smb_set_file_size(conn, req,
5077 /****************************************************************************
5078 Allow a UNIX info mknod.
5079 ****************************************************************************/
5081 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5085 SMB_STRUCT_STAT *psbuf)
5087 uint32 file_type = IVAL(pdata,56);
5088 #if defined(HAVE_MAKEDEV)
5089 uint32 dev_major = IVAL(pdata,60);
5090 uint32 dev_minor = IVAL(pdata,68);
5092 SMB_DEV_T dev = (SMB_DEV_T)0;
5093 uint32 raw_unixmode = IVAL(pdata,84);
5097 if (total_data < 100) {
5098 return NT_STATUS_INVALID_PARAMETER;
5101 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5102 if (!NT_STATUS_IS_OK(status)) {
5106 #if defined(HAVE_MAKEDEV)
5107 dev = makedev(dev_major, dev_minor);
5110 switch (file_type) {
5111 #if defined(S_IFIFO)
5112 case UNIX_TYPE_FIFO:
5113 unixmode |= S_IFIFO;
5116 #if defined(S_IFSOCK)
5117 case UNIX_TYPE_SOCKET:
5118 unixmode |= S_IFSOCK;
5121 #if defined(S_IFCHR)
5122 case UNIX_TYPE_CHARDEV:
5123 unixmode |= S_IFCHR;
5126 #if defined(S_IFBLK)
5127 case UNIX_TYPE_BLKDEV:
5128 unixmode |= S_IFBLK;
5132 return NT_STATUS_INVALID_PARAMETER;
5135 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5136 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5138 /* Ok - do the mknod. */
5139 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5140 return map_nt_error_from_unix(errno);
5143 /* If any of the other "set" calls fail we
5144 * don't want to end up with a half-constructed mknod.
5147 if (lp_inherit_perms(SNUM(conn))) {
5149 conn, parent_dirname(fname),
5153 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5154 status = map_nt_error_from_unix(errno);
5155 SMB_VFS_UNLINK(conn,fname);
5158 return NT_STATUS_OK;
5161 /****************************************************************************
5162 Deal with SMB_SET_FILE_UNIX_BASIC.
5163 ****************************************************************************/
5165 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5166 struct smb_request *req,
5171 SMB_STRUCT_STAT *psbuf)
5173 struct timespec ts[2];
5174 uint32 raw_unixmode;
5177 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5178 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5179 NTSTATUS status = NT_STATUS_OK;
5180 BOOL delete_on_fail = False;
5181 enum perm_type ptype;
5183 if (total_data < 100) {
5184 return NT_STATUS_INVALID_PARAMETER;
5187 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5188 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5189 size=IVAL(pdata,0); /* first 8 Bytes are size */
5190 #ifdef LARGE_SMB_OFF_T
5191 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5192 #else /* LARGE_SMB_OFF_T */
5193 if (IVAL(pdata,4) != 0) {
5194 /* more than 32 bits? */
5195 return NT_STATUS_INVALID_PARAMETER;
5197 #endif /* LARGE_SMB_OFF_T */
5200 ts[0] = interpret_long_date(pdata+24); /* access_time */
5201 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5202 set_owner = (uid_t)IVAL(pdata,40);
5203 set_grp = (gid_t)IVAL(pdata,48);
5204 raw_unixmode = IVAL(pdata,84);
5206 if (VALID_STAT(*psbuf)) {
5207 if (S_ISDIR(psbuf->st_mode)) {
5208 ptype = PERM_EXISTING_DIR;
5210 ptype = PERM_EXISTING_FILE;
5213 ptype = PERM_NEW_FILE;
5216 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5217 if (!NT_STATUS_IS_OK(status)) {
5221 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5222 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5223 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5225 if (!VALID_STAT(*psbuf)) {
5227 * The only valid use of this is to create character and block
5228 * devices, and named pipes. This is deprecated (IMHO) and
5229 * a new info level should be used for mknod. JRA.
5232 status = smb_unix_mknod(conn,
5237 if (!NT_STATUS_IS_OK(status)) {
5241 /* Ensure we don't try and change anything else. */
5242 raw_unixmode = SMB_MODE_NO_CHANGE;
5243 size = get_file_size(*psbuf);
5244 ts[0] = get_atimespec(psbuf);
5245 ts[1] = get_mtimespec(psbuf);
5247 * We continue here as we might want to change the
5250 delete_on_fail = True;
5254 /* Horrible backwards compatibility hack as an old server bug
5255 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5259 size = get_file_size(*psbuf);
5264 * Deal with the UNIX specific mode set.
5267 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5268 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5269 (unsigned int)unixmode, fname ));
5270 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5271 return map_nt_error_from_unix(errno);
5276 * Deal with the UNIX specific uid set.
5279 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5282 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5283 (unsigned int)set_owner, fname ));
5285 if (S_ISLNK(psbuf->st_mode)) {
5286 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5288 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5292 status = map_nt_error_from_unix(errno);
5293 if (delete_on_fail) {
5294 SMB_VFS_UNLINK(conn,fname);
5301 * Deal with the UNIX specific gid set.
5304 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5305 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5306 (unsigned int)set_owner, fname ));
5307 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5308 status = map_nt_error_from_unix(errno);
5309 if (delete_on_fail) {
5310 SMB_VFS_UNLINK(conn,fname);
5316 /* Deal with any size changes. */
5318 status = smb_set_file_size(conn, req,
5323 if (!NT_STATUS_IS_OK(status)) {
5327 /* Deal with any time changes. */
5329 return smb_set_file_time(conn,
5336 /****************************************************************************
5337 Deal with SMB_SET_FILE_UNIX_INFO2.
5338 ****************************************************************************/
5340 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5341 struct smb_request *req,
5346 SMB_STRUCT_STAT *psbuf)
5352 if (total_data < 116) {
5353 return NT_STATUS_INVALID_PARAMETER;
5356 /* Start by setting all the fields that are common between UNIX_BASIC
5359 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5361 if (!NT_STATUS_IS_OK(status)) {
5365 smb_fflags = IVAL(pdata, 108);
5366 smb_fmask = IVAL(pdata, 112);
5368 /* NB: We should only attempt to alter the file flags if the client
5369 * sends a non-zero mask.
5371 if (smb_fmask != 0) {
5372 int stat_fflags = 0;
5374 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5376 /* Client asked to alter a flag we don't understand. */
5377 return NT_STATUS_INVALID_PARAMETER;
5380 if (fsp && fsp->fh->fd != -1) {
5381 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5382 return NT_STATUS_NOT_SUPPORTED;
5384 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5385 return map_nt_error_from_unix(errno);
5390 /* XXX: need to add support for changing the create_time here. You
5391 * can do this for paths on Darwin with setattrlist(2). The right way
5392 * to hook this up is probably by extending the VFS utimes interface.
5395 return NT_STATUS_OK;
5398 /****************************************************************************
5399 Create a directory with POSIX semantics.
5400 ****************************************************************************/
5402 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5403 struct smb_request *req,
5407 SMB_STRUCT_STAT *psbuf,
5408 int *pdata_return_size)
5410 NTSTATUS status = NT_STATUS_OK;
5411 uint32 raw_unixmode = 0;
5412 uint32 mod_unixmode = 0;
5413 mode_t unixmode = (mode_t)0;
5414 files_struct *fsp = NULL;
5415 uint16 info_level_return = 0;
5417 char *pdata = *ppdata;
5419 if (total_data < 18) {
5420 return NT_STATUS_INVALID_PARAMETER;
5423 raw_unixmode = IVAL(pdata,8);
5424 /* Next 4 bytes are not yet defined. */
5426 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5427 if (!NT_STATUS_IS_OK(status)) {
5431 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5433 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5434 fname, (unsigned int)unixmode ));
5436 status = open_directory(conn, req,
5439 FILE_READ_ATTRIBUTES, /* Just a stat open */
5440 FILE_SHARE_NONE, /* Ignored for stat opens */
5447 if (NT_STATUS_IS_OK(status)) {
5448 close_file(fsp, NORMAL_CLOSE);
5451 info_level_return = SVAL(pdata,16);
5453 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5454 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5455 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5456 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5458 *pdata_return_size = 12;
5461 /* Realloc the data size */
5462 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5463 if (*ppdata == NULL) {
5464 *pdata_return_size = 0;
5465 return NT_STATUS_NO_MEMORY;
5469 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5470 SSVAL(pdata,2,0); /* No fnum. */
5471 SIVAL(pdata,4,info); /* Was directory created. */
5473 switch (info_level_return) {
5474 case SMB_QUERY_FILE_UNIX_BASIC:
5475 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5476 SSVAL(pdata,10,0); /* Padding. */
5477 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5479 case SMB_QUERY_FILE_UNIX_INFO2:
5480 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5481 SSVAL(pdata,10,0); /* Padding. */
5482 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5485 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5486 SSVAL(pdata,10,0); /* Padding. */
5493 /****************************************************************************
5494 Open/Create a file with POSIX semantics.
5495 ****************************************************************************/
5497 static NTSTATUS smb_posix_open(connection_struct *conn,
5498 struct smb_request *req,
5502 SMB_STRUCT_STAT *psbuf,
5503 int *pdata_return_size)
5505 BOOL extended_oplock_granted = False;
5506 char *pdata = *ppdata;
5508 uint32 wire_open_mode = 0;
5509 uint32 raw_unixmode = 0;
5510 uint32 mod_unixmode = 0;
5511 uint32 create_disp = 0;
5512 uint32 access_mask = 0;
5513 uint32 create_options = 0;
5514 NTSTATUS status = NT_STATUS_OK;
5515 mode_t unixmode = (mode_t)0;
5516 files_struct *fsp = NULL;
5517 int oplock_request = 0;
5519 uint16 info_level_return = 0;
5521 if (total_data < 18) {
5522 return NT_STATUS_INVALID_PARAMETER;
5525 flags = IVAL(pdata,0);
5526 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5527 if (oplock_request) {
5528 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5531 wire_open_mode = IVAL(pdata,4);
5533 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5534 return smb_posix_mkdir(conn, req,
5542 switch (wire_open_mode & SMB_ACCMODE) {
5544 access_mask = FILE_READ_DATA;
5547 access_mask = FILE_WRITE_DATA;
5550 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5553 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5554 (unsigned int)wire_open_mode ));
5555 return NT_STATUS_INVALID_PARAMETER;
5558 wire_open_mode &= ~SMB_ACCMODE;
5560 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5561 create_disp = FILE_CREATE;
5562 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5563 create_disp = FILE_OVERWRITE_IF;
5564 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5565 create_disp = FILE_OPEN_IF;
5567 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5568 (unsigned int)wire_open_mode ));
5569 return NT_STATUS_INVALID_PARAMETER;
5572 raw_unixmode = IVAL(pdata,8);
5573 /* Next 4 bytes are not yet defined. */
5575 status = unix_perms_from_wire(conn,
5578 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5581 if (!NT_STATUS_IS_OK(status)) {
5585 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5587 if (wire_open_mode & SMB_O_SYNC) {
5588 create_options |= FILE_WRITE_THROUGH;
5590 if (wire_open_mode & SMB_O_APPEND) {
5591 access_mask |= FILE_APPEND_DATA;
5593 if (wire_open_mode & SMB_O_DIRECT) {
5594 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5597 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5599 (unsigned int)wire_open_mode,
5600 (unsigned int)unixmode ));
5602 status = open_file_ntcreate(conn, req,
5606 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5608 0, /* no create options yet. */
5614 if (!NT_STATUS_IS_OK(status)) {
5618 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5619 extended_oplock_granted = True;
5622 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5623 extended_oplock_granted = True;
5626 info_level_return = SVAL(pdata,16);
5628 /* Allocate the correct return size. */
5630 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5631 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5632 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5633 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5635 *pdata_return_size = 12;
5638 /* Realloc the data size */
5639 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5640 if (*ppdata == NULL) {
5641 close_file(fsp,ERROR_CLOSE);
5642 *pdata_return_size = 0;
5643 return NT_STATUS_NO_MEMORY;
5647 if (extended_oplock_granted) {
5648 if (flags & REQUEST_BATCH_OPLOCK) {
5649 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5651 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5653 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5654 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5656 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5659 SSVAL(pdata,2,fsp->fnum);
5660 SIVAL(pdata,4,info); /* Was file created etc. */
5662 switch (info_level_return) {
5663 case SMB_QUERY_FILE_UNIX_BASIC:
5664 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5665 SSVAL(pdata,10,0); /* padding. */
5666 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5668 case SMB_QUERY_FILE_UNIX_INFO2:
5669 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5670 SSVAL(pdata,10,0); /* padding. */
5671 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5674 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5675 SSVAL(pdata,10,0); /* padding. */
5678 return NT_STATUS_OK;
5681 /****************************************************************************
5682 Delete a file with POSIX semantics.
5683 ****************************************************************************/
5685 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5686 struct smb_request *req,
5690 SMB_STRUCT_STAT *psbuf)
5692 NTSTATUS status = NT_STATUS_OK;
5693 files_struct *fsp = NULL;
5697 if (total_data < 2) {
5698 return NT_STATUS_INVALID_PARAMETER;
5701 flags = SVAL(pdata,0);
5703 if (!VALID_STAT(*psbuf)) {
5704 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5707 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5708 !VALID_STAT_OF_DIR(*psbuf)) {
5709 return NT_STATUS_NOT_A_DIRECTORY;
5712 DEBUG(10,("smb_posix_unlink: %s %s\n",
5713 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5716 if (VALID_STAT_OF_DIR(*psbuf)) {
5717 status = open_directory(conn, req,
5721 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5723 FILE_DELETE_ON_CLOSE,
5724 FILE_FLAG_POSIX_SEMANTICS|0777,
5730 status = open_file_ntcreate(conn, req,
5734 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5737 FILE_FLAG_POSIX_SEMANTICS|0777,
5738 0, /* No oplock, but break existing ones. */
5742 * For file opens we must set the delete on close
5746 if (!NT_STATUS_IS_OK(status)) {
5750 status = smb_set_file_disposition_info(conn,
5758 if (!NT_STATUS_IS_OK(status)) {
5761 return close_file(fsp, NORMAL_CLOSE);
5764 /****************************************************************************
5765 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5766 ****************************************************************************/
5768 static int call_trans2setfilepathinfo(connection_struct *conn,
5769 struct smb_request *req,
5770 char *inbuf, char *outbuf, int length,
5772 unsigned int tran_call,
5773 char **pparams, int total_params, char **ppdata, int total_data,
5774 unsigned int max_data_bytes)
5776 char *params = *pparams;
5777 char *pdata = *ppdata;
5779 SMB_STRUCT_STAT sbuf;
5781 files_struct *fsp = NULL;
5782 NTSTATUS status = NT_STATUS_OK;
5783 int data_return_size = 0;
5786 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5791 if (tran_call == TRANSACT2_SETFILEINFO) {
5792 if (total_params < 4) {
5793 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5796 fsp = file_fsp(params,0);
5797 info_level = SVAL(params,2);
5799 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5801 * This is actually a SETFILEINFO on a directory
5802 * handle (returned from an NT SMB). NT5.0 seems
5803 * to do this call. JRA.
5805 pstrcpy(fname, fsp->fsp_name);
5806 if (INFO_LEVEL_IS_UNIX(info_level)) {
5807 /* Always do lstat for UNIX calls. */
5808 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5809 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5810 return UNIXERROR(ERRDOS,ERRbadpath);
5813 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5814 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5815 return UNIXERROR(ERRDOS,ERRbadpath);
5818 } else if (fsp && fsp->print_file) {
5820 * Doing a DELETE_ON_CLOSE should cancel a print job.
5822 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5823 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5825 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5828 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5831 return (UNIXERROR(ERRDOS,ERRbadpath));
5834 * Original code - this is an open file.
5836 CHECK_FSP(fsp,conn);
5838 pstrcpy(fname, fsp->fsp_name);
5840 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5841 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5842 return(UNIXERROR(ERRDOS,ERRbadfid));
5847 if (total_params < 7) {
5848 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5851 info_level = SVAL(params,0);
5852 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5853 if (!NT_STATUS_IS_OK(status)) {
5854 return ERROR_NT(status);
5857 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5858 if (!NT_STATUS_IS_OK(status)) {
5859 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5860 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5862 return ERROR_NT(status);
5865 status = unix_convert(conn, fname, False, NULL, &sbuf);
5866 if (!NT_STATUS_IS_OK(status)) {
5867 return ERROR_NT(status);
5870 status = check_name(conn, fname);
5871 if (!NT_STATUS_IS_OK(status)) {
5872 return ERROR_NT(status);
5875 if (INFO_LEVEL_IS_UNIX(info_level)) {
5877 * For CIFS UNIX extensions the target name may not exist.
5880 /* Always do lstat for UNIX calls. */
5881 SMB_VFS_LSTAT(conn,fname,&sbuf);
5883 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5884 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5885 return UNIXERROR(ERRDOS,ERRbadpath);
5889 if (!CAN_WRITE(conn)) {
5890 return ERROR_DOS(ERRSRV,ERRaccess);
5893 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5894 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5897 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5898 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5900 /* Realloc the parameter size */
5901 *pparams = (char *)SMB_REALLOC(*pparams,2);
5902 if (*pparams == NULL) {
5903 return ERROR_NT(NT_STATUS_NO_MEMORY);
5909 if (fsp && !null_timespec(fsp->pending_modtime)) {
5910 /* the pending modtime overrides the current modtime */
5911 set_mtimespec(&sbuf, fsp->pending_modtime);
5914 switch (info_level) {
5916 case SMB_INFO_STANDARD:
5918 status = smb_set_info_standard(conn,
5927 case SMB_INFO_SET_EA:
5929 status = smb_info_set_ea(conn,
5937 case SMB_SET_FILE_BASIC_INFO:
5938 case SMB_FILE_BASIC_INFORMATION:
5940 status = smb_set_file_basic_info(conn,
5949 case SMB_FILE_ALLOCATION_INFORMATION:
5950 case SMB_SET_FILE_ALLOCATION_INFO:
5952 status = smb_set_file_allocation_info(conn, req,
5961 case SMB_FILE_END_OF_FILE_INFORMATION:
5962 case SMB_SET_FILE_END_OF_FILE_INFO:
5964 status = smb_set_file_end_of_file_info(conn, req,
5973 case SMB_FILE_DISPOSITION_INFORMATION:
5974 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5977 /* JRA - We used to just ignore this on a path ?
5978 * Shouldn't this be invalid level on a pathname
5981 if (tran_call != TRANSACT2_SETFILEINFO) {
5982 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5985 status = smb_set_file_disposition_info(conn,
5994 case SMB_FILE_POSITION_INFORMATION:
5996 status = smb_file_position_information(conn,
6003 /* From tridge Samba4 :
6004 * MODE_INFORMATION in setfileinfo (I have no
6005 * idea what "mode information" on a file is - it takes a value of 0,
6006 * 2, 4 or 6. What could it be?).
6009 case SMB_FILE_MODE_INFORMATION:
6011 status = smb_file_mode_information(conn,
6018 * CIFS UNIX extensions.
6021 case SMB_SET_FILE_UNIX_BASIC:
6023 status = smb_set_file_unix_basic(conn, req,
6032 case SMB_SET_FILE_UNIX_INFO2:
6034 status = smb_set_file_unix_info2(conn, req,
6043 case SMB_SET_FILE_UNIX_LINK:
6045 if (tran_call != TRANSACT2_SETPATHINFO) {
6046 /* We must have a pathname for this. */
6047 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6049 status = smb_set_file_unix_link(conn,
6057 case SMB_SET_FILE_UNIX_HLINK:
6059 if (tran_call != TRANSACT2_SETPATHINFO) {
6060 /* We must have a pathname for this. */
6061 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6063 status = smb_set_file_unix_hlink(conn,
6072 case SMB_FILE_RENAME_INFORMATION:
6074 status = smb_file_rename_information(conn, req,
6084 #if defined(HAVE_POSIX_ACLS)
6085 case SMB_SET_POSIX_ACL:
6087 status = smb_set_posix_acl(conn,
6097 case SMB_SET_POSIX_LOCK:
6099 if (tran_call != TRANSACT2_SETFILEINFO) {
6100 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6102 status = smb_set_posix_lock(conn,
6111 case SMB_POSIX_PATH_OPEN:
6113 if (tran_call != TRANSACT2_SETPATHINFO) {
6114 /* We must have a pathname for this. */
6115 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6118 status = smb_posix_open(conn, req,
6127 case SMB_POSIX_PATH_UNLINK:
6129 if (tran_call != TRANSACT2_SETPATHINFO) {
6130 /* We must have a pathname for this. */
6131 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6134 status = smb_posix_unlink(conn, req,
6143 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6147 if (!NT_STATUS_IS_OK(status)) {
6148 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6149 /* We have re-scheduled this call. */
6152 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6153 /* We have re-scheduled this call. */
6156 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6157 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6159 return ERROR_NT(status);
6163 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6168 /****************************************************************************
6169 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6170 ****************************************************************************/
6172 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6173 char **pparams, int total_params, char **ppdata, int total_data,
6174 unsigned int max_data_bytes)
6176 char *params = *pparams;
6177 char *pdata = *ppdata;
6179 SMB_STRUCT_STAT sbuf;
6180 NTSTATUS status = NT_STATUS_OK;
6181 struct ea_list *ea_list = NULL;
6183 if (!CAN_WRITE(conn))
6184 return ERROR_DOS(ERRSRV,ERRaccess);
6186 if (total_params < 5) {
6187 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6190 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6191 if (!NT_STATUS_IS_OK(status)) {
6192 return ERROR_NT(status);
6195 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6197 status = unix_convert(conn, directory, False, NULL, &sbuf);
6198 if (!NT_STATUS_IS_OK(status)) {
6199 return ERROR_NT(status);
6202 status = check_name(conn, directory);
6203 if (!NT_STATUS_IS_OK(status)) {
6204 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6205 return ERROR_NT(status);
6208 /* Any data in this call is an EA list. */
6209 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6210 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6214 * OS/2 workplace shell seems to send SET_EA requests of "null"
6215 * length (4 bytes containing IVAL 4).
6216 * They seem to have no effect. Bug #3212. JRA.
6219 if (total_data != 4) {
6220 if (total_data < 10) {
6221 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6224 if (IVAL(pdata,0) > total_data) {
6225 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6226 IVAL(pdata,0), (unsigned int)total_data));
6227 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6230 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6233 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6235 } else if (IVAL(pdata,0) != 4) {
6236 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6239 status = create_directory(conn, directory);
6241 if (!NT_STATUS_IS_OK(status)) {
6242 return ERROR_NT(status);
6245 /* Try and set any given EA. */
6247 status = set_ea(conn, NULL, directory, ea_list);
6248 if (!NT_STATUS_IS_OK(status)) {
6249 return ERROR_NT(status);
6253 /* Realloc the parameter and data sizes */
6254 *pparams = (char *)SMB_REALLOC(*pparams,2);
6255 if(*pparams == NULL) {
6256 return ERROR_NT(NT_STATUS_NO_MEMORY);
6262 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6267 /****************************************************************************
6268 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6269 We don't actually do this - we just send a null response.
6270 ****************************************************************************/
6272 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6273 char **pparams, int total_params, char **ppdata, int total_data,
6274 unsigned int max_data_bytes)
6276 static uint16 fnf_handle = 257;
6277 char *params = *pparams;
6280 if (total_params < 6) {
6281 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6284 info_level = SVAL(params,4);
6285 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6287 switch (info_level) {
6292 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6295 /* Realloc the parameter and data sizes */
6296 *pparams = (char *)SMB_REALLOC(*pparams,6);
6297 if (*pparams == NULL) {
6298 return ERROR_NT(NT_STATUS_NO_MEMORY);
6302 SSVAL(params,0,fnf_handle);
6303 SSVAL(params,2,0); /* No changes */
6304 SSVAL(params,4,0); /* No EA errors */
6311 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6316 /****************************************************************************
6317 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6318 changes). Currently this does nothing.
6319 ****************************************************************************/
6321 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6322 char **pparams, int total_params, char **ppdata, int total_data,
6323 unsigned int max_data_bytes)
6325 char *params = *pparams;
6327 DEBUG(3,("call_trans2findnotifynext\n"));
6329 /* Realloc the parameter and data sizes */
6330 *pparams = (char *)SMB_REALLOC(*pparams,4);
6331 if (*pparams == NULL) {
6332 return ERROR_NT(NT_STATUS_NO_MEMORY);
6336 SSVAL(params,0,0); /* No changes */
6337 SSVAL(params,2,0); /* No EA errors */
6339 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6344 /****************************************************************************
6345 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6346 ****************************************************************************/
6348 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6349 char **pparams, int total_params, char **ppdata, int total_data,
6350 unsigned int max_data_bytes)
6352 char *params = *pparams;
6355 int max_referral_level;
6356 NTSTATUS status = NT_STATUS_OK;
6358 DEBUG(10,("call_trans2getdfsreferral\n"));
6360 if (total_params < 3) {
6361 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6364 max_referral_level = SVAL(params,0);
6366 if(!lp_host_msdfs())
6367 return ERROR_DOS(ERRDOS,ERRbadfunc);
6369 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6370 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6371 return ERROR_NT(status);
6373 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6374 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6379 #define LMCAT_SPL 0x53
6380 #define LMFUNC_GETJOBID 0x60
6382 /****************************************************************************
6383 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6384 ****************************************************************************/
6386 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6387 char **pparams, int total_params, char **ppdata, int total_data,
6388 unsigned int max_data_bytes)
6390 char *pdata = *ppdata;
6391 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6393 /* check for an invalid fid before proceeding */
6396 return(ERROR_DOS(ERRDOS,ERRbadfid));
6398 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6399 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6400 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6401 if (*ppdata == NULL) {
6402 return ERROR_NT(NT_STATUS_NO_MEMORY);
6406 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6407 CAN ACCEPT THIS IN UNICODE. JRA. */
6409 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6410 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6411 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6412 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6415 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6416 return ERROR_DOS(ERRSRV,ERRerror);
6420 /****************************************************************************
6421 Reply to a SMBfindclose (stop trans2 directory search).
6422 ****************************************************************************/
6424 int reply_findclose(connection_struct *conn,
6425 char *inbuf,char *outbuf,int length,int bufsize)
6428 int dptr_num=SVALS(inbuf,smb_vwv0);
6429 START_PROFILE(SMBfindclose);
6431 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6433 dptr_close(&dptr_num);
6435 outsize = set_message(inbuf, outbuf,0,0,False);
6437 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6439 END_PROFILE(SMBfindclose);
6443 /****************************************************************************
6444 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6445 ****************************************************************************/
6447 int reply_findnclose(connection_struct *conn,
6448 char *inbuf,char *outbuf,int length,int bufsize)
6452 START_PROFILE(SMBfindnclose);
6454 dptr_num = SVAL(inbuf,smb_vwv0);
6456 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6458 /* We never give out valid handles for a
6459 findnotifyfirst - so any dptr_num is ok here.
6462 outsize = set_message(inbuf, outbuf,0,0,False);
6464 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6466 END_PROFILE(SMBfindnclose);
6470 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6471 struct trans_state *state,
6472 char *inbuf, char *outbuf, int size, int bufsize)
6476 if (Protocol >= PROTOCOL_NT1) {
6477 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6480 /* Now we must call the relevant TRANS2 function */
6481 switch(state->call) {
6482 case TRANSACT2_OPEN:
6484 START_PROFILE(Trans2_open);
6485 outsize = call_trans2open(
6486 conn, req, inbuf, outbuf, bufsize,
6487 &state->param, state->total_param,
6488 &state->data, state->total_data,
6489 state->max_data_return);
6490 END_PROFILE(Trans2_open);
6494 case TRANSACT2_FINDFIRST:
6496 START_PROFILE(Trans2_findfirst);
6497 outsize = call_trans2findfirst(
6498 conn, inbuf, outbuf, bufsize,
6499 &state->param, state->total_param,
6500 &state->data, state->total_data,
6501 state->max_data_return);
6502 END_PROFILE(Trans2_findfirst);
6506 case TRANSACT2_FINDNEXT:
6508 START_PROFILE(Trans2_findnext);
6509 outsize = call_trans2findnext(
6510 conn, inbuf, outbuf, size, bufsize,
6511 &state->param, state->total_param,
6512 &state->data, state->total_data,
6513 state->max_data_return);
6514 END_PROFILE(Trans2_findnext);
6518 case TRANSACT2_QFSINFO:
6520 START_PROFILE(Trans2_qfsinfo);
6521 outsize = call_trans2qfsinfo(
6522 conn, inbuf, outbuf, size, bufsize,
6523 &state->param, state->total_param,
6524 &state->data, state->total_data,
6525 state->max_data_return);
6526 END_PROFILE(Trans2_qfsinfo);
6530 case TRANSACT2_SETFSINFO:
6532 START_PROFILE(Trans2_setfsinfo);
6533 outsize = call_trans2setfsinfo(
6534 conn, inbuf, outbuf, size, bufsize,
6535 &state->param, state->total_param,
6536 &state->data, state->total_data,
6537 state->max_data_return);
6538 END_PROFILE(Trans2_setfsinfo);
6542 case TRANSACT2_QPATHINFO:
6543 case TRANSACT2_QFILEINFO:
6545 START_PROFILE(Trans2_qpathinfo);
6546 outsize = call_trans2qfilepathinfo(
6547 conn, inbuf, outbuf, size, bufsize, state->call,
6548 &state->param, state->total_param,
6549 &state->data, state->total_data,
6550 state->max_data_return);
6551 END_PROFILE(Trans2_qpathinfo);
6555 case TRANSACT2_SETPATHINFO:
6556 case TRANSACT2_SETFILEINFO:
6558 START_PROFILE(Trans2_setpathinfo);
6559 outsize = call_trans2setfilepathinfo(
6560 conn, req, inbuf, outbuf, size, bufsize, state->call,
6561 &state->param, state->total_param,
6562 &state->data, state->total_data,
6563 state->max_data_return);
6564 END_PROFILE(Trans2_setpathinfo);
6568 case TRANSACT2_FINDNOTIFYFIRST:
6570 START_PROFILE(Trans2_findnotifyfirst);
6571 outsize = call_trans2findnotifyfirst(
6572 conn, inbuf, outbuf, size, bufsize,
6573 &state->param, state->total_param,
6574 &state->data, state->total_data,
6575 state->max_data_return);
6576 END_PROFILE(Trans2_findnotifyfirst);
6580 case TRANSACT2_FINDNOTIFYNEXT:
6582 START_PROFILE(Trans2_findnotifynext);
6583 outsize = call_trans2findnotifynext(
6584 conn, inbuf, outbuf, size, bufsize,
6585 &state->param, state->total_param,
6586 &state->data, state->total_data,
6587 state->max_data_return);
6588 END_PROFILE(Trans2_findnotifynext);
6592 case TRANSACT2_MKDIR:
6594 START_PROFILE(Trans2_mkdir);
6595 outsize = call_trans2mkdir(
6596 conn, inbuf, outbuf, size, bufsize,
6597 &state->param, state->total_param,
6598 &state->data, state->total_data,
6599 state->max_data_return);
6600 END_PROFILE(Trans2_mkdir);
6604 case TRANSACT2_GET_DFS_REFERRAL:
6606 START_PROFILE(Trans2_get_dfs_referral);
6607 outsize = call_trans2getdfsreferral(
6608 conn, inbuf, outbuf, size, bufsize,
6609 &state->param, state->total_param,
6610 &state->data, state->total_data,
6611 state->max_data_return);
6612 END_PROFILE(Trans2_get_dfs_referral);
6616 case TRANSACT2_IOCTL:
6618 START_PROFILE(Trans2_ioctl);
6619 outsize = call_trans2ioctl(
6620 conn, inbuf, outbuf, size, bufsize,
6621 &state->param, state->total_param,
6622 &state->data, state->total_data,
6623 state->max_data_return);
6624 END_PROFILE(Trans2_ioctl);
6629 /* Error in request */
6630 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6631 outsize = ERROR_DOS(ERRSRV,ERRerror);
6637 /****************************************************************************
6638 Reply to a SMBtrans2.
6639 ****************************************************************************/
6641 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6642 int size, int bufsize)
6645 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6646 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6647 unsigned int psoff = SVAL(inbuf, smb_psoff);
6648 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6649 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6650 struct trans_state *state;
6653 START_PROFILE(SMBtrans2);
6655 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6656 if (!NT_STATUS_IS_OK(result)) {
6657 DEBUG(2, ("Got invalid trans2 request: %s\n",
6658 nt_errstr(result)));
6659 END_PROFILE(SMBtrans2);
6660 return ERROR_NT(result);
6663 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6664 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6665 && (tran_call != TRANSACT2_QFILEINFO)) {
6666 END_PROFILE(SMBtrans2);
6667 return ERROR_DOS(ERRSRV,ERRaccess);
6670 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6671 DEBUG(0, ("talloc failed\n"));
6672 END_PROFILE(SMBtrans2);
6673 return ERROR_NT(NT_STATUS_NO_MEMORY);
6676 state->cmd = SMBtrans2;
6678 state->mid = SVAL(inbuf, smb_mid);
6679 state->vuid = SVAL(inbuf, smb_uid);
6680 state->setup_count = SVAL(inbuf, smb_suwcnt);
6681 state->setup = NULL;
6682 state->total_param = SVAL(inbuf, smb_tpscnt);
6683 state->param = NULL;
6684 state->total_data = SVAL(inbuf, smb_tdscnt);
6686 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6687 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6688 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6689 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6690 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6692 state->call = tran_call;
6694 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6695 is so as a sanity check */
6696 if (state->setup_count != 1) {
6698 * Need to have rc=0 for ioctl to get job id for OS/2.
6699 * Network printing will fail if function is not successful.
6700 * Similar function in reply.c will be used if protocol
6701 * is LANMAN1.0 instead of LM1.2X002.
6702 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6703 * outbuf doesn't have to be set(only job id is used).
6705 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6706 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6707 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6708 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6710 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6711 DEBUG(2,("Transaction is %d\n",tran_call));
6713 END_PROFILE(SMBtrans2);
6714 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6718 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6721 if (state->total_data) {
6722 /* Can't use talloc here, the core routines do realloc on the
6723 * params and data. */
6724 state->data = (char *)SMB_MALLOC(state->total_data);
6725 if (state->data == NULL) {
6726 DEBUG(0,("reply_trans2: data malloc fail for %u "
6727 "bytes !\n", (unsigned int)state->total_data));
6729 END_PROFILE(SMBtrans2);
6730 return(ERROR_DOS(ERRDOS,ERRnomem));
6732 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6734 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6735 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6738 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6741 if (state->total_param) {
6742 /* Can't use talloc here, the core routines do realloc on the
6743 * params and data. */
6744 state->param = (char *)SMB_MALLOC(state->total_param);
6745 if (state->param == NULL) {
6746 DEBUG(0,("reply_trans: param malloc fail for %u "
6747 "bytes !\n", (unsigned int)state->total_param));
6748 SAFE_FREE(state->data);
6750 END_PROFILE(SMBtrans2);
6751 return(ERROR_DOS(ERRDOS,ERRnomem));
6753 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6755 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6756 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6759 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6762 state->received_data = dscnt;
6763 state->received_param = pscnt;
6765 if ((state->received_param == state->total_param) &&
6766 (state->received_data == state->total_data)) {
6768 struct smb_request req;
6769 init_smb_request(&req, (uint8 *)inbuf);
6771 outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
6773 SAFE_FREE(state->data);
6774 SAFE_FREE(state->param);
6776 END_PROFILE(SMBtrans2);
6780 DLIST_ADD(conn->pending_trans, state);
6782 /* We need to send an interim response then receive the rest
6783 of the parameter/data bytes */
6784 outsize = set_message(inbuf, outbuf,0,0,False);
6786 END_PROFILE(SMBtrans2);
6791 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6792 SAFE_FREE(state->data);
6793 SAFE_FREE(state->param);
6795 END_PROFILE(SMBtrans2);
6796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6800 /****************************************************************************
6801 Reply to a SMBtranss2
6802 ****************************************************************************/
6804 int reply_transs2(connection_struct *conn,
6805 char *inbuf,char *outbuf,int size,int bufsize)
6808 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6809 struct trans_state *state;
6810 struct smb_request req;
6812 START_PROFILE(SMBtranss2);
6816 for (state = conn->pending_trans; state != NULL;
6817 state = state->next) {
6818 if (state->mid == SVAL(inbuf,smb_mid)) {
6823 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6824 END_PROFILE(SMBtranss2);
6825 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6828 /* Revise state->total_param and state->total_data in case they have
6829 changed downwards */
6831 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6832 state->total_param = SVAL(inbuf, smb_tpscnt);
6833 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6834 state->total_data = SVAL(inbuf, smb_tdscnt);
6836 pcnt = SVAL(inbuf, smb_spscnt);
6837 poff = SVAL(inbuf, smb_spsoff);
6838 pdisp = SVAL(inbuf, smb_spsdisp);
6840 dcnt = SVAL(inbuf, smb_sdscnt);
6841 doff = SVAL(inbuf, smb_sdsoff);
6842 ddisp = SVAL(inbuf, smb_sdsdisp);
6844 state->received_param += pcnt;
6845 state->received_data += dcnt;
6847 if ((state->received_data > state->total_data) ||
6848 (state->received_param > state->total_param))
6852 if (pdisp+pcnt > state->total_param)
6854 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6856 if (pdisp > state->total_param)
6858 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6859 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6861 if (state->param + pdisp < state->param)
6864 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6869 if (ddisp+dcnt > state->total_data)
6871 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6873 if (ddisp > state->total_data)
6875 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6876 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6878 if (state->data + ddisp < state->data)
6881 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6885 if ((state->received_param < state->total_param) ||
6886 (state->received_data < state->total_data)) {
6887 END_PROFILE(SMBtranss2);
6891 /* construct_reply_common has done us the favor to pre-fill the
6892 * command field with SMBtranss2 which is wrong :-)
6894 SCVAL(outbuf,smb_com,SMBtrans2);
6896 init_smb_request(&req, (uint8 *)inbuf);
6898 outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
6901 DLIST_REMOVE(conn->pending_trans, state);
6902 SAFE_FREE(state->data);
6903 SAFE_FREE(state->param);
6907 END_PROFILE(SMBtranss2);
6908 return(ERROR_DOS(ERRSRV,ERRnosupport));
6911 END_PROFILE(SMBtranss2);
6916 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6917 DLIST_REMOVE(conn->pending_trans, state);
6918 SAFE_FREE(state->data);
6919 SAFE_FREE(state->param);
6921 END_PROFILE(SMBtranss2);
6922 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);