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, SVAL(inbuf, smb_flg2), link_target, pdata,
4534 sizeof(link_target), total_data, STR_TERMINATE);
4536 /* !widelinks forces the target path to be within the share. */
4537 /* This means we can interpret the target as a pathname. */
4538 if (!lp_widelinks(SNUM(conn))) {
4540 char *last_dirp = NULL;
4542 if (*link_target == '/') {
4543 /* No absolute paths allowed. */
4544 return NT_STATUS_ACCESS_DENIED;
4546 pstrcpy(rel_name, newname);
4547 last_dirp = strrchr_m(rel_name, '/');
4549 last_dirp[1] = '\0';
4551 pstrcpy(rel_name, "./");
4553 pstrcat(rel_name, link_target);
4555 status = check_name(conn, rel_name);
4556 if (!NT_STATUS_IS_OK(status)) {
4561 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4562 newname, link_target ));
4564 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4565 return map_nt_error_from_unix(errno);
4568 return NT_STATUS_OK;
4571 /****************************************************************************
4572 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4573 ****************************************************************************/
4575 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4583 NTSTATUS status = NT_STATUS_OK;
4585 /* Set a hard link. */
4586 if (total_data == 0) {
4587 return NT_STATUS_INVALID_PARAMETER;
4590 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4591 if (!NT_STATUS_IS_OK(status)) {
4595 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4596 if (!NT_STATUS_IS_OK(status)) {
4600 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4603 return hardlink_internals(conn, oldname, fname);
4606 /****************************************************************************
4607 Deal with SMB_FILE_RENAME_INFORMATION.
4608 ****************************************************************************/
4610 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4611 struct smb_request *req,
4624 BOOL dest_has_wcard = False;
4625 NTSTATUS status = NT_STATUS_OK;
4628 if (total_data < 13) {
4629 return NT_STATUS_INVALID_PARAMETER;
4632 overwrite = (CVAL(pdata,0) ? True : False);
4633 root_fid = IVAL(pdata,4);
4634 len = IVAL(pdata,8);
4636 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4637 return NT_STATUS_INVALID_PARAMETER;
4640 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4641 if (!NT_STATUS_IS_OK(status)) {
4645 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4646 if (!NT_STATUS_IS_OK(status)) {
4650 /* Check the new name has no '/' characters. */
4651 if (strchr_m(newname, '/')) {
4652 return NT_STATUS_NOT_SUPPORTED;
4655 /* Create the base directory. */
4656 pstrcpy(base_name, fname);
4657 p = strrchr_m(base_name, '/');
4661 pstrcpy(base_name, "./");
4663 /* Append the new name. */
4664 pstrcat(base_name, newname);
4667 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4668 fsp->fnum, fsp->fsp_name, base_name ));
4669 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4671 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4673 status = rename_internals(conn, req, fname, base_name, 0,
4674 overwrite, False, dest_has_wcard);
4680 /****************************************************************************
4681 Deal with SMB_SET_POSIX_ACL.
4682 ****************************************************************************/
4684 #if defined(HAVE_POSIX_ACLS)
4685 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4690 SMB_STRUCT_STAT *psbuf)
4692 uint16 posix_acl_version;
4693 uint16 num_file_acls;
4694 uint16 num_def_acls;
4695 BOOL valid_file_acls = True;
4696 BOOL valid_def_acls = True;
4698 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4699 return NT_STATUS_INVALID_PARAMETER;
4701 posix_acl_version = SVAL(pdata,0);
4702 num_file_acls = SVAL(pdata,2);
4703 num_def_acls = SVAL(pdata,4);
4705 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4706 valid_file_acls = False;
4710 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4711 valid_def_acls = False;
4715 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4716 return NT_STATUS_INVALID_PARAMETER;
4719 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4720 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4721 return NT_STATUS_INVALID_PARAMETER;
4724 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4725 fname ? fname : fsp->fsp_name,
4726 (unsigned int)num_file_acls,
4727 (unsigned int)num_def_acls));
4729 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4730 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4731 return map_nt_error_from_unix(errno);
4734 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4735 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4736 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4737 return map_nt_error_from_unix(errno);
4739 return NT_STATUS_OK;
4743 /****************************************************************************
4744 Deal with SMB_SET_POSIX_LOCK.
4745 ****************************************************************************/
4747 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4755 SMB_BIG_UINT offset;
4757 BOOL blocking_lock = False;
4758 enum brl_type lock_type;
4759 NTSTATUS status = NT_STATUS_OK;
4761 if (fsp == NULL || fsp->fh->fd == -1) {
4762 return NT_STATUS_INVALID_HANDLE;
4765 if (total_data != POSIX_LOCK_DATA_SIZE) {
4766 return NT_STATUS_INVALID_PARAMETER;
4769 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4770 case POSIX_LOCK_TYPE_READ:
4771 lock_type = READ_LOCK;
4773 case POSIX_LOCK_TYPE_WRITE:
4774 /* Return the right POSIX-mappable error code for files opened read-only. */
4775 if (!fsp->can_write) {
4776 return NT_STATUS_INVALID_HANDLE;
4778 lock_type = WRITE_LOCK;
4780 case POSIX_LOCK_TYPE_UNLOCK:
4781 lock_type = UNLOCK_LOCK;
4784 return NT_STATUS_INVALID_PARAMETER;
4787 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4788 blocking_lock = False;
4789 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4790 blocking_lock = True;
4792 return NT_STATUS_INVALID_PARAMETER;
4795 if (!lp_blocking_locks(SNUM(conn))) {
4796 blocking_lock = False;
4799 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4800 #if defined(HAVE_LONGLONG)
4801 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4802 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4803 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4804 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4805 #else /* HAVE_LONGLONG */
4806 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4807 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4808 #endif /* HAVE_LONGLONG */
4810 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4811 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4813 (unsigned int)lock_type,
4814 (unsigned int)lock_pid,
4818 if (lock_type == UNLOCK_LOCK) {
4819 status = do_unlock(smbd_messaging_context(),
4826 uint32 block_smbpid;
4828 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4839 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4841 * A blocking lock was requested. Package up
4842 * this smb into a queued request and push it
4843 * onto the blocking lock queue.
4845 if(push_blocking_lock_request(br_lck,
4848 -1, /* infinite timeout. */
4856 TALLOC_FREE(br_lck);
4860 TALLOC_FREE(br_lck);
4866 /****************************************************************************
4867 Deal with SMB_INFO_STANDARD.
4868 ****************************************************************************/
4870 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4875 const SMB_STRUCT_STAT *psbuf)
4877 struct timespec ts[2];
4879 if (total_data < 12) {
4880 return NT_STATUS_INVALID_PARAMETER;
4884 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4886 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4888 DEBUG(10,("smb_set_info_standard: file %s\n",
4889 fname ? fname : fsp->fsp_name ));
4891 return smb_set_file_time(conn,
4898 /****************************************************************************
4899 Deal with SMB_SET_FILE_BASIC_INFO.
4900 ****************************************************************************/
4902 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4907 SMB_STRUCT_STAT *psbuf)
4909 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4910 struct timespec write_time;
4911 struct timespec changed_time;
4913 struct timespec ts[2];
4914 NTSTATUS status = NT_STATUS_OK;
4916 if (total_data < 36) {
4917 return NT_STATUS_INVALID_PARAMETER;
4920 /* Set the attributes */
4921 dosmode = IVAL(pdata,32);
4922 status = smb_set_file_dosmode(conn,
4926 if (!NT_STATUS_IS_OK(status)) {
4930 /* Ignore create time at offset pdata. */
4933 ts[0] = interpret_long_date(pdata+8);
4935 write_time = interpret_long_date(pdata+16);
4936 changed_time = interpret_long_date(pdata+24);
4939 ts[1] = timespec_min(&write_time, &changed_time);
4941 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4945 /* Prefer a defined time to an undefined one. */
4946 if (null_timespec(ts[1])) {
4947 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4950 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4951 fname ? fname : fsp->fsp_name ));
4953 return smb_set_file_time(conn,
4960 /****************************************************************************
4961 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4962 ****************************************************************************/
4964 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4965 struct smb_request *req,
4970 SMB_STRUCT_STAT *psbuf)
4972 SMB_BIG_UINT allocation_size = 0;
4973 NTSTATUS status = NT_STATUS_OK;
4974 files_struct *new_fsp = NULL;
4976 if (!VALID_STAT(*psbuf)) {
4977 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4980 if (total_data < 8) {
4981 return NT_STATUS_INVALID_PARAMETER;
4984 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4985 #ifdef LARGE_SMB_OFF_T
4986 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4987 #else /* LARGE_SMB_OFF_T */
4988 if (IVAL(pdata,4) != 0) {
4989 /* more than 32 bits? */
4990 return NT_STATUS_INVALID_PARAMETER;
4992 #endif /* LARGE_SMB_OFF_T */
4994 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4995 fname, (double)allocation_size ));
4997 if (allocation_size) {
4998 allocation_size = smb_roundup(conn, allocation_size);
5001 if(allocation_size == get_file_size(*psbuf)) {
5002 return NT_STATUS_OK;
5005 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5006 fname, (double)allocation_size ));
5008 if (fsp && fsp->fh->fd != -1) {
5009 /* Open file handle. */
5010 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5011 return map_nt_error_from_unix(errno);
5013 return NT_STATUS_OK;
5016 /* Pathname or stat or directory file. */
5018 status = open_file_ntcreate(conn, req, fname, psbuf,
5020 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5023 FILE_ATTRIBUTE_NORMAL,
5024 FORCE_OPLOCK_BREAK_TO_NONE,
5027 if (!NT_STATUS_IS_OK(status)) {
5028 /* NB. We check for open_was_deferred in the caller. */
5031 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5032 status = map_nt_error_from_unix(errno);
5033 close_file(new_fsp,NORMAL_CLOSE);
5037 close_file(new_fsp,NORMAL_CLOSE);
5038 return NT_STATUS_OK;
5041 /****************************************************************************
5042 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5043 ****************************************************************************/
5045 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5046 struct smb_request *req,
5051 SMB_STRUCT_STAT *psbuf)
5055 if (total_data < 8) {
5056 return NT_STATUS_INVALID_PARAMETER;
5059 size = IVAL(pdata,0);
5060 #ifdef LARGE_SMB_OFF_T
5061 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5062 #else /* LARGE_SMB_OFF_T */
5063 if (IVAL(pdata,4) != 0) {
5064 /* more than 32 bits? */
5065 return NT_STATUS_INVALID_PARAMETER;
5067 #endif /* LARGE_SMB_OFF_T */
5068 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5069 "file %s to %.0f\n", fname, (double)size ));
5071 return smb_set_file_size(conn, req,
5078 /****************************************************************************
5079 Allow a UNIX info mknod.
5080 ****************************************************************************/
5082 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5086 SMB_STRUCT_STAT *psbuf)
5088 uint32 file_type = IVAL(pdata,56);
5089 #if defined(HAVE_MAKEDEV)
5090 uint32 dev_major = IVAL(pdata,60);
5091 uint32 dev_minor = IVAL(pdata,68);
5093 SMB_DEV_T dev = (SMB_DEV_T)0;
5094 uint32 raw_unixmode = IVAL(pdata,84);
5098 if (total_data < 100) {
5099 return NT_STATUS_INVALID_PARAMETER;
5102 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5103 if (!NT_STATUS_IS_OK(status)) {
5107 #if defined(HAVE_MAKEDEV)
5108 dev = makedev(dev_major, dev_minor);
5111 switch (file_type) {
5112 #if defined(S_IFIFO)
5113 case UNIX_TYPE_FIFO:
5114 unixmode |= S_IFIFO;
5117 #if defined(S_IFSOCK)
5118 case UNIX_TYPE_SOCKET:
5119 unixmode |= S_IFSOCK;
5122 #if defined(S_IFCHR)
5123 case UNIX_TYPE_CHARDEV:
5124 unixmode |= S_IFCHR;
5127 #if defined(S_IFBLK)
5128 case UNIX_TYPE_BLKDEV:
5129 unixmode |= S_IFBLK;
5133 return NT_STATUS_INVALID_PARAMETER;
5136 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5137 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5139 /* Ok - do the mknod. */
5140 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5141 return map_nt_error_from_unix(errno);
5144 /* If any of the other "set" calls fail we
5145 * don't want to end up with a half-constructed mknod.
5148 if (lp_inherit_perms(SNUM(conn))) {
5150 conn, parent_dirname(fname),
5154 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5155 status = map_nt_error_from_unix(errno);
5156 SMB_VFS_UNLINK(conn,fname);
5159 return NT_STATUS_OK;
5162 /****************************************************************************
5163 Deal with SMB_SET_FILE_UNIX_BASIC.
5164 ****************************************************************************/
5166 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5167 struct smb_request *req,
5172 SMB_STRUCT_STAT *psbuf)
5174 struct timespec ts[2];
5175 uint32 raw_unixmode;
5178 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5179 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5180 NTSTATUS status = NT_STATUS_OK;
5181 BOOL delete_on_fail = False;
5182 enum perm_type ptype;
5184 if (total_data < 100) {
5185 return NT_STATUS_INVALID_PARAMETER;
5188 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5189 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5190 size=IVAL(pdata,0); /* first 8 Bytes are size */
5191 #ifdef LARGE_SMB_OFF_T
5192 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5193 #else /* LARGE_SMB_OFF_T */
5194 if (IVAL(pdata,4) != 0) {
5195 /* more than 32 bits? */
5196 return NT_STATUS_INVALID_PARAMETER;
5198 #endif /* LARGE_SMB_OFF_T */
5201 ts[0] = interpret_long_date(pdata+24); /* access_time */
5202 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5203 set_owner = (uid_t)IVAL(pdata,40);
5204 set_grp = (gid_t)IVAL(pdata,48);
5205 raw_unixmode = IVAL(pdata,84);
5207 if (VALID_STAT(*psbuf)) {
5208 if (S_ISDIR(psbuf->st_mode)) {
5209 ptype = PERM_EXISTING_DIR;
5211 ptype = PERM_EXISTING_FILE;
5214 ptype = PERM_NEW_FILE;
5217 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5218 if (!NT_STATUS_IS_OK(status)) {
5222 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5223 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5224 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5226 if (!VALID_STAT(*psbuf)) {
5228 * The only valid use of this is to create character and block
5229 * devices, and named pipes. This is deprecated (IMHO) and
5230 * a new info level should be used for mknod. JRA.
5233 status = smb_unix_mknod(conn,
5238 if (!NT_STATUS_IS_OK(status)) {
5242 /* Ensure we don't try and change anything else. */
5243 raw_unixmode = SMB_MODE_NO_CHANGE;
5244 size = get_file_size(*psbuf);
5245 ts[0] = get_atimespec(psbuf);
5246 ts[1] = get_mtimespec(psbuf);
5248 * We continue here as we might want to change the
5251 delete_on_fail = True;
5255 /* Horrible backwards compatibility hack as an old server bug
5256 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5260 size = get_file_size(*psbuf);
5265 * Deal with the UNIX specific mode set.
5268 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5269 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5270 (unsigned int)unixmode, fname ));
5271 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5272 return map_nt_error_from_unix(errno);
5277 * Deal with the UNIX specific uid set.
5280 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5283 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5284 (unsigned int)set_owner, fname ));
5286 if (S_ISLNK(psbuf->st_mode)) {
5287 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5289 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5293 status = map_nt_error_from_unix(errno);
5294 if (delete_on_fail) {
5295 SMB_VFS_UNLINK(conn,fname);
5302 * Deal with the UNIX specific gid set.
5305 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5306 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5307 (unsigned int)set_owner, fname ));
5308 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5309 status = map_nt_error_from_unix(errno);
5310 if (delete_on_fail) {
5311 SMB_VFS_UNLINK(conn,fname);
5317 /* Deal with any size changes. */
5319 status = smb_set_file_size(conn, req,
5324 if (!NT_STATUS_IS_OK(status)) {
5328 /* Deal with any time changes. */
5330 return smb_set_file_time(conn,
5337 /****************************************************************************
5338 Deal with SMB_SET_FILE_UNIX_INFO2.
5339 ****************************************************************************/
5341 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5342 struct smb_request *req,
5347 SMB_STRUCT_STAT *psbuf)
5353 if (total_data < 116) {
5354 return NT_STATUS_INVALID_PARAMETER;
5357 /* Start by setting all the fields that are common between UNIX_BASIC
5360 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5362 if (!NT_STATUS_IS_OK(status)) {
5366 smb_fflags = IVAL(pdata, 108);
5367 smb_fmask = IVAL(pdata, 112);
5369 /* NB: We should only attempt to alter the file flags if the client
5370 * sends a non-zero mask.
5372 if (smb_fmask != 0) {
5373 int stat_fflags = 0;
5375 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5377 /* Client asked to alter a flag we don't understand. */
5378 return NT_STATUS_INVALID_PARAMETER;
5381 if (fsp && fsp->fh->fd != -1) {
5382 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5383 return NT_STATUS_NOT_SUPPORTED;
5385 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5386 return map_nt_error_from_unix(errno);
5391 /* XXX: need to add support for changing the create_time here. You
5392 * can do this for paths on Darwin with setattrlist(2). The right way
5393 * to hook this up is probably by extending the VFS utimes interface.
5396 return NT_STATUS_OK;
5399 /****************************************************************************
5400 Create a directory with POSIX semantics.
5401 ****************************************************************************/
5403 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5404 struct smb_request *req,
5408 SMB_STRUCT_STAT *psbuf,
5409 int *pdata_return_size)
5411 NTSTATUS status = NT_STATUS_OK;
5412 uint32 raw_unixmode = 0;
5413 uint32 mod_unixmode = 0;
5414 mode_t unixmode = (mode_t)0;
5415 files_struct *fsp = NULL;
5416 uint16 info_level_return = 0;
5418 char *pdata = *ppdata;
5420 if (total_data < 18) {
5421 return NT_STATUS_INVALID_PARAMETER;
5424 raw_unixmode = IVAL(pdata,8);
5425 /* Next 4 bytes are not yet defined. */
5427 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5428 if (!NT_STATUS_IS_OK(status)) {
5432 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5434 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5435 fname, (unsigned int)unixmode ));
5437 status = open_directory(conn, req,
5440 FILE_READ_ATTRIBUTES, /* Just a stat open */
5441 FILE_SHARE_NONE, /* Ignored for stat opens */
5448 if (NT_STATUS_IS_OK(status)) {
5449 close_file(fsp, NORMAL_CLOSE);
5452 info_level_return = SVAL(pdata,16);
5454 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5455 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5456 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5457 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5459 *pdata_return_size = 12;
5462 /* Realloc the data size */
5463 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5464 if (*ppdata == NULL) {
5465 *pdata_return_size = 0;
5466 return NT_STATUS_NO_MEMORY;
5470 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5471 SSVAL(pdata,2,0); /* No fnum. */
5472 SIVAL(pdata,4,info); /* Was directory created. */
5474 switch (info_level_return) {
5475 case SMB_QUERY_FILE_UNIX_BASIC:
5476 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5477 SSVAL(pdata,10,0); /* Padding. */
5478 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5480 case SMB_QUERY_FILE_UNIX_INFO2:
5481 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5482 SSVAL(pdata,10,0); /* Padding. */
5483 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5486 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5487 SSVAL(pdata,10,0); /* Padding. */
5494 /****************************************************************************
5495 Open/Create a file with POSIX semantics.
5496 ****************************************************************************/
5498 static NTSTATUS smb_posix_open(connection_struct *conn,
5499 struct smb_request *req,
5503 SMB_STRUCT_STAT *psbuf,
5504 int *pdata_return_size)
5506 BOOL extended_oplock_granted = False;
5507 char *pdata = *ppdata;
5509 uint32 wire_open_mode = 0;
5510 uint32 raw_unixmode = 0;
5511 uint32 mod_unixmode = 0;
5512 uint32 create_disp = 0;
5513 uint32 access_mask = 0;
5514 uint32 create_options = 0;
5515 NTSTATUS status = NT_STATUS_OK;
5516 mode_t unixmode = (mode_t)0;
5517 files_struct *fsp = NULL;
5518 int oplock_request = 0;
5520 uint16 info_level_return = 0;
5522 if (total_data < 18) {
5523 return NT_STATUS_INVALID_PARAMETER;
5526 flags = IVAL(pdata,0);
5527 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5528 if (oplock_request) {
5529 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5532 wire_open_mode = IVAL(pdata,4);
5534 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5535 return smb_posix_mkdir(conn, req,
5543 switch (wire_open_mode & SMB_ACCMODE) {
5545 access_mask = FILE_READ_DATA;
5548 access_mask = FILE_WRITE_DATA;
5551 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5554 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5555 (unsigned int)wire_open_mode ));
5556 return NT_STATUS_INVALID_PARAMETER;
5559 wire_open_mode &= ~SMB_ACCMODE;
5561 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5562 create_disp = FILE_CREATE;
5563 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5564 create_disp = FILE_OVERWRITE_IF;
5565 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5566 create_disp = FILE_OPEN_IF;
5568 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5569 (unsigned int)wire_open_mode ));
5570 return NT_STATUS_INVALID_PARAMETER;
5573 raw_unixmode = IVAL(pdata,8);
5574 /* Next 4 bytes are not yet defined. */
5576 status = unix_perms_from_wire(conn,
5579 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5582 if (!NT_STATUS_IS_OK(status)) {
5586 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5588 if (wire_open_mode & SMB_O_SYNC) {
5589 create_options |= FILE_WRITE_THROUGH;
5591 if (wire_open_mode & SMB_O_APPEND) {
5592 access_mask |= FILE_APPEND_DATA;
5594 if (wire_open_mode & SMB_O_DIRECT) {
5595 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5598 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5600 (unsigned int)wire_open_mode,
5601 (unsigned int)unixmode ));
5603 status = open_file_ntcreate(conn, req,
5607 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5609 0, /* no create options yet. */
5615 if (!NT_STATUS_IS_OK(status)) {
5619 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5620 extended_oplock_granted = True;
5623 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5624 extended_oplock_granted = True;
5627 info_level_return = SVAL(pdata,16);
5629 /* Allocate the correct return size. */
5631 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5632 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5633 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5634 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5636 *pdata_return_size = 12;
5639 /* Realloc the data size */
5640 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5641 if (*ppdata == NULL) {
5642 close_file(fsp,ERROR_CLOSE);
5643 *pdata_return_size = 0;
5644 return NT_STATUS_NO_MEMORY;
5648 if (extended_oplock_granted) {
5649 if (flags & REQUEST_BATCH_OPLOCK) {
5650 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5652 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5654 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5655 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5657 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5660 SSVAL(pdata,2,fsp->fnum);
5661 SIVAL(pdata,4,info); /* Was file created etc. */
5663 switch (info_level_return) {
5664 case SMB_QUERY_FILE_UNIX_BASIC:
5665 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5666 SSVAL(pdata,10,0); /* padding. */
5667 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5669 case SMB_QUERY_FILE_UNIX_INFO2:
5670 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5671 SSVAL(pdata,10,0); /* padding. */
5672 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5675 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5676 SSVAL(pdata,10,0); /* padding. */
5679 return NT_STATUS_OK;
5682 /****************************************************************************
5683 Delete a file with POSIX semantics.
5684 ****************************************************************************/
5686 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5687 struct smb_request *req,
5691 SMB_STRUCT_STAT *psbuf)
5693 NTSTATUS status = NT_STATUS_OK;
5694 files_struct *fsp = NULL;
5698 if (total_data < 2) {
5699 return NT_STATUS_INVALID_PARAMETER;
5702 flags = SVAL(pdata,0);
5704 if (!VALID_STAT(*psbuf)) {
5705 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5708 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5709 !VALID_STAT_OF_DIR(*psbuf)) {
5710 return NT_STATUS_NOT_A_DIRECTORY;
5713 DEBUG(10,("smb_posix_unlink: %s %s\n",
5714 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5717 if (VALID_STAT_OF_DIR(*psbuf)) {
5718 status = open_directory(conn, req,
5722 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5724 FILE_DELETE_ON_CLOSE,
5725 FILE_FLAG_POSIX_SEMANTICS|0777,
5731 status = open_file_ntcreate(conn, req,
5735 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5738 FILE_FLAG_POSIX_SEMANTICS|0777,
5739 0, /* No oplock, but break existing ones. */
5743 * For file opens we must set the delete on close
5747 if (!NT_STATUS_IS_OK(status)) {
5751 status = smb_set_file_disposition_info(conn,
5759 if (!NT_STATUS_IS_OK(status)) {
5762 return close_file(fsp, NORMAL_CLOSE);
5765 /****************************************************************************
5766 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5767 ****************************************************************************/
5769 static int call_trans2setfilepathinfo(connection_struct *conn,
5770 struct smb_request *req,
5771 char *inbuf, char *outbuf, int length,
5773 unsigned int tran_call,
5774 char **pparams, int total_params, char **ppdata, int total_data,
5775 unsigned int max_data_bytes)
5777 char *params = *pparams;
5778 char *pdata = *ppdata;
5780 SMB_STRUCT_STAT sbuf;
5782 files_struct *fsp = NULL;
5783 NTSTATUS status = NT_STATUS_OK;
5784 int data_return_size = 0;
5787 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5792 if (tran_call == TRANSACT2_SETFILEINFO) {
5793 if (total_params < 4) {
5794 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5797 fsp = file_fsp(params,0);
5798 info_level = SVAL(params,2);
5800 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5802 * This is actually a SETFILEINFO on a directory
5803 * handle (returned from an NT SMB). NT5.0 seems
5804 * to do this call. JRA.
5806 pstrcpy(fname, fsp->fsp_name);
5807 if (INFO_LEVEL_IS_UNIX(info_level)) {
5808 /* Always do lstat for UNIX calls. */
5809 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5810 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5811 return UNIXERROR(ERRDOS,ERRbadpath);
5814 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5815 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5816 return UNIXERROR(ERRDOS,ERRbadpath);
5819 } else if (fsp && fsp->print_file) {
5821 * Doing a DELETE_ON_CLOSE should cancel a print job.
5823 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5824 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5826 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5829 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5832 return (UNIXERROR(ERRDOS,ERRbadpath));
5835 * Original code - this is an open file.
5837 CHECK_FSP(fsp,conn);
5839 pstrcpy(fname, fsp->fsp_name);
5841 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5842 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5843 return(UNIXERROR(ERRDOS,ERRbadfid));
5848 if (total_params < 7) {
5849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5852 info_level = SVAL(params,0);
5853 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5854 if (!NT_STATUS_IS_OK(status)) {
5855 return ERROR_NT(status);
5858 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5859 if (!NT_STATUS_IS_OK(status)) {
5860 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5861 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5863 return ERROR_NT(status);
5866 status = unix_convert(conn, fname, False, NULL, &sbuf);
5867 if (!NT_STATUS_IS_OK(status)) {
5868 return ERROR_NT(status);
5871 status = check_name(conn, fname);
5872 if (!NT_STATUS_IS_OK(status)) {
5873 return ERROR_NT(status);
5876 if (INFO_LEVEL_IS_UNIX(info_level)) {
5878 * For CIFS UNIX extensions the target name may not exist.
5881 /* Always do lstat for UNIX calls. */
5882 SMB_VFS_LSTAT(conn,fname,&sbuf);
5884 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5885 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5886 return UNIXERROR(ERRDOS,ERRbadpath);
5890 if (!CAN_WRITE(conn)) {
5891 return ERROR_DOS(ERRSRV,ERRaccess);
5894 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5895 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5898 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5899 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5901 /* Realloc the parameter size */
5902 *pparams = (char *)SMB_REALLOC(*pparams,2);
5903 if (*pparams == NULL) {
5904 return ERROR_NT(NT_STATUS_NO_MEMORY);
5910 if (fsp && !null_timespec(fsp->pending_modtime)) {
5911 /* the pending modtime overrides the current modtime */
5912 set_mtimespec(&sbuf, fsp->pending_modtime);
5915 switch (info_level) {
5917 case SMB_INFO_STANDARD:
5919 status = smb_set_info_standard(conn,
5928 case SMB_INFO_SET_EA:
5930 status = smb_info_set_ea(conn,
5938 case SMB_SET_FILE_BASIC_INFO:
5939 case SMB_FILE_BASIC_INFORMATION:
5941 status = smb_set_file_basic_info(conn,
5950 case SMB_FILE_ALLOCATION_INFORMATION:
5951 case SMB_SET_FILE_ALLOCATION_INFO:
5953 status = smb_set_file_allocation_info(conn, req,
5962 case SMB_FILE_END_OF_FILE_INFORMATION:
5963 case SMB_SET_FILE_END_OF_FILE_INFO:
5965 status = smb_set_file_end_of_file_info(conn, req,
5974 case SMB_FILE_DISPOSITION_INFORMATION:
5975 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5978 /* JRA - We used to just ignore this on a path ?
5979 * Shouldn't this be invalid level on a pathname
5982 if (tran_call != TRANSACT2_SETFILEINFO) {
5983 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5986 status = smb_set_file_disposition_info(conn,
5995 case SMB_FILE_POSITION_INFORMATION:
5997 status = smb_file_position_information(conn,
6004 /* From tridge Samba4 :
6005 * MODE_INFORMATION in setfileinfo (I have no
6006 * idea what "mode information" on a file is - it takes a value of 0,
6007 * 2, 4 or 6. What could it be?).
6010 case SMB_FILE_MODE_INFORMATION:
6012 status = smb_file_mode_information(conn,
6019 * CIFS UNIX extensions.
6022 case SMB_SET_FILE_UNIX_BASIC:
6024 status = smb_set_file_unix_basic(conn, req,
6033 case SMB_SET_FILE_UNIX_INFO2:
6035 status = smb_set_file_unix_info2(conn, req,
6044 case SMB_SET_FILE_UNIX_LINK:
6046 if (tran_call != TRANSACT2_SETPATHINFO) {
6047 /* We must have a pathname for this. */
6048 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6050 status = smb_set_file_unix_link(conn,
6058 case SMB_SET_FILE_UNIX_HLINK:
6060 if (tran_call != TRANSACT2_SETPATHINFO) {
6061 /* We must have a pathname for this. */
6062 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6064 status = smb_set_file_unix_hlink(conn,
6073 case SMB_FILE_RENAME_INFORMATION:
6075 status = smb_file_rename_information(conn, req,
6085 #if defined(HAVE_POSIX_ACLS)
6086 case SMB_SET_POSIX_ACL:
6088 status = smb_set_posix_acl(conn,
6098 case SMB_SET_POSIX_LOCK:
6100 if (tran_call != TRANSACT2_SETFILEINFO) {
6101 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6103 status = smb_set_posix_lock(conn,
6112 case SMB_POSIX_PATH_OPEN:
6114 if (tran_call != TRANSACT2_SETPATHINFO) {
6115 /* We must have a pathname for this. */
6116 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6119 status = smb_posix_open(conn, req,
6128 case SMB_POSIX_PATH_UNLINK:
6130 if (tran_call != TRANSACT2_SETPATHINFO) {
6131 /* We must have a pathname for this. */
6132 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6135 status = smb_posix_unlink(conn, req,
6144 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6148 if (!NT_STATUS_IS_OK(status)) {
6149 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6150 /* We have re-scheduled this call. */
6153 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6154 /* We have re-scheduled this call. */
6157 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6158 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6160 return ERROR_NT(status);
6164 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6169 /****************************************************************************
6170 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6171 ****************************************************************************/
6173 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6174 char **pparams, int total_params, char **ppdata, int total_data,
6175 unsigned int max_data_bytes)
6177 char *params = *pparams;
6178 char *pdata = *ppdata;
6180 SMB_STRUCT_STAT sbuf;
6181 NTSTATUS status = NT_STATUS_OK;
6182 struct ea_list *ea_list = NULL;
6184 if (!CAN_WRITE(conn))
6185 return ERROR_DOS(ERRSRV,ERRaccess);
6187 if (total_params < 5) {
6188 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6191 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6192 if (!NT_STATUS_IS_OK(status)) {
6193 return ERROR_NT(status);
6196 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6198 status = unix_convert(conn, directory, False, NULL, &sbuf);
6199 if (!NT_STATUS_IS_OK(status)) {
6200 return ERROR_NT(status);
6203 status = check_name(conn, directory);
6204 if (!NT_STATUS_IS_OK(status)) {
6205 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6206 return ERROR_NT(status);
6209 /* Any data in this call is an EA list. */
6210 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6211 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6215 * OS/2 workplace shell seems to send SET_EA requests of "null"
6216 * length (4 bytes containing IVAL 4).
6217 * They seem to have no effect. Bug #3212. JRA.
6220 if (total_data != 4) {
6221 if (total_data < 10) {
6222 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6225 if (IVAL(pdata,0) > total_data) {
6226 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6227 IVAL(pdata,0), (unsigned int)total_data));
6228 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6231 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6234 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6236 } else if (IVAL(pdata,0) != 4) {
6237 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6240 status = create_directory(conn, directory);
6242 if (!NT_STATUS_IS_OK(status)) {
6243 return ERROR_NT(status);
6246 /* Try and set any given EA. */
6248 status = set_ea(conn, NULL, directory, ea_list);
6249 if (!NT_STATUS_IS_OK(status)) {
6250 return ERROR_NT(status);
6254 /* Realloc the parameter and data sizes */
6255 *pparams = (char *)SMB_REALLOC(*pparams,2);
6256 if(*pparams == NULL) {
6257 return ERROR_NT(NT_STATUS_NO_MEMORY);
6263 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6268 /****************************************************************************
6269 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6270 We don't actually do this - we just send a null response.
6271 ****************************************************************************/
6273 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6274 char **pparams, int total_params, char **ppdata, int total_data,
6275 unsigned int max_data_bytes)
6277 static uint16 fnf_handle = 257;
6278 char *params = *pparams;
6281 if (total_params < 6) {
6282 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6285 info_level = SVAL(params,4);
6286 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6288 switch (info_level) {
6293 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6296 /* Realloc the parameter and data sizes */
6297 *pparams = (char *)SMB_REALLOC(*pparams,6);
6298 if (*pparams == NULL) {
6299 return ERROR_NT(NT_STATUS_NO_MEMORY);
6303 SSVAL(params,0,fnf_handle);
6304 SSVAL(params,2,0); /* No changes */
6305 SSVAL(params,4,0); /* No EA errors */
6312 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6317 /****************************************************************************
6318 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6319 changes). Currently this does nothing.
6320 ****************************************************************************/
6322 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6323 char **pparams, int total_params, char **ppdata, int total_data,
6324 unsigned int max_data_bytes)
6326 char *params = *pparams;
6328 DEBUG(3,("call_trans2findnotifynext\n"));
6330 /* Realloc the parameter and data sizes */
6331 *pparams = (char *)SMB_REALLOC(*pparams,4);
6332 if (*pparams == NULL) {
6333 return ERROR_NT(NT_STATUS_NO_MEMORY);
6337 SSVAL(params,0,0); /* No changes */
6338 SSVAL(params,2,0); /* No EA errors */
6340 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6345 /****************************************************************************
6346 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6347 ****************************************************************************/
6349 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6350 char **pparams, int total_params, char **ppdata, int total_data,
6351 unsigned int max_data_bytes)
6353 char *params = *pparams;
6356 int max_referral_level;
6357 NTSTATUS status = NT_STATUS_OK;
6359 DEBUG(10,("call_trans2getdfsreferral\n"));
6361 if (total_params < 3) {
6362 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6365 max_referral_level = SVAL(params,0);
6367 if(!lp_host_msdfs())
6368 return ERROR_DOS(ERRDOS,ERRbadfunc);
6370 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2],
6371 sizeof(pathname), total_params - 2, STR_TERMINATE);
6372 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6373 return ERROR_NT(status);
6375 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6376 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6381 #define LMCAT_SPL 0x53
6382 #define LMFUNC_GETJOBID 0x60
6384 /****************************************************************************
6385 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6386 ****************************************************************************/
6388 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6389 char **pparams, int total_params, char **ppdata, int total_data,
6390 unsigned int max_data_bytes)
6392 char *pdata = *ppdata;
6393 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6395 /* check for an invalid fid before proceeding */
6398 return(ERROR_DOS(ERRDOS,ERRbadfid));
6400 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6401 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6402 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6403 if (*ppdata == NULL) {
6404 return ERROR_NT(NT_STATUS_NO_MEMORY);
6408 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6409 CAN ACCEPT THIS IN UNICODE. JRA. */
6411 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6412 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6413 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6414 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6417 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6418 return ERROR_DOS(ERRSRV,ERRerror);
6422 /****************************************************************************
6423 Reply to a SMBfindclose (stop trans2 directory search).
6424 ****************************************************************************/
6426 int reply_findclose(connection_struct *conn,
6427 char *inbuf,char *outbuf,int length,int bufsize)
6430 int dptr_num=SVALS(inbuf,smb_vwv0);
6431 START_PROFILE(SMBfindclose);
6433 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6435 dptr_close(&dptr_num);
6437 outsize = set_message(inbuf, outbuf,0,0,False);
6439 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6441 END_PROFILE(SMBfindclose);
6445 /****************************************************************************
6446 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6447 ****************************************************************************/
6449 int reply_findnclose(connection_struct *conn,
6450 char *inbuf,char *outbuf,int length,int bufsize)
6454 START_PROFILE(SMBfindnclose);
6456 dptr_num = SVAL(inbuf,smb_vwv0);
6458 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6460 /* We never give out valid handles for a
6461 findnotifyfirst - so any dptr_num is ok here.
6464 outsize = set_message(inbuf, outbuf,0,0,False);
6466 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6468 END_PROFILE(SMBfindnclose);
6472 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6473 struct trans_state *state,
6474 char *inbuf, char *outbuf, int size, int bufsize)
6478 if (Protocol >= PROTOCOL_NT1) {
6479 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6482 /* Now we must call the relevant TRANS2 function */
6483 switch(state->call) {
6484 case TRANSACT2_OPEN:
6486 START_PROFILE(Trans2_open);
6487 outsize = call_trans2open(
6488 conn, req, inbuf, outbuf, bufsize,
6489 &state->param, state->total_param,
6490 &state->data, state->total_data,
6491 state->max_data_return);
6492 END_PROFILE(Trans2_open);
6496 case TRANSACT2_FINDFIRST:
6498 START_PROFILE(Trans2_findfirst);
6499 outsize = call_trans2findfirst(
6500 conn, inbuf, outbuf, bufsize,
6501 &state->param, state->total_param,
6502 &state->data, state->total_data,
6503 state->max_data_return);
6504 END_PROFILE(Trans2_findfirst);
6508 case TRANSACT2_FINDNEXT:
6510 START_PROFILE(Trans2_findnext);
6511 outsize = call_trans2findnext(
6512 conn, inbuf, outbuf, size, bufsize,
6513 &state->param, state->total_param,
6514 &state->data, state->total_data,
6515 state->max_data_return);
6516 END_PROFILE(Trans2_findnext);
6520 case TRANSACT2_QFSINFO:
6522 START_PROFILE(Trans2_qfsinfo);
6523 outsize = call_trans2qfsinfo(
6524 conn, inbuf, outbuf, size, bufsize,
6525 &state->param, state->total_param,
6526 &state->data, state->total_data,
6527 state->max_data_return);
6528 END_PROFILE(Trans2_qfsinfo);
6532 case TRANSACT2_SETFSINFO:
6534 START_PROFILE(Trans2_setfsinfo);
6535 outsize = call_trans2setfsinfo(
6536 conn, inbuf, outbuf, size, bufsize,
6537 &state->param, state->total_param,
6538 &state->data, state->total_data,
6539 state->max_data_return);
6540 END_PROFILE(Trans2_setfsinfo);
6544 case TRANSACT2_QPATHINFO:
6545 case TRANSACT2_QFILEINFO:
6547 START_PROFILE(Trans2_qpathinfo);
6548 outsize = call_trans2qfilepathinfo(
6549 conn, inbuf, outbuf, size, bufsize, state->call,
6550 &state->param, state->total_param,
6551 &state->data, state->total_data,
6552 state->max_data_return);
6553 END_PROFILE(Trans2_qpathinfo);
6557 case TRANSACT2_SETPATHINFO:
6558 case TRANSACT2_SETFILEINFO:
6560 START_PROFILE(Trans2_setpathinfo);
6561 outsize = call_trans2setfilepathinfo(
6562 conn, req, inbuf, outbuf, size, bufsize, state->call,
6563 &state->param, state->total_param,
6564 &state->data, state->total_data,
6565 state->max_data_return);
6566 END_PROFILE(Trans2_setpathinfo);
6570 case TRANSACT2_FINDNOTIFYFIRST:
6572 START_PROFILE(Trans2_findnotifyfirst);
6573 outsize = call_trans2findnotifyfirst(
6574 conn, inbuf, outbuf, size, bufsize,
6575 &state->param, state->total_param,
6576 &state->data, state->total_data,
6577 state->max_data_return);
6578 END_PROFILE(Trans2_findnotifyfirst);
6582 case TRANSACT2_FINDNOTIFYNEXT:
6584 START_PROFILE(Trans2_findnotifynext);
6585 outsize = call_trans2findnotifynext(
6586 conn, inbuf, outbuf, size, bufsize,
6587 &state->param, state->total_param,
6588 &state->data, state->total_data,
6589 state->max_data_return);
6590 END_PROFILE(Trans2_findnotifynext);
6594 case TRANSACT2_MKDIR:
6596 START_PROFILE(Trans2_mkdir);
6597 outsize = call_trans2mkdir(
6598 conn, inbuf, outbuf, size, bufsize,
6599 &state->param, state->total_param,
6600 &state->data, state->total_data,
6601 state->max_data_return);
6602 END_PROFILE(Trans2_mkdir);
6606 case TRANSACT2_GET_DFS_REFERRAL:
6608 START_PROFILE(Trans2_get_dfs_referral);
6609 outsize = call_trans2getdfsreferral(
6610 conn, inbuf, outbuf, size, bufsize,
6611 &state->param, state->total_param,
6612 &state->data, state->total_data,
6613 state->max_data_return);
6614 END_PROFILE(Trans2_get_dfs_referral);
6618 case TRANSACT2_IOCTL:
6620 START_PROFILE(Trans2_ioctl);
6621 outsize = call_trans2ioctl(
6622 conn, inbuf, outbuf, size, bufsize,
6623 &state->param, state->total_param,
6624 &state->data, state->total_data,
6625 state->max_data_return);
6626 END_PROFILE(Trans2_ioctl);
6631 /* Error in request */
6632 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6633 outsize = ERROR_DOS(ERRSRV,ERRerror);
6639 /****************************************************************************
6640 Reply to a SMBtrans2.
6641 ****************************************************************************/
6643 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6644 int size, int bufsize)
6647 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6648 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6649 unsigned int psoff = SVAL(inbuf, smb_psoff);
6650 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6651 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6652 struct trans_state *state;
6655 START_PROFILE(SMBtrans2);
6657 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6658 if (!NT_STATUS_IS_OK(result)) {
6659 DEBUG(2, ("Got invalid trans2 request: %s\n",
6660 nt_errstr(result)));
6661 END_PROFILE(SMBtrans2);
6662 return ERROR_NT(result);
6665 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6666 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6667 && (tran_call != TRANSACT2_QFILEINFO)) {
6668 END_PROFILE(SMBtrans2);
6669 return ERROR_DOS(ERRSRV,ERRaccess);
6672 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6673 DEBUG(0, ("talloc failed\n"));
6674 END_PROFILE(SMBtrans2);
6675 return ERROR_NT(NT_STATUS_NO_MEMORY);
6678 state->cmd = SMBtrans2;
6680 state->mid = SVAL(inbuf, smb_mid);
6681 state->vuid = SVAL(inbuf, smb_uid);
6682 state->setup_count = SVAL(inbuf, smb_suwcnt);
6683 state->setup = NULL;
6684 state->total_param = SVAL(inbuf, smb_tpscnt);
6685 state->param = NULL;
6686 state->total_data = SVAL(inbuf, smb_tdscnt);
6688 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6689 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6690 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6691 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6692 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6694 state->call = tran_call;
6696 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6697 is so as a sanity check */
6698 if (state->setup_count != 1) {
6700 * Need to have rc=0 for ioctl to get job id for OS/2.
6701 * Network printing will fail if function is not successful.
6702 * Similar function in reply.c will be used if protocol
6703 * is LANMAN1.0 instead of LM1.2X002.
6704 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6705 * outbuf doesn't have to be set(only job id is used).
6707 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6708 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6709 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6710 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6712 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6713 DEBUG(2,("Transaction is %d\n",tran_call));
6715 END_PROFILE(SMBtrans2);
6716 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6720 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6723 if (state->total_data) {
6724 /* Can't use talloc here, the core routines do realloc on the
6725 * params and data. */
6726 state->data = (char *)SMB_MALLOC(state->total_data);
6727 if (state->data == NULL) {
6728 DEBUG(0,("reply_trans2: data malloc fail for %u "
6729 "bytes !\n", (unsigned int)state->total_data));
6731 END_PROFILE(SMBtrans2);
6732 return(ERROR_DOS(ERRDOS,ERRnomem));
6734 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6736 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6737 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6740 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6743 if (state->total_param) {
6744 /* Can't use talloc here, the core routines do realloc on the
6745 * params and data. */
6746 state->param = (char *)SMB_MALLOC(state->total_param);
6747 if (state->param == NULL) {
6748 DEBUG(0,("reply_trans: param malloc fail for %u "
6749 "bytes !\n", (unsigned int)state->total_param));
6750 SAFE_FREE(state->data);
6752 END_PROFILE(SMBtrans2);
6753 return(ERROR_DOS(ERRDOS,ERRnomem));
6755 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6757 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6758 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6761 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6764 state->received_data = dscnt;
6765 state->received_param = pscnt;
6767 if ((state->received_param == state->total_param) &&
6768 (state->received_data == state->total_data)) {
6770 struct smb_request req;
6771 init_smb_request(&req, (uint8 *)inbuf);
6773 outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
6775 SAFE_FREE(state->data);
6776 SAFE_FREE(state->param);
6778 END_PROFILE(SMBtrans2);
6782 DLIST_ADD(conn->pending_trans, state);
6784 /* We need to send an interim response then receive the rest
6785 of the parameter/data bytes */
6786 outsize = set_message(inbuf, outbuf,0,0,False);
6788 END_PROFILE(SMBtrans2);
6793 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6794 SAFE_FREE(state->data);
6795 SAFE_FREE(state->param);
6797 END_PROFILE(SMBtrans2);
6798 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6802 /****************************************************************************
6803 Reply to a SMBtranss2
6804 ****************************************************************************/
6806 int reply_transs2(connection_struct *conn,
6807 char *inbuf,char *outbuf,int size,int bufsize)
6810 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6811 struct trans_state *state;
6812 struct smb_request req;
6814 START_PROFILE(SMBtranss2);
6818 for (state = conn->pending_trans; state != NULL;
6819 state = state->next) {
6820 if (state->mid == SVAL(inbuf,smb_mid)) {
6825 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6826 END_PROFILE(SMBtranss2);
6827 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6830 /* Revise state->total_param and state->total_data in case they have
6831 changed downwards */
6833 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6834 state->total_param = SVAL(inbuf, smb_tpscnt);
6835 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6836 state->total_data = SVAL(inbuf, smb_tdscnt);
6838 pcnt = SVAL(inbuf, smb_spscnt);
6839 poff = SVAL(inbuf, smb_spsoff);
6840 pdisp = SVAL(inbuf, smb_spsdisp);
6842 dcnt = SVAL(inbuf, smb_sdscnt);
6843 doff = SVAL(inbuf, smb_sdsoff);
6844 ddisp = SVAL(inbuf, smb_sdsdisp);
6846 state->received_param += pcnt;
6847 state->received_data += dcnt;
6849 if ((state->received_data > state->total_data) ||
6850 (state->received_param > state->total_param))
6854 if (pdisp+pcnt > state->total_param)
6856 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6858 if (pdisp > state->total_param)
6860 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6861 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6863 if (state->param + pdisp < state->param)
6866 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6871 if (ddisp+dcnt > state->total_data)
6873 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6875 if (ddisp > state->total_data)
6877 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6878 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6880 if (state->data + ddisp < state->data)
6883 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6887 if ((state->received_param < state->total_param) ||
6888 (state->received_data < state->total_data)) {
6889 END_PROFILE(SMBtranss2);
6893 /* construct_reply_common has done us the favor to pre-fill the
6894 * command field with SMBtranss2 which is wrong :-)
6896 SCVAL(outbuf,smb_com,SMBtrans2);
6898 init_smb_request(&req, (uint8 *)inbuf);
6900 outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
6903 DLIST_REMOVE(conn->pending_trans, state);
6904 SAFE_FREE(state->data);
6905 SAFE_FREE(state->param);
6909 END_PROFILE(SMBtranss2);
6910 return(ERROR_DOS(ERRSRV,ERRnosupport));
6913 END_PROFILE(SMBtranss2);
6918 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6919 DLIST_REMOVE(conn->pending_trans, state);
6920 SAFE_FREE(state->data);
6921 SAFE_FREE(state->param);
6923 END_PROFILE(SMBtranss2);
6924 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);