2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
9 Extensively modified by Andrew Tridgell, 1995
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 /********************************************************************
38 Roundup a value to the nearest allocation roundup size boundary.
39 Only do this for Windows clients.
40 ********************************************************************/
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
44 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
46 /* Only roundup for Windows clients. */
47 enum remote_arch_types ra_type = get_remote_arch();
48 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49 val = SMB_ROUNDUP(val,rval);
54 /********************************************************************
55 Given a stat buffer return the allocated size on disk, taking into
57 ********************************************************************/
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
63 if(S_ISDIR(sbuf->st_mode)) {
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
70 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
73 if (fsp && fsp->initial_allocation_size)
74 ret = MAX(ret,fsp->initial_allocation_size);
76 return smb_roundup(conn, ret);
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 static const char *prohibited_ea_names[] = {
84 SAMBA_POSIX_INHERITANCE_EA_NAME,
85 SAMBA_XATTR_DOS_ATTRIB,
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
123 if (fsp && fsp->fh->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
138 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139 dump_data(10, val, sizeret);
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
147 pea->value.data = (unsigned char *)val;
148 pea->value.length = (size_t)sizeret;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157 const char *fname, size_t *pea_total_len)
159 /* Get a list of all xattrs. Max namesize is 64k. */
160 size_t ea_namelist_size = 1024;
165 struct ea_list *ea_list_head = NULL;
169 if (!lp_ea_support(SNUM(conn))) {
173 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
174 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
180 if (fsp && fsp->fh->fd != -1) {
181 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
183 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
186 if (sizeret == -1 && errno == ERANGE) {
187 ea_namelist_size *= 2;
196 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
199 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
200 struct ea_list *listp;
202 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
205 listp = TALLOC_P(mem_ctx, struct ea_list);
209 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
215 push_ascii_fstring(dos_ea_name, listp->ea.name);
216 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
217 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
218 (unsigned int)*pea_total_len, dos_ea_name,
219 (unsigned int)listp->ea.value.length ));
221 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
223 /* Add on 4 for total length. */
224 if (*pea_total_len) {
229 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
233 /****************************************************************************
234 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
236 ****************************************************************************/
238 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
239 connection_struct *conn, struct ea_list *ea_list)
241 unsigned int ret_data_size = 4;
244 SMB_ASSERT(total_data_size >= 4);
246 if (!lp_ea_support(SNUM(conn))) {
251 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
254 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
255 dos_namelen = strlen(dos_ea_name);
256 if (dos_namelen > 255 || dos_namelen == 0) {
259 if (ea_list->ea.value.length > 65535) {
262 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
266 /* We know we have room. */
267 SCVAL(p,0,ea_list->ea.flags);
268 SCVAL(p,1,dos_namelen);
269 SSVAL(p,2,ea_list->ea.value.length);
270 fstrcpy(p+4, dos_ea_name);
271 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
273 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
274 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
277 ret_data_size = PTR_DIFF(p, pdata);
278 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
279 SIVAL(pdata,0,ret_data_size);
280 return ret_data_size;
283 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
285 size_t total_ea_len = 0;
286 TALLOC_CTX *mem_ctx = NULL;
288 if (!lp_ea_support(SNUM(conn))) {
291 mem_ctx = talloc_init("estimate_ea_size");
292 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
293 talloc_destroy(mem_ctx);
297 /****************************************************************************
298 Ensure the EA name is case insensitive by matching any existing EA name.
299 ****************************************************************************/
301 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
304 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
305 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
307 for (; ea_list; ea_list = ea_list->next) {
308 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
309 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
310 &unix_ea_name[5], ea_list->ea.name));
311 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
315 talloc_destroy(mem_ctx);
318 /****************************************************************************
319 Set or delete an extended attribute.
320 ****************************************************************************/
322 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
324 if (!lp_ea_support(SNUM(conn))) {
325 return NT_STATUS_EAS_NOT_SUPPORTED;
328 for (;ea_list; ea_list = ea_list->next) {
330 fstring unix_ea_name;
332 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
333 fstrcat(unix_ea_name, ea_list->ea.name);
335 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
337 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
339 if (samba_private_attr_name(unix_ea_name)) {
340 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
341 return NT_STATUS_ACCESS_DENIED;
344 if (ea_list->ea.value.length == 0) {
345 /* Remove the attribute. */
346 if (fsp && (fsp->fh->fd != -1)) {
347 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
348 unix_ea_name, fsp->fsp_name));
349 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
351 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
352 unix_ea_name, fname));
353 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
356 /* Removing a non existent attribute always succeeds. */
357 if (ret == -1 && errno == ENOATTR) {
358 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
364 if (fsp && (fsp->fh->fd != -1)) {
365 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
366 unix_ea_name, fsp->fsp_name));
367 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
368 ea_list->ea.value.data, ea_list->ea.value.length, 0);
370 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
371 unix_ea_name, fname));
372 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
373 ea_list->ea.value.data, ea_list->ea.value.length, 0);
379 if (errno == ENOTSUP) {
380 return NT_STATUS_EAS_NOT_SUPPORTED;
383 return map_nt_error_from_unix(errno);
389 /****************************************************************************
390 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
391 ****************************************************************************/
393 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
395 struct ea_list *ea_list_head = NULL;
398 while (offset + 2 < data_size) {
399 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
400 unsigned int namelen = CVAL(pdata,offset);
402 offset++; /* Go past the namelen byte. */
404 /* integer wrap paranioa. */
405 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
406 (offset > data_size) || (namelen > data_size) ||
407 (offset + namelen >= data_size)) {
410 /* Ensure the name is null terminated. */
411 if (pdata[offset + namelen] != '\0') {
414 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
419 offset += (namelen + 1); /* Go past the name + terminating zero. */
420 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
421 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
427 /****************************************************************************
428 Read one EA list entry from the buffer.
429 ****************************************************************************/
431 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
433 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
435 unsigned int namelen;
445 eal->ea.flags = CVAL(pdata,0);
446 namelen = CVAL(pdata,1);
447 val_len = SVAL(pdata,2);
449 if (4 + namelen + 1 + val_len > data_size) {
453 /* Ensure the name is null terminated. */
454 if (pdata[namelen + 4] != '\0') {
457 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
462 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
463 if (!eal->ea.value.data) {
467 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
469 /* Ensure we're null terminated just in case we print the value. */
470 eal->ea.value.data[val_len] = '\0';
471 /* But don't count the null. */
472 eal->ea.value.length--;
475 *pbytes_used = 4 + namelen + 1 + val_len;
478 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
479 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
484 /****************************************************************************
485 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
486 ****************************************************************************/
488 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
490 struct ea_list *ea_list_head = NULL;
492 size_t bytes_used = 0;
494 while (offset < data_size) {
495 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
501 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
502 offset += bytes_used;
508 /****************************************************************************
509 Count the total EA size needed.
510 ****************************************************************************/
512 static size_t ea_list_size(struct ea_list *ealist)
515 struct ea_list *listp;
518 for (listp = ealist; listp; listp = listp->next) {
519 push_ascii_fstring(dos_ea_name, listp->ea.name);
520 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
522 /* Add on 4 for total length. */
530 /****************************************************************************
531 Return a union of EA's from a file list and a list of names.
532 The TALLOC context for the two lists *MUST* be identical as we steal
533 memory from one list to add to another. JRA.
534 ****************************************************************************/
536 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
538 struct ea_list *nlistp, *flistp;
540 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
541 for (flistp = file_list; flistp; flistp = flistp->next) {
542 if (strequal(nlistp->ea.name, flistp->ea.name)) {
548 /* Copy the data from this entry. */
549 nlistp->ea.flags = flistp->ea.flags;
550 nlistp->ea.value = flistp->ea.value;
553 nlistp->ea.flags = 0;
554 ZERO_STRUCT(nlistp->ea.value);
558 *total_ea_len = ea_list_size(name_list);
562 /****************************************************************************
563 Send the required number of replies back.
564 We assume all fields other than the data fields are
565 set correctly for the type of call.
566 HACK ! Always assumes smb_setup field is zero.
567 ****************************************************************************/
569 int send_trans2_replies(char *outbuf,
577 /* As we are using a protocol > LANMAN1 then the max_send
578 variable must have been set in the sessetupX call.
579 This takes precedence over the max_xmit field in the
580 global struct. These different max_xmit variables should
581 be merged as this is now too confusing */
583 int data_to_send = datasize;
584 int params_to_send = paramsize;
588 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
589 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
590 int data_alignment_offset = 0;
592 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
594 set_message(outbuf,10,0,True);
596 /* Modify the data_to_send and datasize and set the error if
597 we're trying to send more than max_data_bytes. We still send
598 the part of the packet(s) that fit. Strange, but needed
601 if (max_data_bytes > 0 && datasize > max_data_bytes) {
602 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
603 max_data_bytes, datasize ));
604 datasize = data_to_send = max_data_bytes;
605 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
608 /* If there genuinely are no parameters or data to send just send the empty packet */
610 if(params_to_send == 0 && data_to_send == 0) {
612 if (!send_smb(smbd_server_fd(),outbuf))
613 exit_server_cleanly("send_trans2_replies: send_smb failed.");
617 /* When sending params and data ensure that both are nicely aligned */
618 /* Only do this alignment when there is also data to send - else
619 can cause NT redirector problems. */
621 if (((params_to_send % 4) != 0) && (data_to_send != 0))
622 data_alignment_offset = 4 - (params_to_send % 4);
624 /* Space is bufsize minus Netbios over TCP header minus SMB header */
625 /* The alignment_offset is to align the param bytes on an even byte
626 boundary. NT 4.0 Beta needs this to work correctly. */
628 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
630 /* useable_space can never be more than max_send minus the alignment offset. */
632 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
634 while (params_to_send || data_to_send) {
635 /* Calculate whether we will totally or partially fill this packet */
637 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
639 /* We can never send more than useable_space */
641 * Note that 'useable_space' does not include the alignment offsets,
642 * but we must include the alignment offsets in the calculation of
643 * the length of the data we send over the wire, as the alignment offsets
644 * are sent here. Fix from Marc_Jacobsen@hp.com.
647 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
649 set_message(outbuf, 10, total_sent_thistime, True);
651 /* Set total params and data to be sent */
652 SSVAL(outbuf,smb_tprcnt,paramsize);
653 SSVAL(outbuf,smb_tdrcnt,datasize);
655 /* Calculate how many parameters and data we can fit into
656 * this packet. Parameters get precedence
659 params_sent_thistime = MIN(params_to_send,useable_space);
660 data_sent_thistime = useable_space - params_sent_thistime;
661 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
663 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
665 /* smb_proff is the offset from the start of the SMB header to the
666 parameter bytes, however the first 4 bytes of outbuf are
667 the Netbios over TCP header. Thus use smb_base() to subtract
668 them from the calculation */
670 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
672 if(params_sent_thistime == 0)
673 SSVAL(outbuf,smb_prdisp,0);
675 /* Absolute displacement of param bytes sent in this packet */
676 SSVAL(outbuf,smb_prdisp,pp - params);
678 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
679 if(data_sent_thistime == 0) {
680 SSVAL(outbuf,smb_droff,0);
681 SSVAL(outbuf,smb_drdisp, 0);
683 /* The offset of the data bytes is the offset of the
684 parameter bytes plus the number of parameters being sent this time */
685 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
686 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
687 SSVAL(outbuf,smb_drdisp, pd - pdata);
690 /* Copy the param bytes into the packet */
692 if(params_sent_thistime)
693 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
695 /* Copy in the data bytes */
696 if(data_sent_thistime)
697 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
698 data_alignment_offset,pd,data_sent_thistime);
700 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
701 params_sent_thistime, data_sent_thistime, useable_space));
702 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
703 params_to_send, data_to_send, paramsize, datasize));
705 /* Send the packet */
707 if (!send_smb(smbd_server_fd(),outbuf))
708 exit_server_cleanly("send_trans2_replies: send_smb failed.");
710 pp += params_sent_thistime;
711 pd += data_sent_thistime;
713 params_to_send -= params_sent_thistime;
714 data_to_send -= data_sent_thistime;
717 if(params_to_send < 0 || data_to_send < 0) {
718 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
719 params_to_send, data_to_send));
727 /****************************************************************************
728 Reply to a TRANSACT2_OPEN.
729 ****************************************************************************/
731 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
732 char **pparams, int total_params, char **ppdata, int total_data,
733 unsigned int max_data_bytes)
735 char *params = *pparams;
736 char *pdata = *ppdata;
741 BOOL return_additional_info;
752 SMB_STRUCT_STAT sbuf;
754 BOOL bad_path = False;
756 struct ea_list *ea_list = NULL;
761 uint32 create_disposition;
762 uint32 create_options = 0;
765 * Ensure we have enough parameters to perform the operation.
768 if (total_params < 29) {
769 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
772 flags = SVAL(params, 0);
773 deny_mode = SVAL(params, 2);
774 open_attr = SVAL(params,6);
775 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
776 if (oplock_request) {
777 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
781 return_additional_info = BITSETW(params,0);
782 open_sattr = SVAL(params, 4);
783 open_time = make_unix_date3(params+8);
785 open_ofun = SVAL(params,12);
786 open_size = IVAL(params,14);
790 return(ERROR_DOS(ERRSRV,ERRaccess));
793 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
794 if (!NT_STATUS_IS_OK(status)) {
795 return ERROR_NT(status);
798 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
799 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
800 (unsigned int)open_ofun, open_size));
802 /* XXXX we need to handle passed times, sattr and flags */
804 unix_convert(fname,conn,0,&bad_path,&sbuf);
806 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
809 if (!check_name(fname,conn)) {
810 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
813 if (open_ofun == 0) {
814 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
817 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
822 return ERROR_DOS(ERRDOS, ERRbadaccess);
825 /* Any data in this call is an EA list. */
826 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
827 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
830 if (total_data != 4) {
831 if (total_data < 10) {
832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
835 if (IVAL(pdata,0) > total_data) {
836 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
837 IVAL(pdata,0), (unsigned int)total_data));
838 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
841 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
844 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 } else if (IVAL(pdata,0) != 4) {
847 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
850 status = open_file_ntcreate(conn,fname,&sbuf,
859 if (!NT_STATUS_IS_OK(status)) {
860 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
861 /* We have re-scheduled this call. */
864 return ERROR_NT(status);
867 size = get_file_size(sbuf);
868 fattr = dos_mode(conn,fname,&sbuf);
869 mtime = sbuf.st_mtime;
872 close_file(fsp,ERROR_CLOSE);
873 return(ERROR_DOS(ERRDOS,ERRnoaccess));
876 /* Save the requested allocation size. */
877 /* Allocate space for the file if a size hint is supplied */
878 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
879 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
880 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
881 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
882 if (fsp->is_directory) {
883 close_file(fsp,ERROR_CLOSE);
884 /* Can't set allocation size on a directory. */
885 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
887 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
888 close_file(fsp,ERROR_CLOSE);
889 return ERROR_NT(NT_STATUS_DISK_FULL);
892 /* Adjust size here to return the right size in the reply.
893 Windows does it this way. */
894 size = fsp->initial_allocation_size;
896 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
900 if (ea_list && smb_action == FILE_WAS_CREATED) {
901 status = set_ea(conn, fsp, fname, ea_list);
902 if (!NT_STATUS_IS_OK(status)) {
903 close_file(fsp,ERROR_CLOSE);
904 return ERROR_NT(status);
908 /* Realloc the size of parameters and data we will return */
909 *pparams = (char *)SMB_REALLOC(*pparams, 30);
910 if(*pparams == NULL ) {
911 return ERROR_NT(NT_STATUS_NO_MEMORY);
915 SSVAL(params,0,fsp->fnum);
916 SSVAL(params,2,fattr);
917 srv_put_dos_date2(params,4, mtime);
918 SIVAL(params,8, (uint32)size);
919 SSVAL(params,12,deny_mode);
920 SSVAL(params,14,0); /* open_type - file or directory. */
921 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
923 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
924 smb_action |= EXTENDED_OPLOCK_GRANTED;
927 SSVAL(params,18,smb_action);
930 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
932 SIVAL(params,20,inode);
933 SSVAL(params,24,0); /* Padding. */
935 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
936 SIVAL(params, 26, ea_size);
938 SIVAL(params, 26, 0);
941 /* Send the required number of replies */
942 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
947 /*********************************************************
948 Routine to check if a given string matches exactly.
949 as a special case a mask of "." does NOT match. That
950 is required for correct wildcard semantics
951 Case can be significant or not.
952 **********************************************************/
954 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
956 if (mask[0] == '.' && mask[1] == 0)
958 if (conn->case_sensitive)
959 return strcmp(str,mask)==0;
960 if (StrCaseCmp(str,mask) != 0) {
963 if (dptr_has_wild(conn->dirptr)) {
969 /****************************************************************************
970 Return the filetype for UNIX extensions.
971 ****************************************************************************/
973 static uint32 unix_filetype(mode_t mode)
976 return UNIX_TYPE_FILE;
977 else if(S_ISDIR(mode))
978 return UNIX_TYPE_DIR;
980 else if(S_ISLNK(mode))
981 return UNIX_TYPE_SYMLINK;
984 else if(S_ISCHR(mode))
985 return UNIX_TYPE_CHARDEV;
988 else if(S_ISBLK(mode))
989 return UNIX_TYPE_BLKDEV;
992 else if(S_ISFIFO(mode))
993 return UNIX_TYPE_FIFO;
996 else if(S_ISSOCK(mode))
997 return UNIX_TYPE_SOCKET;
1000 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1001 return UNIX_TYPE_UNKNOWN;
1004 /****************************************************************************
1005 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1006 ****************************************************************************/
1008 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
1012 if (perms == SMB_MODE_NO_CHANGE)
1013 return pst->st_mode;
1015 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1016 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1017 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1018 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1019 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1020 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1021 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1022 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1023 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1025 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1028 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1031 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1034 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
1035 ret &= lp_dir_mask(SNUM(conn));
1036 /* Add in force bits */
1037 ret |= lp_force_dir_mode(SNUM(conn));
1039 /* Apply mode mask */
1040 ret &= lp_create_mask(SNUM(conn));
1041 /* Add in force bits */
1042 ret |= lp_force_create_mode(SNUM(conn));
1048 /****************************************************************************
1049 Get a level dependent lanman2 dir entry.
1050 ****************************************************************************/
1052 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1053 void *inbuf, char *outbuf,
1054 char *path_mask,uint32 dirtype,int info_level,
1055 int requires_resume_key,
1056 BOOL dont_descend,char **ppdata,
1057 char *base_data, int space_remaining,
1058 BOOL *out_of_space, BOOL *got_exact_match,
1059 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1063 SMB_STRUCT_STAT sbuf;
1067 char *p, *q, *pdata = *ppdata;
1071 SMB_OFF_T file_size = 0;
1072 SMB_BIG_UINT allocation_size = 0;
1074 struct timespec mdate_ts, adate_ts, create_date_ts;
1075 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1077 char *last_entry_ptr;
1079 uint32 nt_extmode; /* Used for NT connections instead of mode */
1080 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1081 BOOL check_mangled_names = lp_manglednames(conn->params);
1084 *out_of_space = False;
1085 *got_exact_match = False;
1087 ZERO_STRUCT(mdate_ts);
1088 ZERO_STRUCT(adate_ts);
1089 ZERO_STRUCT(create_date_ts);
1094 p = strrchr_m(path_mask,'/');
1097 pstrcpy(mask,"*.*");
1101 pstrcpy(mask, path_mask);
1106 BOOL ms_dfs_link = False;
1108 /* Needed if we run out of space */
1109 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1110 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1113 * Due to bugs in NT client redirectors we are not using
1114 * resume keys any more - set them to zero.
1115 * Check out the related comments in findfirst/findnext.
1121 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1122 (long)conn->dirptr,curr_dirpos));
1127 pstrcpy(fname,dname);
1129 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1130 got_match = mask_match(fname, mask, conn->case_sensitive);
1132 if(!got_match && check_mangled_names &&
1133 !mangle_is_8_3(fname, False, conn->params)) {
1136 * It turns out that NT matches wildcards against
1137 * both long *and* short names. This may explain some
1138 * of the wildcard wierdness from old DOS clients
1139 * that some people have been seeing.... JRA.
1143 pstrcpy( newname, fname);
1144 mangle_map( newname, True, False, conn->params);
1145 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1146 got_match = mask_match(newname, mask, conn->case_sensitive);
1150 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1151 if (dont_descend && !isdots)
1154 pstrcpy(pathreal,conn->dirpath);
1156 pstrcat(pathreal,"/");
1157 pstrcat(pathreal,dname);
1159 if (INFO_LEVEL_IS_UNIX(info_level)) {
1160 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1161 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1162 pathreal,strerror(errno)));
1165 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1167 /* Needed to show the msdfs symlinks as
1170 if(lp_host_msdfs() &&
1171 lp_msdfs_root(SNUM(conn)) &&
1172 ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1174 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1175 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1179 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1180 pathreal,strerror(errno)));
1186 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1188 mode = dos_mode(conn,pathreal,&sbuf);
1191 if (!dir_check_ftype(conn,mode,dirtype)) {
1192 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1197 file_size = get_file_size(sbuf);
1198 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1200 mdate_ts = get_mtimespec(&sbuf);
1201 adate_ts = get_atimespec(&sbuf);
1202 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1204 if (lp_dos_filetime_resolution(SNUM(conn))) {
1205 dos_filetime_timespec(&create_date_ts);
1206 dos_filetime_timespec(&mdate_ts);
1207 dos_filetime_timespec(&adate_ts);
1210 create_date = convert_timespec_to_time_t(create_date_ts);
1211 mdate = convert_timespec_to_time_t(mdate_ts);
1212 adate = convert_timespec_to_time_t(adate_ts);
1214 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1218 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1222 mangle_map(fname,False,True,conn->params);
1227 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1229 switch (info_level) {
1230 case SMB_FIND_INFO_STANDARD:
1231 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1232 if(requires_resume_key) {
1236 srv_put_dos_date2(p,0,create_date);
1237 srv_put_dos_date2(p,4,adate);
1238 srv_put_dos_date2(p,8,mdate);
1239 SIVAL(p,12,(uint32)file_size);
1240 SIVAL(p,16,(uint32)allocation_size);
1244 p += align_string(outbuf, p, 0);
1245 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1246 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1248 SCVAL(nameptr, -1, len - 2);
1250 SCVAL(nameptr, -1, 0);
1254 SCVAL(nameptr, -1, len - 1);
1256 SCVAL(nameptr, -1, 0);
1262 case SMB_FIND_EA_SIZE:
1263 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1264 if(requires_resume_key) {
1268 srv_put_dos_date2(p,0,create_date);
1269 srv_put_dos_date2(p,4,adate);
1270 srv_put_dos_date2(p,8,mdate);
1271 SIVAL(p,12,(uint32)file_size);
1272 SIVAL(p,16,(uint32)allocation_size);
1275 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1276 SIVAL(p,22,ea_size); /* Extended attributes */
1280 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1281 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1294 SCVAL(nameptr,0,len);
1296 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1299 case SMB_FIND_EA_LIST:
1301 struct ea_list *file_list = NULL;
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1308 if(requires_resume_key) {
1312 srv_put_dos_date2(p,0,create_date);
1313 srv_put_dos_date2(p,4,adate);
1314 srv_put_dos_date2(p,8,mdate);
1315 SIVAL(p,12,(uint32)file_size);
1316 SIVAL(p,16,(uint32)allocation_size);
1318 p += 22; /* p now points to the EA area. */
1320 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1321 name_list = ea_list_union(name_list, file_list, &ea_len);
1323 /* We need to determine if this entry will fit in the space available. */
1324 /* Max string size is 255 bytes. */
1325 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1326 /* Move the dirptr back to prev_dirpos */
1327 dptr_SeekDir(conn->dirptr, prev_dirpos);
1328 *out_of_space = True;
1329 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1330 return False; /* Not finished - just out of space */
1333 /* Push the ea_data followed by the name. */
1334 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1336 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1337 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1350 SCVAL(nameptr,0,len);
1352 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1356 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1357 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1358 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1360 SIVAL(p,0,reskey); p += 4;
1361 put_long_date_timespec(p,create_date_ts); p += 8;
1362 put_long_date_timespec(p,adate_ts); p += 8;
1363 put_long_date_timespec(p,mdate_ts); p += 8;
1364 put_long_date_timespec(p,mdate_ts); p += 8;
1365 SOFF_T(p,0,file_size); p += 8;
1366 SOFF_T(p,0,allocation_size); p += 8;
1367 SIVAL(p,0,nt_extmode); p += 4;
1368 q = p; p += 4; /* q is placeholder for name length. */
1370 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1371 SIVAL(p,0,ea_size); /* Extended attributes */
1374 /* Clear the short name buffer. This is
1375 * IMPORTANT as not doing so will trigger
1376 * a Win2k client bug. JRA.
1378 if (!was_8_3 && check_mangled_names) {
1379 pstring mangled_name;
1380 pstrcpy(mangled_name, fname);
1381 mangle_map(mangled_name,True,True,
1383 mangled_name[12] = 0;
1384 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1386 memset(p + 2 + len,'\0',24 - len);
1393 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1396 SIVAL(p,0,0); /* Ensure any padding is null. */
1397 len = PTR_DIFF(p, pdata);
1398 len = (len + 3) & ~3;
1403 case SMB_FIND_FILE_DIRECTORY_INFO:
1404 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1406 SIVAL(p,0,reskey); p += 4;
1407 put_long_date_timespec(p,create_date_ts); p += 8;
1408 put_long_date_timespec(p,adate_ts); p += 8;
1409 put_long_date_timespec(p,mdate_ts); p += 8;
1410 put_long_date_timespec(p,mdate_ts); p += 8;
1411 SOFF_T(p,0,file_size); p += 8;
1412 SOFF_T(p,0,allocation_size); p += 8;
1413 SIVAL(p,0,nt_extmode); p += 4;
1414 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1417 SIVAL(p,0,0); /* Ensure any padding is null. */
1418 len = PTR_DIFF(p, pdata);
1419 len = (len + 3) & ~3;
1424 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1425 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1427 SIVAL(p,0,reskey); p += 4;
1428 put_long_date_timespec(p,create_date_ts); p += 8;
1429 put_long_date_timespec(p,adate_ts); p += 8;
1430 put_long_date_timespec(p,mdate_ts); p += 8;
1431 put_long_date_timespec(p,mdate_ts); p += 8;
1432 SOFF_T(p,0,file_size); p += 8;
1433 SOFF_T(p,0,allocation_size); p += 8;
1434 SIVAL(p,0,nt_extmode); p += 4;
1435 q = p; p += 4; /* q is placeholder for name length. */
1437 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1438 SIVAL(p,0,ea_size); /* Extended attributes */
1441 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1445 SIVAL(p,0,0); /* Ensure any padding is null. */
1446 len = PTR_DIFF(p, pdata);
1447 len = (len + 3) & ~3;
1452 case SMB_FIND_FILE_NAMES_INFO:
1453 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1455 SIVAL(p,0,reskey); p += 4;
1457 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1458 acl on a dir (tridge) */
1459 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1462 SIVAL(p,0,0); /* Ensure any padding is null. */
1463 len = PTR_DIFF(p, pdata);
1464 len = (len + 3) & ~3;
1469 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1470 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1472 SIVAL(p,0,reskey); p += 4;
1473 put_long_date_timespec(p,create_date_ts); p += 8;
1474 put_long_date_timespec(p,adate_ts); p += 8;
1475 put_long_date_timespec(p,mdate_ts); p += 8;
1476 put_long_date_timespec(p,mdate_ts); p += 8;
1477 SOFF_T(p,0,file_size); p += 8;
1478 SOFF_T(p,0,allocation_size); p += 8;
1479 SIVAL(p,0,nt_extmode); p += 4;
1480 q = p; p += 4; /* q is placeholder for name length. */
1482 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1483 SIVAL(p,0,ea_size); /* Extended attributes */
1486 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1487 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1488 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1489 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1492 SIVAL(p,0,0); /* Ensure any padding is null. */
1493 len = PTR_DIFF(p, pdata);
1494 len = (len + 3) & ~3;
1499 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1500 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1501 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1503 SIVAL(p,0,reskey); p += 4;
1504 put_long_date_timespec(p,create_date_ts); p += 8;
1505 put_long_date_timespec(p,adate_ts); p += 8;
1506 put_long_date_timespec(p,mdate_ts); p += 8;
1507 put_long_date_timespec(p,mdate_ts); p += 8;
1508 SOFF_T(p,0,file_size); p += 8;
1509 SOFF_T(p,0,allocation_size); p += 8;
1510 SIVAL(p,0,nt_extmode); p += 4;
1511 q = p; p += 4; /* q is placeholder for name length */
1513 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1514 SIVAL(p,0,ea_size); /* Extended attributes */
1517 /* Clear the short name buffer. This is
1518 * IMPORTANT as not doing so will trigger
1519 * a Win2k client bug. JRA.
1521 if (!was_8_3 && check_mangled_names) {
1522 pstring mangled_name;
1523 pstrcpy(mangled_name, fname);
1524 mangle_map(mangled_name,True,True,
1526 mangled_name[12] = 0;
1527 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1530 memset(p + 2 + len,'\0',24 - len);
1537 SSVAL(p,0,0); p += 2; /* Reserved ? */
1538 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1539 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1540 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1543 SIVAL(p,0,0); /* Ensure any padding is null. */
1544 len = PTR_DIFF(p, pdata);
1545 len = (len + 3) & ~3;
1550 /* CIFS UNIX Extension. */
1552 case SMB_FIND_FILE_UNIX:
1553 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1555 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1557 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1558 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1561 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1564 put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */
1565 put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
1566 put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
1569 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1573 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1577 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1580 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1584 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1588 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1591 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1595 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1599 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1601 SIVAL(p,0,0); /* Ensure any padding is null. */
1603 len = PTR_DIFF(p, pdata);
1604 len = (len + 3) & ~3;
1605 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1607 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1616 if (PTR_DIFF(p,pdata) > space_remaining) {
1617 /* Move the dirptr back to prev_dirpos */
1618 dptr_SeekDir(conn->dirptr, prev_dirpos);
1619 *out_of_space = True;
1620 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1621 return False; /* Not finished - just out of space */
1624 /* Setup the last entry pointer, as an offset from base_data */
1625 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1626 /* Advance the data pointer to the next slot */
1632 /****************************************************************************
1633 Reply to a TRANS2_FINDFIRST.
1634 ****************************************************************************/
1636 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1637 char **pparams, int total_params, char **ppdata, int total_data,
1638 unsigned int max_data_bytes)
1640 /* We must be careful here that we don't return more than the
1641 allowed number of data bytes. If this means returning fewer than
1642 maxentries then so be it. We assume that the redirector has
1643 enough room for the fixed number of parameter bytes it has
1645 char *params = *pparams;
1646 char *pdata = *ppdata;
1649 uint16 findfirst_flags;
1650 BOOL close_after_first;
1652 BOOL requires_resume_key;
1657 int last_entry_off=0;
1661 BOOL finished = False;
1662 BOOL dont_descend = False;
1663 BOOL out_of_space = False;
1664 int space_remaining;
1665 BOOL bad_path = False;
1666 BOOL mask_contains_wcard = False;
1667 SMB_STRUCT_STAT sbuf;
1668 TALLOC_CTX *ea_ctx = NULL;
1669 struct ea_list *ea_list = NULL;
1670 NTSTATUS ntstatus = NT_STATUS_OK;
1672 if (total_params < 13) {
1673 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1676 dirtype = SVAL(params,0);
1677 maxentries = SVAL(params,2);
1678 findfirst_flags = SVAL(params,4);
1679 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1680 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1681 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1682 info_level = SVAL(params,6);
1684 *directory = *mask = 0;
1686 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1687 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1688 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1689 info_level, max_data_bytes));
1692 /* W2K3 seems to treat zero as 1. */
1696 switch (info_level) {
1697 case SMB_FIND_INFO_STANDARD:
1698 case SMB_FIND_EA_SIZE:
1699 case SMB_FIND_EA_LIST:
1700 case SMB_FIND_FILE_DIRECTORY_INFO:
1701 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1702 case SMB_FIND_FILE_NAMES_INFO:
1703 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1704 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1705 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1707 case SMB_FIND_FILE_UNIX:
1708 if (!lp_unix_extensions()) {
1709 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1713 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1716 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1717 if (!NT_STATUS_IS_OK(ntstatus)) {
1718 return ERROR_NT(ntstatus);
1721 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1723 unix_convert(directory,conn,0,&bad_path,&sbuf);
1725 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1727 if(!check_name(directory,conn)) {
1728 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1731 p = strrchr_m(directory,'/');
1733 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1734 if((directory[0] == '.') && (directory[1] == '\0')) {
1736 mask_contains_wcard = True;
1738 pstrcpy(mask,directory);
1740 pstrcpy(directory,"./");
1746 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1748 if (info_level == SMB_FIND_EA_LIST) {
1751 if (total_data < 4) {
1752 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1755 ea_size = IVAL(pdata,0);
1756 if (ea_size != total_data) {
1757 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1758 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1759 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1762 if (!lp_ea_support(SNUM(conn))) {
1763 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1766 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1767 return ERROR_NT(NT_STATUS_NO_MEMORY);
1770 /* Pull out the list of names. */
1771 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1773 talloc_destroy(ea_ctx);
1774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1778 *ppdata = (char *)SMB_REALLOC(
1779 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1780 if(*ppdata == NULL ) {
1781 talloc_destroy(ea_ctx);
1782 return ERROR_NT(NT_STATUS_NO_MEMORY);
1786 /* Realloc the params space */
1787 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1788 if (*pparams == NULL) {
1789 talloc_destroy(ea_ctx);
1790 return ERROR_NT(NT_STATUS_NO_MEMORY);
1794 /* Save the wildcard match and attribs we are using on this directory -
1795 needed as lanman2 assumes these are being saved between calls */
1797 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1799 talloc_destroy(ea_ctx);
1800 return(UNIXERROR(ERRDOS,ERRbadfile));
1803 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1805 /* We don't need to check for VOL here as this is returned by
1806 a different TRANS2 call. */
1808 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1809 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1810 dont_descend = True;
1813 space_remaining = max_data_bytes;
1814 out_of_space = False;
1816 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1817 BOOL got_exact_match = False;
1819 /* this is a heuristic to avoid seeking the dirptr except when
1820 absolutely necessary. It allows for a filename of about 40 chars */
1821 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1822 out_of_space = True;
1825 finished = !get_lanman2_dir_entry(conn,
1827 mask,dirtype,info_level,
1828 requires_resume_key,dont_descend,
1829 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1830 &last_entry_off, ea_list, ea_ctx);
1833 if (finished && out_of_space)
1836 if (!finished && !out_of_space)
1840 * As an optimisation if we know we aren't looking
1841 * for a wildcard name (ie. the name matches the wildcard exactly)
1842 * then we can finish on any (first) match.
1843 * This speeds up large directory searches. JRA.
1849 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1852 talloc_destroy(ea_ctx);
1854 /* Check if we can close the dirptr */
1855 if(close_after_first || (finished && close_if_end)) {
1856 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1857 dptr_close(&dptr_num);
1861 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1862 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1863 * the protocol level is less than NT1. Tested with smbclient. JRA.
1864 * This should fix the OS/2 client bug #2335.
1867 if(numentries == 0) {
1868 dptr_close(&dptr_num);
1869 if (Protocol < PROTOCOL_NT1) {
1870 return ERROR_DOS(ERRDOS,ERRnofiles);
1872 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1876 /* At this point pdata points to numentries directory entries. */
1878 /* Set up the return parameter block */
1879 SSVAL(params,0,dptr_num);
1880 SSVAL(params,2,numentries);
1881 SSVAL(params,4,finished);
1882 SSVAL(params,6,0); /* Never an EA error */
1883 SSVAL(params,8,last_entry_off);
1885 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1887 if ((! *directory) && dptr_path(dptr_num))
1888 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1890 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1891 smb_fn_name(CVAL(inbuf,smb_com)),
1892 mask, directory, dirtype, numentries ) );
1895 * Force a name mangle here to ensure that the
1896 * mask as an 8.3 name is top of the mangled cache.
1897 * The reasons for this are subtle. Don't remove
1898 * this code unless you know what you are doing
1899 * (see PR#13758). JRA.
1902 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1903 mangle_map(mask, True, True, conn->params);
1908 /****************************************************************************
1909 Reply to a TRANS2_FINDNEXT.
1910 ****************************************************************************/
1912 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1913 char **pparams, int total_params, char **ppdata, int total_data,
1914 unsigned int max_data_bytes)
1916 /* We must be careful here that we don't return more than the
1917 allowed number of data bytes. If this means returning fewer than
1918 maxentries then so be it. We assume that the redirector has
1919 enough room for the fixed number of parameter bytes it has
1921 char *params = *pparams;
1922 char *pdata = *ppdata;
1927 uint16 findnext_flags;
1928 BOOL close_after_request;
1930 BOOL requires_resume_key;
1932 BOOL mask_contains_wcard = False;
1933 pstring resume_name;
1939 int i, last_entry_off=0;
1940 BOOL finished = False;
1941 BOOL dont_descend = False;
1942 BOOL out_of_space = False;
1943 int space_remaining;
1944 TALLOC_CTX *ea_ctx = NULL;
1945 struct ea_list *ea_list = NULL;
1946 NTSTATUS ntstatus = NT_STATUS_OK;
1948 if (total_params < 13) {
1949 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1952 dptr_num = SVAL(params,0);
1953 maxentries = SVAL(params,2);
1954 info_level = SVAL(params,4);
1955 resume_key = IVAL(params,6);
1956 findnext_flags = SVAL(params,10);
1957 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1958 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1959 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1960 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1962 *mask = *directory = *resume_name = 0;
1964 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1965 if (!NT_STATUS_IS_OK(ntstatus)) {
1966 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1967 complain (it thinks we're asking for the directory above the shared
1968 path or an invalid name). Catch this as the resume name is only compared, never used in
1969 a file access. JRA. */
1970 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1971 pstrcpy(resume_name, "..");
1972 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1973 pstrcpy(resume_name, ".");
1975 return ERROR_NT(ntstatus);
1979 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1980 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1981 resume_key = %d resume name = %s continue=%d level = %d\n",
1982 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1983 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1986 /* W2K3 seems to treat zero as 1. */
1990 switch (info_level) {
1991 case SMB_FIND_INFO_STANDARD:
1992 case SMB_FIND_EA_SIZE:
1993 case SMB_FIND_EA_LIST:
1994 case SMB_FIND_FILE_DIRECTORY_INFO:
1995 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1996 case SMB_FIND_FILE_NAMES_INFO:
1997 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1998 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1999 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2001 case SMB_FIND_FILE_UNIX:
2002 if (!lp_unix_extensions()) {
2003 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2007 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2010 if (info_level == SMB_FIND_EA_LIST) {
2013 if (total_data < 4) {
2014 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2017 ea_size = IVAL(pdata,0);
2018 if (ea_size != total_data) {
2019 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2020 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2021 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2024 if (!lp_ea_support(SNUM(conn))) {
2025 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2028 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2029 return ERROR_NT(NT_STATUS_NO_MEMORY);
2032 /* Pull out the list of names. */
2033 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2035 talloc_destroy(ea_ctx);
2036 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2040 *ppdata = (char *)SMB_REALLOC(
2041 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2042 if(*ppdata == NULL) {
2043 talloc_destroy(ea_ctx);
2044 return ERROR_NT(NT_STATUS_NO_MEMORY);
2049 /* Realloc the params space */
2050 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2051 if(*pparams == NULL ) {
2052 talloc_destroy(ea_ctx);
2053 return ERROR_NT(NT_STATUS_NO_MEMORY);
2058 /* Check that the dptr is valid */
2059 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2060 talloc_destroy(ea_ctx);
2061 return ERROR_DOS(ERRDOS,ERRnofiles);
2064 string_set(&conn->dirpath,dptr_path(dptr_num));
2066 /* Get the wildcard mask from the dptr */
2067 if((p = dptr_wcard(dptr_num))== NULL) {
2068 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2069 talloc_destroy(ea_ctx);
2070 return ERROR_DOS(ERRDOS,ERRnofiles);
2074 pstrcpy(directory,conn->dirpath);
2076 /* Get the attr mask from the dptr */
2077 dirtype = dptr_attr(dptr_num);
2079 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2080 dptr_num, mask, dirtype,
2082 dptr_TellDir(conn->dirptr)));
2084 /* We don't need to check for VOL here as this is returned by
2085 a different TRANS2 call. */
2087 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2088 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2089 dont_descend = True;
2092 space_remaining = max_data_bytes;
2093 out_of_space = False;
2096 * Seek to the correct position. We no longer use the resume key but
2097 * depend on the last file name instead.
2100 if(*resume_name && !continue_bit) {
2103 long current_pos = 0;
2105 * Remember, mangle_map is called by
2106 * get_lanman2_dir_entry(), so the resume name
2107 * could be mangled. Ensure we check the unmangled name.
2110 if (mangle_is_mangled(resume_name, conn->params)) {
2111 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2116 * Fix for NT redirector problem triggered by resume key indexes
2117 * changing between directory scans. We now return a resume key of 0
2118 * and instead look for the filename to continue from (also given
2119 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2120 * findfirst/findnext (as is usual) then the directory pointer
2121 * should already be at the correct place.
2124 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2125 } /* end if resume_name && !continue_bit */
2127 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2128 BOOL got_exact_match = False;
2130 /* this is a heuristic to avoid seeking the dirptr except when
2131 absolutely necessary. It allows for a filename of about 40 chars */
2132 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2133 out_of_space = True;
2136 finished = !get_lanman2_dir_entry(conn,
2138 mask,dirtype,info_level,
2139 requires_resume_key,dont_descend,
2140 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2141 &last_entry_off, ea_list, ea_ctx);
2144 if (finished && out_of_space)
2147 if (!finished && !out_of_space)
2151 * As an optimisation if we know we aren't looking
2152 * for a wildcard name (ie. the name matches the wildcard exactly)
2153 * then we can finish on any (first) match.
2154 * This speeds up large directory searches. JRA.
2160 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2163 talloc_destroy(ea_ctx);
2165 /* Check if we can close the dirptr */
2166 if(close_after_request || (finished && close_if_end)) {
2167 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2168 dptr_close(&dptr_num); /* This frees up the saved mask */
2171 /* Set up the return parameter block */
2172 SSVAL(params,0,numentries);
2173 SSVAL(params,2,finished);
2174 SSVAL(params,4,0); /* Never an EA error */
2175 SSVAL(params,6,last_entry_off);
2177 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2179 if ((! *directory) && dptr_path(dptr_num))
2180 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2182 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2183 smb_fn_name(CVAL(inbuf,smb_com)),
2184 mask, directory, dirtype, numentries ) );
2189 /****************************************************************************
2190 Reply to a TRANS2_QFSINFO (query filesystem info).
2191 ****************************************************************************/
2193 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2194 char **pparams, int total_params, char **ppdata, int total_data,
2195 unsigned int max_data_bytes)
2197 char *pdata = *ppdata;
2198 char *params = *pparams;
2202 char *vname = volume_label(SNUM(conn));
2203 int snum = SNUM(conn);
2204 char *fstype = lp_fstype(SNUM(conn));
2207 if (total_params < 2) {
2208 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2211 info_level = SVAL(params,0);
2213 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2215 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2216 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2217 return ERROR_DOS(ERRSRV,ERRinvdevice);
2220 *ppdata = (char *)SMB_REALLOC(
2221 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2222 if (*ppdata == NULL ) {
2223 return ERROR_NT(NT_STATUS_NO_MEMORY);
2227 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2229 switch (info_level) {
2230 case SMB_INFO_ALLOCATION:
2232 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2234 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2235 return(UNIXERROR(ERRHRD,ERRgeneral));
2238 block_size = lp_block_size(snum);
2239 if (bsize < block_size) {
2240 SMB_BIG_UINT factor = block_size/bsize;
2245 if (bsize > block_size) {
2246 SMB_BIG_UINT factor = bsize/block_size;
2251 bytes_per_sector = 512;
2252 sectors_per_unit = bsize/bytes_per_sector;
2254 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2255 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2256 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2258 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2259 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2260 SIVAL(pdata,l1_cUnit,dsize);
2261 SIVAL(pdata,l1_cUnitAvail,dfree);
2262 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2266 case SMB_INFO_VOLUME:
2267 /* Return volume name */
2269 * Add volume serial number - hash of a combination of
2270 * the called hostname and the service name.
2272 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2274 * Win2k3 and previous mess this up by sending a name length
2275 * one byte short. I believe only older clients (OS/2 Win9x) use
2276 * this call so try fixing this by adding a terminating null to
2277 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2279 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2280 SCVAL(pdata,l2_vol_cch,len);
2281 data_len = l2_vol_szVolLabel + len;
2282 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2283 (unsigned)st.st_ctime, len, vname));
2286 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2287 case SMB_FS_ATTRIBUTE_INFORMATION:
2290 #if defined(HAVE_SYS_QUOTAS)
2291 quota_flag = FILE_VOLUME_QUOTAS;
2294 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2295 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2296 quota_flag); /* FS ATTRIBUTES */
2298 SIVAL(pdata,4,255); /* Max filename component length */
2299 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2300 and will think we can't do long filenames */
2301 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2303 data_len = 12 + len;
2306 case SMB_QUERY_FS_LABEL_INFO:
2307 case SMB_FS_LABEL_INFORMATION:
2308 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2313 case SMB_QUERY_FS_VOLUME_INFO:
2314 case SMB_FS_VOLUME_INFORMATION:
2317 * Add volume serial number - hash of a combination of
2318 * the called hostname and the service name.
2320 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2321 (str_checksum(get_local_machine_name())<<16));
2323 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2324 SIVAL(pdata,12,len);
2326 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2327 (int)strlen(vname),vname, lp_servicename(snum)));
2330 case SMB_QUERY_FS_SIZE_INFO:
2331 case SMB_FS_SIZE_INFORMATION:
2333 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2335 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2336 return(UNIXERROR(ERRHRD,ERRgeneral));
2338 block_size = lp_block_size(snum);
2339 if (bsize < block_size) {
2340 SMB_BIG_UINT factor = block_size/bsize;
2345 if (bsize > block_size) {
2346 SMB_BIG_UINT factor = bsize/block_size;
2351 bytes_per_sector = 512;
2352 sectors_per_unit = bsize/bytes_per_sector;
2353 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2354 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2355 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2356 SBIG_UINT(pdata,0,dsize);
2357 SBIG_UINT(pdata,8,dfree);
2358 SIVAL(pdata,16,sectors_per_unit);
2359 SIVAL(pdata,20,bytes_per_sector);
2363 case SMB_FS_FULL_SIZE_INFORMATION:
2365 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2367 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2368 return(UNIXERROR(ERRHRD,ERRgeneral));
2370 block_size = lp_block_size(snum);
2371 if (bsize < block_size) {
2372 SMB_BIG_UINT factor = block_size/bsize;
2377 if (bsize > block_size) {
2378 SMB_BIG_UINT factor = bsize/block_size;
2383 bytes_per_sector = 512;
2384 sectors_per_unit = bsize/bytes_per_sector;
2385 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2386 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2387 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2388 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2389 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2390 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2391 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2392 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2396 case SMB_QUERY_FS_DEVICE_INFO:
2397 case SMB_FS_DEVICE_INFORMATION:
2399 SIVAL(pdata,0,0); /* dev type */
2400 SIVAL(pdata,4,0); /* characteristics */
2403 #ifdef HAVE_SYS_QUOTAS
2404 case SMB_FS_QUOTA_INFORMATION:
2406 * what we have to send --metze:
2408 * Unknown1: 24 NULL bytes
2409 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2410 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2411 * Quota Flags: 2 byte :
2412 * Unknown3: 6 NULL bytes
2416 * details for Quota Flags:
2418 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2419 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2420 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2421 * 0x0001 Enable Quotas: enable quota for this fs
2425 /* we need to fake up a fsp here,
2426 * because its not send in this call
2429 SMB_NTQUOTA_STRUCT quotas;
2432 ZERO_STRUCT(quotas);
2438 if (current_user.ut.uid != 0) {
2439 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2440 lp_servicename(SNUM(conn)),conn->user));
2441 return ERROR_DOS(ERRDOS,ERRnoaccess);
2444 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2445 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2446 return ERROR_DOS(ERRSRV,ERRerror);
2451 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2453 /* Unknown1 24 NULL bytes*/
2454 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2455 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2456 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2458 /* Default Soft Quota 8 bytes */
2459 SBIG_UINT(pdata,24,quotas.softlim);
2461 /* Default Hard Quota 8 bytes */
2462 SBIG_UINT(pdata,32,quotas.hardlim);
2464 /* Quota flag 2 bytes */
2465 SSVAL(pdata,40,quotas.qflags);
2467 /* Unknown3 6 NULL bytes */
2473 #endif /* HAVE_SYS_QUOTAS */
2474 case SMB_FS_OBJECTID_INFORMATION:
2479 * Query the version and capabilities of the CIFS UNIX extensions
2483 case SMB_QUERY_CIFS_UNIX_INFO:
2484 if (!lp_unix_extensions()) {
2485 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2488 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2489 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2490 /* We have POSIX ACLs, pathname and locking capability. */
2491 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2492 CIFS_UNIX_POSIX_ACLS_CAP|
2493 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2494 CIFS_UNIX_FCNTL_LOCKS_CAP)));
2497 case SMB_QUERY_POSIX_FS_INFO:
2500 vfs_statvfs_struct svfs;
2502 if (!lp_unix_extensions()) {
2503 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2506 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2510 SIVAL(pdata,0,svfs.OptimalTransferSize);
2511 SIVAL(pdata,4,svfs.BlockSize);
2512 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2513 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2514 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2515 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2516 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2517 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2518 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2520 } else if (rc == EOPNOTSUPP) {
2521 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2522 #endif /* EOPNOTSUPP */
2524 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2525 return ERROR_DOS(ERRSRV,ERRerror);
2530 case SMB_MAC_QUERY_FS_INFO:
2532 * Thursby MAC extension... ONLY on NTFS filesystems
2533 * once we do streams then we don't need this
2535 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2537 SIVAL(pdata,84,0x100); /* Don't support mac... */
2542 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2546 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2548 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2553 /****************************************************************************
2554 Reply to a TRANS2_SETFSINFO (set filesystem info).
2555 ****************************************************************************/
2557 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2558 char **pparams, int total_params, char **ppdata, int total_data,
2559 unsigned int max_data_bytes)
2561 char *pdata = *ppdata;
2562 char *params = *pparams;
2566 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2569 if (total_params < 4) {
2570 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2572 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2575 info_level = SVAL(params,2);
2577 switch(info_level) {
2578 case SMB_SET_CIFS_UNIX_INFO:
2580 uint16 client_unix_major;
2581 uint16 client_unix_minor;
2582 uint32 client_unix_cap_low;
2583 uint32 client_unix_cap_high;
2585 if (!lp_unix_extensions()) {
2586 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2589 /* There should be 12 bytes of capabilities set. */
2590 if (total_data < 8) {
2591 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2593 client_unix_major = SVAL(pdata,0);
2594 client_unix_minor = SVAL(pdata,2);
2595 client_unix_cap_low = IVAL(pdata,4);
2596 client_unix_cap_high = IVAL(pdata,8);
2597 /* Just print these values for now. */
2598 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2599 cap_low = 0x%x, cap_high = 0x%x\n",
2600 (unsigned int)client_unix_major,
2601 (unsigned int)client_unix_minor,
2602 (unsigned int)client_unix_cap_low,
2603 (unsigned int)client_unix_cap_high ));
2605 /* Here is where we must switch to posix pathname processing... */
2606 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2607 lp_set_posix_pathnames();
2608 mangle_change_to_posix();
2611 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2612 lp_set_posix_cifsx_locktype(POSIX_LOCK);
2616 case SMB_FS_QUOTA_INFORMATION:
2618 files_struct *fsp = NULL;
2619 SMB_NTQUOTA_STRUCT quotas;
2621 ZERO_STRUCT(quotas);
2624 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2625 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2626 lp_servicename(SNUM(conn)),conn->user));
2627 return ERROR_DOS(ERRSRV,ERRaccess);
2630 /* note: normaly there're 48 bytes,
2631 * but we didn't use the last 6 bytes for now
2634 fsp = file_fsp(params,0);
2635 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2636 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2637 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2640 if (total_data < 42) {
2641 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2643 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2646 /* unknown_1 24 NULL bytes in pdata*/
2648 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2649 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2650 #ifdef LARGE_SMB_OFF_T
2651 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2652 #else /* LARGE_SMB_OFF_T */
2653 if ((IVAL(pdata,28) != 0)&&
2654 ((quotas.softlim != 0xFFFFFFFF)||
2655 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2656 /* more than 32 bits? */
2657 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2659 #endif /* LARGE_SMB_OFF_T */
2661 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2662 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2663 #ifdef LARGE_SMB_OFF_T
2664 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2665 #else /* LARGE_SMB_OFF_T */
2666 if ((IVAL(pdata,36) != 0)&&
2667 ((quotas.hardlim != 0xFFFFFFFF)||
2668 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2669 /* more than 32 bits? */
2670 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2672 #endif /* LARGE_SMB_OFF_T */
2674 /* quota_flags 2 bytes **/
2675 quotas.qflags = SVAL(pdata,40);
2677 /* unknown_2 6 NULL bytes follow*/
2679 /* now set the quotas */
2680 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2681 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2682 return ERROR_DOS(ERRSRV,ERRerror);
2688 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2690 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2695 * sending this reply works fine,
2696 * but I'm not sure it's the same
2697 * like windows do...
2700 outsize = set_message(outbuf,10,0,True);
2705 /****************************************************************************
2706 Utility function to set bad path error.
2707 ****************************************************************************/
2709 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2711 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2712 err, (int)bad_path ));
2716 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2718 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2721 return UNIXERROR(def_class,def_code);
2724 #if defined(HAVE_POSIX_ACLS)
2725 /****************************************************************************
2726 Utility function to count the number of entries in a POSIX acl.
2727 ****************************************************************************/
2729 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2731 unsigned int ace_count = 0;
2732 int entry_id = SMB_ACL_FIRST_ENTRY;
2733 SMB_ACL_ENTRY_T entry;
2735 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2737 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2738 entry_id = SMB_ACL_NEXT_ENTRY;
2745 /****************************************************************************
2746 Utility function to marshall a POSIX acl into wire format.
2747 ****************************************************************************/
2749 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2751 int entry_id = SMB_ACL_FIRST_ENTRY;
2752 SMB_ACL_ENTRY_T entry;
2754 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2755 SMB_ACL_TAG_T tagtype;
2756 SMB_ACL_PERMSET_T permset;
2757 unsigned char perms = 0;
2758 unsigned int own_grp;
2761 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2762 entry_id = SMB_ACL_NEXT_ENTRY;
2765 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2766 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2770 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2771 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2775 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2776 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2777 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2779 SCVAL(pdata,1,perms);
2782 case SMB_ACL_USER_OBJ:
2783 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2784 own_grp = (unsigned int)pst->st_uid;
2785 SIVAL(pdata,2,own_grp);
2790 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2792 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2794 own_grp = (unsigned int)*puid;
2795 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2796 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2797 SIVAL(pdata,2,own_grp);
2801 case SMB_ACL_GROUP_OBJ:
2802 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2803 own_grp = (unsigned int)pst->st_gid;
2804 SIVAL(pdata,2,own_grp);
2809 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2811 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2813 own_grp = (unsigned int)*pgid;
2814 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2815 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2816 SIVAL(pdata,2,own_grp);
2821 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2822 SIVAL(pdata,2,0xFFFFFFFF);
2823 SIVAL(pdata,6,0xFFFFFFFF);
2826 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2827 SIVAL(pdata,2,0xFFFFFFFF);
2828 SIVAL(pdata,6,0xFFFFFFFF);
2831 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2834 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2841 /****************************************************************************
2842 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2843 file name or file id).
2844 ****************************************************************************/
2846 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2847 unsigned int tran_call,
2848 char **pparams, int total_params, char **ppdata, int total_data,
2849 unsigned int max_data_bytes)
2851 char *params = *pparams;
2852 char *pdata = *ppdata;
2856 SMB_OFF_T file_size=0;
2857 SMB_BIG_UINT allocation_size=0;
2858 unsigned int data_size = 0;
2859 unsigned int param_size = 2;
2860 SMB_STRUCT_STAT sbuf;
2861 pstring fname, dos_fname;
2866 BOOL bad_path = False;
2867 BOOL delete_pending = False;
2869 time_t create_time, mtime, atime;
2870 struct timespec create_time_ts, mtime_ts, atime_ts;
2871 files_struct *fsp = NULL;
2872 TALLOC_CTX *data_ctx = NULL;
2873 struct ea_list *ea_list = NULL;
2874 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2875 char *lock_data = NULL;
2878 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2882 if (tran_call == TRANSACT2_QFILEINFO) {
2883 if (total_params < 4) {
2884 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2887 fsp = file_fsp(params,0);
2888 info_level = SVAL(params,2);
2890 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2892 if(fsp && (fsp->fake_file_handle)) {
2894 * This is actually for the QUOTA_FAKE_FILE --metze
2897 pstrcpy(fname, fsp->fsp_name);
2898 /* We know this name is ok, it's already passed the checks. */
2900 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2902 * This is actually a QFILEINFO on a directory
2903 * handle (returned from an NT SMB). NT5.0 seems
2904 * to do this call. JRA.
2906 /* We know this name is ok, it's already passed the checks. */
2907 pstrcpy(fname, fsp->fsp_name);
2909 if (INFO_LEVEL_IS_UNIX(info_level)) {
2910 /* Always do lstat for UNIX calls. */
2911 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2912 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2913 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2915 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2916 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2917 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2920 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2923 * Original code - this is an open file.
2925 CHECK_FSP(fsp,conn);
2927 pstrcpy(fname, fsp->fsp_name);
2928 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2929 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2930 return(UNIXERROR(ERRDOS,ERRbadfid));
2932 pos = fsp->fh->position_information;
2933 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2934 access_mask = fsp->access_mask;
2937 NTSTATUS status = NT_STATUS_OK;
2940 if (total_params < 7) {
2941 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2944 info_level = SVAL(params,0);
2946 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2948 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
2949 if (!NT_STATUS_IS_OK(status)) {
2950 return ERROR_NT(status);
2953 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2955 unix_convert(fname,conn,0,&bad_path,&sbuf);
2957 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2959 if (!check_name(fname,conn)) {
2960 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2961 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2964 if (INFO_LEVEL_IS_UNIX(info_level)) {
2965 /* Always do lstat for UNIX calls. */
2966 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2967 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2968 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2970 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2971 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2972 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2975 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2976 if (delete_pending) {
2977 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2981 nlink = sbuf.st_nlink;
2983 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2984 /* NTFS does not seem to count ".." */
2988 if ((nlink > 0) && delete_pending) {
2992 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2993 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2996 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2997 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2999 p = strrchr_m(fname,'/');
3005 mode = dos_mode(conn,fname,&sbuf);
3007 mode = FILE_ATTRIBUTE_NORMAL;
3009 fullpathname = fname;
3011 file_size = get_file_size(sbuf);
3013 /* Pull out any data sent here before we realloc. */
3014 switch (info_level) {
3015 case SMB_INFO_QUERY_EAS_FROM_LIST:
3017 /* Pull any EA list from the data portion. */
3020 if (total_data < 4) {
3021 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3023 ea_size = IVAL(pdata,0);
3025 if (total_data > 0 && ea_size != total_data) {
3026 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3027 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3028 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3031 if (!lp_ea_support(SNUM(conn))) {
3032 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3035 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3036 return ERROR_NT(NT_STATUS_NO_MEMORY);
3039 /* Pull out the list of names. */
3040 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3042 talloc_destroy(data_ctx);
3043 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3048 case SMB_QUERY_POSIX_LOCK:
3050 if (fsp == NULL || fsp->fh->fd == -1) {
3051 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3054 if (total_data != POSIX_LOCK_DATA_SIZE) {
3055 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3058 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3059 return ERROR_NT(NT_STATUS_NO_MEMORY);
3062 /* Copy the lock range data. */
3063 lock_data = (char *)talloc_memdup(
3064 data_ctx, pdata, total_data);
3066 talloc_destroy(data_ctx);
3067 return ERROR_NT(NT_STATUS_NO_MEMORY);
3074 *pparams = (char *)SMB_REALLOC(*pparams,2);
3075 if (*pparams == NULL) {
3076 talloc_destroy(data_ctx);
3077 return ERROR_NT(NT_STATUS_NO_MEMORY);
3081 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3082 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3083 if (*ppdata == NULL ) {
3084 talloc_destroy(data_ctx);
3085 return ERROR_NT(NT_STATUS_NO_MEMORY);
3089 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3090 mtime_ts = get_mtimespec(&sbuf);
3091 atime_ts = get_atimespec(&sbuf);
3093 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3096 if (fsp->pending_modtime) {
3097 /* the pending modtime overrides the current modtime */
3098 mtime_ts.tv_sec = fsp->pending_modtime;
3099 mtime_ts.tv_nsec = 0;
3102 /* Do we have this path open ? */
3103 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3104 if (fsp1 && fsp1->pending_modtime) {
3105 /* the pending modtime overrides the current modtime */
3106 mtime_ts.tv_sec = fsp1->pending_modtime;
3107 mtime_ts.tv_nsec = 0;
3109 if (fsp1 && fsp1->initial_allocation_size) {
3110 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3114 if (lp_dos_filetime_resolution(SNUM(conn))) {
3115 dos_filetime_timespec(&create_time_ts);
3116 dos_filetime_timespec(&mtime_ts);
3117 dos_filetime_timespec(&atime_ts);
3120 create_time = convert_timespec_to_time_t(create_time_ts);
3121 mtime = convert_timespec_to_time_t(mtime_ts);
3122 atime = convert_timespec_to_time_t(atime_ts);
3124 /* NT expects the name to be in an exact form of the *full*
3125 filename. See the trans2 torture test */
3126 if (strequal(base_name,".")) {
3127 pstrcpy(dos_fname, "\\");
3129 pstr_sprintf(dos_fname, "\\%s", fname);
3130 string_replace(dos_fname, '/', '\\');
3133 switch (info_level) {
3134 case SMB_INFO_STANDARD:
3135 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3137 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3138 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3139 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3140 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3141 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3142 SSVAL(pdata,l1_attrFile,mode);
3145 case SMB_INFO_QUERY_EA_SIZE:
3147 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3148 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3150 srv_put_dos_date2(pdata,0,create_time);
3151 srv_put_dos_date2(pdata,4,atime);
3152 srv_put_dos_date2(pdata,8,mtime); /* write time */
3153 SIVAL(pdata,12,(uint32)file_size);
3154 SIVAL(pdata,16,(uint32)allocation_size);
3155 SSVAL(pdata,20,mode);
3156 SIVAL(pdata,22,ea_size);
3160 case SMB_INFO_IS_NAME_VALID:
3161 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3162 if (tran_call == TRANSACT2_QFILEINFO) {
3163 /* os/2 needs this ? really ?*/
3164 return ERROR_DOS(ERRDOS,ERRbadfunc);
3170 case SMB_INFO_QUERY_EAS_FROM_LIST:
3172 size_t total_ea_len = 0;
3173 struct ea_list *ea_file_list = NULL;
3175 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3177 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3178 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3180 if (!ea_list || (total_ea_len > data_size)) {
3181 talloc_destroy(data_ctx);
3183 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3187 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3188 talloc_destroy(data_ctx);
3192 case SMB_INFO_QUERY_ALL_EAS:
3194 /* We have data_size bytes to put EA's into. */
3195 size_t total_ea_len = 0;
3197 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3199 data_ctx = talloc_init("ea_ctx");
3201 return ERROR_NT(NT_STATUS_NO_MEMORY);
3204 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3205 if (!ea_list || (total_ea_len > data_size)) {
3206 talloc_destroy(data_ctx);
3208 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3212 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3213 talloc_destroy(data_ctx);
3217 case SMB_FILE_BASIC_INFORMATION:
3218 case SMB_QUERY_FILE_BASIC_INFO:
3220 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3221 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3222 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3224 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3228 put_long_date_timespec(pdata,create_time_ts);
3229 put_long_date_timespec(pdata+8,atime_ts);
3230 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3231 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3232 SIVAL(pdata,32,mode);
3234 DEBUG(5,("SMB_QFBI - "));
3235 DEBUG(5,("create: %s ", ctime(&create_time)));
3236 DEBUG(5,("access: %s ", ctime(&atime)));
3237 DEBUG(5,("write: %s ", ctime(&mtime)));
3238 DEBUG(5,("change: %s ", ctime(&mtime)));
3239 DEBUG(5,("mode: %x\n", mode));
3242 case SMB_FILE_STANDARD_INFORMATION:
3243 case SMB_QUERY_FILE_STANDARD_INFO:
3245 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3247 SOFF_T(pdata,0,allocation_size);
3248 SOFF_T(pdata,8,file_size);
3249 SIVAL(pdata,16,nlink);
3250 SCVAL(pdata,20,delete_pending?1:0);
3251 SCVAL(pdata,21,(mode&aDIR)?1:0);
3252 SSVAL(pdata,22,0); /* Padding. */
3255 case SMB_FILE_EA_INFORMATION:
3256 case SMB_QUERY_FILE_EA_INFO:
3258 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3259 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3261 SIVAL(pdata,0,ea_size);
3265 /* Get the 8.3 name - used if NT SMB was negotiated. */
3266 case SMB_QUERY_FILE_ALT_NAME_INFO:
3267 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3271 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3272 pstrcpy(short_name,base_name);
3273 /* Mangle if not already 8.3 */
3274 if(!mangle_is_8_3(short_name, True, conn->params)) {
3275 mangle_map(short_name,True,True,conn->params);
3277 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3278 data_size = 4 + len;
3283 case SMB_QUERY_FILE_NAME_INFO:
3285 this must be *exactly* right for ACLs on mapped drives to work
3287 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3288 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3289 data_size = 4 + len;
3293 case SMB_FILE_ALLOCATION_INFORMATION:
3294 case SMB_QUERY_FILE_ALLOCATION_INFO:
3295 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3297 SOFF_T(pdata,0,allocation_size);
3300 case SMB_FILE_END_OF_FILE_INFORMATION:
3301 case SMB_QUERY_FILE_END_OF_FILEINFO:
3302 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3304 SOFF_T(pdata,0,file_size);
3307 case SMB_QUERY_FILE_ALL_INFO:
3308 case SMB_FILE_ALL_INFORMATION:
3310 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3311 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3312 put_long_date_timespec(pdata,create_time_ts);
3313 put_long_date_timespec(pdata+8,atime_ts);
3314 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3315 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3316 SIVAL(pdata,32,mode);
3317 SIVAL(pdata,36,0); /* padding. */
3319 SOFF_T(pdata,0,allocation_size);
3320 SOFF_T(pdata,8,file_size);
3321 SIVAL(pdata,16,nlink);
3322 SCVAL(pdata,20,delete_pending);
3323 SCVAL(pdata,21,(mode&aDIR)?1:0);
3326 SIVAL(pdata,0,ea_size);
3327 pdata += 4; /* EA info */
3328 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3331 data_size = PTR_DIFF(pdata,(*ppdata));
3334 case SMB_FILE_INTERNAL_INFORMATION:
3335 /* This should be an index number - looks like
3338 I think this causes us to fail the IFSKIT
3339 BasicFileInformationTest. -tpot */
3341 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3342 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3343 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3347 case SMB_FILE_ACCESS_INFORMATION:
3348 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3349 SIVAL(pdata,0,access_mask);
3353 case SMB_FILE_NAME_INFORMATION:
3354 /* Pathname with leading '\'. */
3357 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3358 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3359 SIVAL(pdata,0,byte_len);
3360 data_size = 4 + byte_len;
3364 case SMB_FILE_DISPOSITION_INFORMATION:
3365 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3367 SCVAL(pdata,0,delete_pending);
3370 case SMB_FILE_POSITION_INFORMATION:
3371 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3373 SOFF_T(pdata,0,pos);
3376 case SMB_FILE_MODE_INFORMATION:
3377 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3378 SIVAL(pdata,0,mode);
3382 case SMB_FILE_ALIGNMENT_INFORMATION:
3383 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3384 SIVAL(pdata,0,0); /* No alignment needed. */
3390 * NT4 server just returns "invalid query" to this - if we try to answer
3391 * it then NTws gets a BSOD! (tridge).
3392 * W2K seems to want this. JRA.
3394 case SMB_QUERY_FILE_STREAM_INFO:
3396 case SMB_FILE_STREAM_INFORMATION:
3397 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3401 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3402 SIVAL(pdata,0,0); /* ??? */
3403 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3404 SOFF_T(pdata,8,file_size);
3405 SIVAL(pdata,16,allocation_size);
3406 SIVAL(pdata,20,0); /* ??? */
3407 data_size = 24 + byte_len;
3411 case SMB_QUERY_COMPRESSION_INFO:
3412 case SMB_FILE_COMPRESSION_INFORMATION:
3413 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3414 SOFF_T(pdata,0,file_size);
3415 SIVAL(pdata,8,0); /* ??? */
3416 SIVAL(pdata,12,0); /* ??? */
3420 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3421 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3422 put_long_date_timespec(pdata,create_time_ts);
3423 put_long_date_timespec(pdata+8,atime_ts);
3424 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3425 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3426 SIVAL(pdata,32,allocation_size);
3427 SOFF_T(pdata,40,file_size);
3428 SIVAL(pdata,48,mode);
3429 SIVAL(pdata,52,0); /* ??? */
3433 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3434 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3435 SIVAL(pdata,0,mode);
3441 * CIFS UNIX Extensions.
3444 case SMB_QUERY_FILE_UNIX_BASIC:
3446 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3447 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3449 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3452 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3455 put_long_date_timespec(pdata,get_ctimespec(&sbuf)); /* Creation Time 64 Bit */
3456 put_long_date_timespec(pdata+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
3457 put_long_date_timespec(pdata+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
3460 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3464 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3468 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3471 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3475 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3479 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3482 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3486 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3489 data_size = PTR_DIFF(pdata,(*ppdata));
3493 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3495 for (i=0; i<100; i++)
3496 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3502 case SMB_QUERY_FILE_UNIX_LINK:
3506 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3508 if(!S_ISLNK(sbuf.st_mode))
3509 return(UNIXERROR(ERRSRV,ERRbadlink));
3511 return(UNIXERROR(ERRDOS,ERRbadlink));
3513 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3515 return(UNIXERROR(ERRDOS,ERRnoaccess));
3517 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3519 data_size = PTR_DIFF(pdata,(*ppdata));
3524 #if defined(HAVE_POSIX_ACLS)
3525 case SMB_QUERY_POSIX_ACL:
3527 SMB_ACL_T file_acl = NULL;
3528 SMB_ACL_T def_acl = NULL;
3529 uint16 num_file_acls = 0;
3530 uint16 num_def_acls = 0;
3532 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3533 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3535 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3538 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3539 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3541 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3544 if (S_ISDIR(sbuf.st_mode)) {
3545 if (fsp && fsp->is_directory) {
3546 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3548 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3550 def_acl = free_empty_sys_acl(conn, def_acl);
3553 num_file_acls = count_acl_entries(conn, file_acl);
3554 num_def_acls = count_acl_entries(conn, def_acl);
3556 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3557 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3559 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3560 SMB_POSIX_ACL_HEADER_SIZE) ));
3562 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3565 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3567 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3570 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3571 SSVAL(pdata,2,num_file_acls);
3572 SSVAL(pdata,4,num_def_acls);
3573 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3575 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3578 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3580 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3582 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3584 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3587 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3589 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3593 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3596 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3598 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3604 case SMB_QUERY_POSIX_LOCK:
3606 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3608 SMB_BIG_UINT offset;
3610 enum brl_type lock_type;
3612 if (total_data != POSIX_LOCK_DATA_SIZE) {
3613 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3616 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3617 case POSIX_LOCK_TYPE_READ:
3618 lock_type = READ_LOCK;
3620 case POSIX_LOCK_TYPE_WRITE:
3621 lock_type = WRITE_LOCK;
3623 case POSIX_LOCK_TYPE_UNLOCK:
3625 /* There's no point in asking for an unlock... */
3626 talloc_destroy(data_ctx);
3627 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3630 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3631 #if defined(HAVE_LONGLONG)
3632 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3633 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3634 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3635 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3636 #else /* HAVE_LONGLONG */
3637 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3638 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3639 #endif /* HAVE_LONGLONG */
3641 status = query_lock(fsp,
3648 if (ERROR_WAS_LOCK_DENIED(status)) {
3649 /* Here we need to report who has it locked... */
3650 data_size = POSIX_LOCK_DATA_SIZE;
3652 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3653 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3654 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3655 #if defined(HAVE_LONGLONG)
3656 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3657 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3658 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3659 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3660 #else /* HAVE_LONGLONG */
3661 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3662 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3663 #endif /* HAVE_LONGLONG */
3665 } else if (NT_STATUS_IS_OK(status)) {
3666 /* For success we just return a copy of what we sent
3667 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3668 data_size = POSIX_LOCK_DATA_SIZE;
3669 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3670 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3672 return ERROR_NT(status);
3678 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3681 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3686 /****************************************************************************
3687 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3689 ****************************************************************************/
3691 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3693 BOOL bad_path_oldname = False;
3694 BOOL bad_path_newname = False;
3695 SMB_STRUCT_STAT sbuf1, sbuf2;
3696 pstring last_component_oldname;
3697 pstring last_component_newname;
3698 NTSTATUS status = NT_STATUS_OK;
3704 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3705 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3708 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3709 if (bad_path_oldname) {
3710 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3713 /* Quick check for "." and ".." */
3714 if (last_component_oldname[0] == '.') {
3715 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3716 return NT_STATUS_OBJECT_NAME_INVALID;
3720 /* source must already exist. */
3721 if (!VALID_STAT(sbuf1)) {
3722 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3725 if (!check_name(oldname,conn)) {
3726 return NT_STATUS_ACCESS_DENIED;
3729 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3730 if (bad_path_newname) {
3731 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3734 /* Quick check for "." and ".." */
3735 if (last_component_newname[0] == '.') {
3736 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3737 return NT_STATUS_OBJECT_NAME_INVALID;
3741 /* Disallow if newname already exists. */
3742 if (VALID_STAT(sbuf2)) {
3743 return NT_STATUS_OBJECT_NAME_COLLISION;
3746 if (!check_name(newname,conn)) {
3747 return NT_STATUS_ACCESS_DENIED;
3750 /* No links from a directory. */
3751 if (S_ISDIR(sbuf1.st_mode)) {
3752 return NT_STATUS_FILE_IS_A_DIRECTORY;
3755 /* Ensure this is within the share. */
3756 if (!reduce_name(conn, oldname) != 0)
3757 return NT_STATUS_ACCESS_DENIED;
3759 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3761 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3762 status = map_nt_error_from_unix(errno);
3763 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3764 nt_errstr(status), newname, oldname));
3770 /****************************************************************************
3771 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3772 ****************************************************************************/
3774 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3775 unsigned int tran_call,
3776 char **pparams, int total_params, char **ppdata, int total_data,
3777 unsigned int max_data_bytes)
3779 char *params = *pparams;
3780 char *pdata = *ppdata;
3785 SMB_STRUCT_STAT sbuf;
3788 BOOL bad_path = False;
3789 files_struct *fsp = NULL;
3790 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3791 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3792 mode_t unixmode = 0;
3793 NTSTATUS status = NT_STATUS_OK;
3796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3801 if (tran_call == TRANSACT2_SETFILEINFO) {
3802 if (total_params < 4) {
3803 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3806 fsp = file_fsp(params,0);
3807 info_level = SVAL(params,2);
3809 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3811 * This is actually a SETFILEINFO on a directory
3812 * handle (returned from an NT SMB). NT5.0 seems
3813 * to do this call. JRA.
3815 pstrcpy(fname, fsp->fsp_name);
3816 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3817 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3818 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3820 } else if (fsp && fsp->print_file) {
3822 * Doing a DELETE_ON_CLOSE should cancel a print job.
3824 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3825 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3827 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3830 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
3833 return (UNIXERROR(ERRDOS,ERRbadpath));
3836 * Original code - this is an open file.
3838 CHECK_FSP(fsp,conn);
3840 pstrcpy(fname, fsp->fsp_name);
3843 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3844 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3845 return(UNIXERROR(ERRDOS,ERRbadfid));
3850 if (total_params < 7) {
3851 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3854 info_level = SVAL(params,0);
3855 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3856 if (!NT_STATUS_IS_OK(status)) {
3857 return ERROR_NT(status);
3859 unix_convert(fname,conn,0,&bad_path,&sbuf);
3861 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3865 * For CIFS UNIX extensions the target name may not exist.
3868 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3869 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3870 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3873 if(!check_name(fname, conn)) {
3874 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3879 if (!CAN_WRITE(conn))
3880 return ERROR_DOS(ERRSRV,ERRaccess);
3882 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3883 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3886 if (VALID_STAT(sbuf))
3887 unixmode = sbuf.st_mode;
3889 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3890 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3892 /* Realloc the parameter size */
3893 *pparams = (char *)SMB_REALLOC(*pparams,2);
3894 if (*pparams == NULL) {
3895 return ERROR_NT(NT_STATUS_NO_MEMORY);
3901 if (fsp && fsp->pending_modtime) {
3902 /* the pending modtime overrides the current modtime */
3903 sbuf.st_mtime = fsp->pending_modtime;
3906 size = get_file_size(sbuf);
3907 tvs.modtime = sbuf.st_mtime;
3908 tvs.actime = sbuf.st_atime;
3909 dosmode = dos_mode(conn,fname,&sbuf);
3910 unixmode = sbuf.st_mode;
3912 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3913 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3915 switch (info_level) {
3916 case SMB_INFO_STANDARD:
3918 if (total_data < 12) {
3919 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3923 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3925 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3929 case SMB_INFO_SET_EA:
3931 struct ea_list *ea_list = NULL;
3932 TALLOC_CTX *ctx = NULL;
3934 if (total_data < 10) {
3936 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3937 length. They seem to have no effect. Bug #3212. JRA */
3939 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3940 /* We're done. We only get EA info in this call. */
3942 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
3946 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3949 if (IVAL(pdata,0) > total_data) {
3950 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3951 IVAL(pdata,0), (unsigned int)total_data));
3952 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3955 ctx = talloc_init("SMB_INFO_SET_EA");
3957 return ERROR_NT(NT_STATUS_NO_MEMORY);
3959 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3961 talloc_destroy(ctx);
3962 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3964 status = set_ea(conn, fsp, fname, ea_list);
3965 talloc_destroy(ctx);
3967 if (!NT_STATUS_IS_OK(status)) {
3968 return ERROR_NT(status);
3971 /* We're done. We only get EA info in this call. */
3973 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
3978 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3979 /* XXXX um, i don't think this is right.
3980 it's also not in the cifs6.txt spec.
3982 case SMB_INFO_QUERY_EAS_FROM_LIST:
3983 if (total_data < 28)
3984 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3986 tvs.actime = make_unix_date2(pdata+8);
3987 tvs.modtime = make_unix_date2(pdata+12);
3988 size = IVAL(pdata,16);
3989 dosmode = IVAL(pdata,24);
3992 /* XXXX nor this. not in cifs6.txt, either. */
3993 case SMB_INFO_QUERY_ALL_EAS:
3994 if (total_data < 28)
3995 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3997 tvs.actime = make_unix_date2(pdata+8);
3998 tvs.modtime = make_unix_date2(pdata+12);
3999 size = IVAL(pdata,16);
4000 dosmode = IVAL(pdata,24);
4004 case SMB_SET_FILE_BASIC_INFO:
4005 case SMB_FILE_BASIC_INFORMATION:
4007 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4009 time_t changed_time;
4011 if (total_data < 36) {
4012 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4015 /* Ignore create time at offset pdata. */
4018 tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
4020 write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
4021 changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
4023 tvs.modtime = MIN(write_time, changed_time);
4025 if (write_time > tvs.modtime && write_time != (time_t)-1) {
4026 tvs.modtime = write_time;
4028 /* Prefer a defined time to an undefined one. */
4029 if (null_mtime(tvs.modtime)) {
4030 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
4034 dosmode = IVAL(pdata,32);
4038 case SMB_FILE_ALLOCATION_INFORMATION:
4039 case SMB_SET_FILE_ALLOCATION_INFO:
4042 SMB_BIG_UINT allocation_size;
4044 if (total_data < 8) {
4045 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4048 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4049 #ifdef LARGE_SMB_OFF_T
4050 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4051 #else /* LARGE_SMB_OFF_T */
4052 if (IVAL(pdata,4) != 0) {
4053 /* more than 32 bits? */
4054 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4056 #endif /* LARGE_SMB_OFF_T */
4057 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4058 fname, (double)allocation_size ));
4060 if (allocation_size) {
4061 allocation_size = smb_roundup(conn, allocation_size);
4064 if(allocation_size != get_file_size(sbuf)) {
4065 SMB_STRUCT_STAT new_sbuf;
4067 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4068 fname, (double)allocation_size ));
4071 files_struct *new_fsp = NULL;
4073 status = open_file_ntcreate(conn, fname, &sbuf,
4075 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4078 FILE_ATTRIBUTE_NORMAL,
4079 FORCE_OPLOCK_BREAK_TO_NONE,
4082 if (!NT_STATUS_IS_OK(status)) {
4083 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4084 /* We have re-scheduled this call. */
4087 return(UNIXERROR(ERRDOS,ERRnoaccess));
4089 ret = vfs_allocate_file_space(new_fsp, allocation_size);
4090 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4091 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4092 new_fsp->fnum, strerror(errno)));
4095 close_file(new_fsp,NORMAL_CLOSE);
4097 ret = vfs_allocate_file_space(fsp, allocation_size);
4098 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4099 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4100 fsp->fnum, strerror(errno)));
4105 return ERROR_NT(NT_STATUS_DISK_FULL);
4107 /* Allocate can truncate size... */
4108 size = get_file_size(new_sbuf);
4114 case SMB_FILE_END_OF_FILE_INFORMATION:
4115 case SMB_SET_FILE_END_OF_FILE_INFO:
4117 if (total_data < 8) {
4118 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4121 size = IVAL(pdata,0);
4122 #ifdef LARGE_SMB_OFF_T
4123 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4124 #else /* LARGE_SMB_OFF_T */
4125 if (IVAL(pdata,4) != 0) {
4126 /* more than 32 bits? */
4127 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4129 #endif /* LARGE_SMB_OFF_T */
4130 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4134 case SMB_FILE_DISPOSITION_INFORMATION:
4135 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4137 BOOL delete_on_close;
4139 if (total_data < 1) {
4140 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4143 delete_on_close = (CVAL(pdata,0) ? True : False);
4145 /* Just ignore this set on a path. */
4146 if (tran_call != TRANSACT2_SETFILEINFO)
4150 return(UNIXERROR(ERRDOS,ERRbadfid));
4152 status = can_set_delete_on_close(fsp, delete_on_close,
4155 if (!NT_STATUS_IS_OK(status)) {
4156 return ERROR_NT(status);
4159 /* The set is across all open files on this dev/inode pair. */
4160 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4161 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4165 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4169 case SMB_FILE_POSITION_INFORMATION:
4171 SMB_BIG_UINT position_information;
4173 if (total_data < 8) {
4174 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4177 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4178 #ifdef LARGE_SMB_OFF_T
4179 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4180 #else /* LARGE_SMB_OFF_T */
4181 if (IVAL(pdata,4) != 0) {
4182 /* more than 32 bits? */
4183 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4185 #endif /* LARGE_SMB_OFF_T */
4186 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4187 fname, (double)position_information ));
4189 fsp->fh->position_information = position_information;
4192 /* We're done. We only get position info in this call. */
4194 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4198 /* From tridge Samba4 :
4199 * MODE_INFORMATION in setfileinfo (I have no
4200 * idea what "mode information" on a file is - it takes a value of 0,
4201 * 2, 4 or 6. What could it be?).
4204 case SMB_FILE_MODE_INFORMATION:
4208 if (total_data < 4) {
4209 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4211 mode = IVAL(pdata,0);
4212 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4213 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4216 /* We're done. We only get mode info in this call. */
4218 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4223 * CIFS UNIX extensions.
4226 case SMB_SET_FILE_UNIX_BASIC:
4228 uint32 raw_unixmode;
4230 if (total_data < 100) {
4231 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4234 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4235 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4236 size=IVAL(pdata,0); /* first 8 Bytes are size */
4237 #ifdef LARGE_SMB_OFF_T
4238 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4239 #else /* LARGE_SMB_OFF_T */
4240 if (IVAL(pdata,4) != 0) {
4241 /* more than 32 bits? */
4242 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4244 #endif /* LARGE_SMB_OFF_T */
4246 pdata+=24; /* ctime & st_blocks are not changed */
4247 tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */
4248 tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */
4250 set_owner = (uid_t)IVAL(pdata,0);
4252 set_grp = (gid_t)IVAL(pdata,0);
4254 raw_unixmode = IVAL(pdata,28);
4255 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4256 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4258 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4259 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4260 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4262 if (!VALID_STAT(sbuf)) {
4265 * The only valid use of this is to create character and block
4266 * devices, and named pipes. This is deprecated (IMHO) and
4267 * a new info level should be used for mknod. JRA.
4270 uint32 file_type = IVAL(pdata,0);
4271 #if defined(HAVE_MAKEDEV)
4272 uint32 dev_major = IVAL(pdata,4);
4273 uint32 dev_minor = IVAL(pdata,12);
4276 uid_t myuid = geteuid();
4277 gid_t mygid = getegid();
4278 SMB_DEV_T dev = (SMB_DEV_T)0;
4280 if (tran_call == TRANSACT2_SETFILEINFO)
4281 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4283 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4284 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4287 #if defined(HAVE_MAKEDEV)
4288 dev = makedev(dev_major, dev_minor);
4291 /* We can only create as the owner/group we are. */
4293 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4294 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4295 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4296 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4298 switch (file_type) {
4299 #if defined(S_IFIFO)
4300 case UNIX_TYPE_FIFO:
4301 unixmode |= S_IFIFO;
4304 #if defined(S_IFSOCK)
4305 case UNIX_TYPE_SOCKET:
4306 unixmode |= S_IFSOCK;
4309 #if defined(S_IFCHR)
4310 case UNIX_TYPE_CHARDEV:
4311 unixmode |= S_IFCHR;
4314 #if defined(S_IFBLK)
4315 case UNIX_TYPE_BLKDEV:
4316 unixmode |= S_IFBLK;
4320 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4323 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4324 0%o for file %s\n", (double)dev, unixmode, fname ));
4326 /* Ok - do the mknod. */
4327 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4328 return(UNIXERROR(ERRDOS,ERRnoaccess));
4330 if (lp_inherit_perms(SNUM(conn))) {
4332 conn, parent_dirname(fname),
4337 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4342 * Deal with the UNIX specific mode set.
4345 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4346 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4347 (unsigned int)unixmode, fname ));
4348 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4349 return(UNIXERROR(ERRDOS,ERRnoaccess));
4353 * Deal with the UNIX specific uid set.
4356 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4357 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4358 (unsigned int)set_owner, fname ));
4359 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4360 return(UNIXERROR(ERRDOS,ERRnoaccess));
4364 * Deal with the UNIX specific gid set.
4367 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4368 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4369 (unsigned int)set_owner, fname ));
4370 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4371 return(UNIXERROR(ERRDOS,ERRnoaccess));
4376 case SMB_SET_FILE_UNIX_LINK:
4378 pstring link_target;
4379 char *newname = fname;
4381 /* Set a symbolic link. */
4382 /* Don't allow this if follow links is false. */
4384 if (total_data == 0) {
4385 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4388 if (!lp_symlinks(SNUM(conn)))
4389 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4391 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4393 /* !widelinks forces the target path to be within the share. */
4394 /* This means we can interpret the target as a pathname. */
4395 if (!lp_widelinks(SNUM(conn))) {
4397 char *last_dirp = NULL;
4399 unix_format(link_target);
4400 if (*link_target == '/') {
4401 /* No absolute paths allowed. */
4402 return(UNIXERROR(ERRDOS,ERRnoaccess));
4404 pstrcpy(rel_name, newname);
4405 last_dirp = strrchr_m(rel_name, '/');
4407 last_dirp[1] = '\0';
4409 pstrcpy(rel_name, "./");
4411 pstrcat(rel_name, link_target);
4413 if (!check_name(rel_name, conn)) {
4414 return(UNIXERROR(ERRDOS,ERRnoaccess));
4418 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4419 fname, link_target ));
4421 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4422 return(UNIXERROR(ERRDOS,ERRnoaccess));
4424 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4428 case SMB_SET_FILE_UNIX_HLINK:
4431 char *newname = fname;
4433 /* Set a hard link. */
4434 if (total_data == 0) {
4435 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4438 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4439 if (!NT_STATUS_IS_OK(status)) {
4440 return ERROR_NT(status);
4443 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4446 status = hardlink_internals(conn, oldname, newname);
4447 if (!NT_STATUS_IS_OK(status)) {
4448 return ERROR_NT(status);
4452 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4456 case SMB_FILE_RENAME_INFORMATION:
4459 /* uint32 root_fid; */ /* Not used */
4465 if (total_data < 13) {
4466 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4469 overwrite = (CVAL(pdata,0) ? True : False);
4470 /* root_fid = IVAL(pdata,4); */
4471 len = IVAL(pdata,8);
4473 if (len > (total_data - 12) || (len == 0)) {
4474 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4477 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4478 if (!NT_STATUS_IS_OK(status)) {
4479 return ERROR_NT(status);
4482 /* Check the new name has no '/' characters. */
4483 if (strchr_m(newname, '/'))
4484 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4486 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4488 /* Create the base directory. */
4489 pstrcpy(base_name, fname);
4490 p = strrchr_m(base_name, '/');
4493 /* Append the new name. */
4494 pstrcat(base_name, "/");
4495 pstrcat(base_name, newname);
4498 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4499 fsp->fnum, fsp->fsp_name, base_name ));
4500 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4502 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4504 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4506 if (!NT_STATUS_IS_OK(status)) {
4507 return ERROR_NT(status);
4509 process_pending_change_notify_queue((time_t)0);
4511 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4515 #if defined(HAVE_POSIX_ACLS)
4516 case SMB_SET_POSIX_ACL:
4518 uint16 posix_acl_version;
4519 uint16 num_file_acls;
4520 uint16 num_def_acls;
4521 BOOL valid_file_acls = True;
4522 BOOL valid_def_acls = True;
4524 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4525 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4527 posix_acl_version = SVAL(pdata,0);
4528 num_file_acls = SVAL(pdata,2);
4529 num_def_acls = SVAL(pdata,4);
4531 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4532 valid_file_acls = False;
4536 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4537 valid_def_acls = False;
4541 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4542 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4545 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4546 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4547 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4550 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4551 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4552 return(UNIXERROR(ERRDOS,ERRnoaccess));
4555 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4556 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4557 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4558 return(UNIXERROR(ERRDOS,ERRnoaccess));
4562 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4567 case SMB_SET_POSIX_LOCK:
4570 SMB_BIG_UINT offset;
4572 BOOL blocking_lock = False;
4573 enum brl_type lock_type;
4575 if (fsp == NULL || fsp->fh->fd == -1) {
4576 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4579 if (total_data != POSIX_LOCK_DATA_SIZE) {
4580 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4583 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4584 case POSIX_LOCK_TYPE_READ:
4585 lock_type = READ_LOCK;
4587 case POSIX_LOCK_TYPE_WRITE:
4588 /* Return the right POSIX-mappable error code for files opened read-only. */
4589 if (!fsp->can_write) {
4590 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4592 lock_type = WRITE_LOCK;
4594 case POSIX_LOCK_TYPE_UNLOCK:
4595 lock_type = UNLOCK_LOCK;
4598 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4601 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4602 blocking_lock = False;
4603 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4604 blocking_lock = True;
4606 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4609 if (!lp_blocking_locks(SNUM(conn))) {
4610 blocking_lock = False;
4613 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4614 #if defined(HAVE_LONGLONG)
4615 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4616 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4617 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4618 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4619 #else /* HAVE_LONGLONG */
4620 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4621 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4622 #endif /* HAVE_LONGLONG */
4624 if (lock_type == UNLOCK_LOCK) {
4625 status = do_unlock(fsp,
4631 struct byte_range_lock *br_lck = do_lock(fsp,
4640 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4642 * A blocking lock was requested. Package up
4643 * this smb into a queued request and push it
4644 * onto the blocking lock queue.
4646 if(push_blocking_lock_request(br_lck,
4649 -1, /* infinite timeout. */
4656 TALLOC_FREE(br_lck);
4660 TALLOC_FREE(br_lck);
4663 if (!NT_STATUS_IS_OK(status)) {
4664 return ERROR_NT(status);
4668 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4673 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4676 /* get some defaults (no modifications) if any info is zero or -1. */
4677 if (null_mtime(tvs.actime)) {
4678 tvs.actime = sbuf.st_atime;
4681 if (null_mtime(tvs.modtime)) {
4682 tvs.modtime = sbuf.st_mtime;
4685 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4686 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4687 DEBUG(6,("size: %.0f ", (double)size));
4690 if (S_ISDIR(sbuf.st_mode))
4696 DEBUG(6,("dosmode: %x\n" , dosmode));
4698 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4699 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4700 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4701 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4704 * Only do this test if we are not explicitly
4705 * changing the size of a file.
4708 size = get_file_size(sbuf);
4712 * Try and set the times, size and mode of this file -
4713 * if they are different from the current values
4716 /* check the mode isn't different, before changing it */
4717 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4719 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4721 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4722 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4723 return(UNIXERROR(ERRDOS,ERRnoaccess));
4728 if (size != get_file_size(sbuf)) {
4732 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4733 fname, (double)size ));
4736 files_struct *new_fsp = NULL;
4738 status = open_file_ntcreate(conn, fname, &sbuf,
4740 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4743 FILE_ATTRIBUTE_NORMAL,
4744 FORCE_OPLOCK_BREAK_TO_NONE,
4747 if (!NT_STATUS_IS_OK(status)) {
4748 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4749 /* We have re-scheduled this call. */
4752 return(UNIXERROR(ERRDOS,ERRnoaccess));
4754 ret = vfs_set_filelen(new_fsp, size);
4755 close_file(new_fsp,NORMAL_CLOSE);
4757 ret = vfs_set_filelen(fsp, size);
4761 return (UNIXERROR(ERRHRD,ERRdiskfull));
4766 * Finally the times.
4768 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4771 * This was a setfileinfo on an open file.
4772 * NT does this a lot. We also need to
4773 * set the time here, as it can be read by
4774 * FindFirst/FindNext and with the patch for bug #2045
4775 * in smbd/fileio.c it ensures that this timestamp is
4776 * kept sticky even after a write. We save the request
4777 * away and will set it on file close and after a write. JRA.
4780 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4781 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4782 fsp_set_pending_modtime(fsp, tvs.modtime);
4786 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4788 if(file_utime(conn, fname, &tvs)!=0) {
4789 return(UNIXERROR(ERRDOS,ERRnoaccess));
4794 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4799 /****************************************************************************
4800 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4801 ****************************************************************************/
4803 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4804 char **pparams, int total_params, char **ppdata, int total_data,
4805 unsigned int max_data_bytes)
4807 char *params = *pparams;
4808 char *pdata = *ppdata;
4810 SMB_STRUCT_STAT sbuf;
4811 BOOL bad_path = False;
4812 NTSTATUS status = NT_STATUS_OK;
4813 struct ea_list *ea_list = NULL;
4815 if (!CAN_WRITE(conn))
4816 return ERROR_DOS(ERRSRV,ERRaccess);
4818 if (total_params < 5) {
4819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4822 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 return ERROR_NT(status);
4827 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4829 unix_convert(directory,conn,0,&bad_path,&sbuf);
4831 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4834 /* Any data in this call is an EA list. */
4835 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4836 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4840 * OS/2 workplace shell seems to send SET_EA requests of "null"
4841 * length (4 bytes containing IVAL 4).
4842 * They seem to have no effect. Bug #3212. JRA.
4845 if (total_data != 4) {
4846 if (total_data < 10) {
4847 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4850 if (IVAL(pdata,0) > total_data) {
4851 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4852 IVAL(pdata,0), (unsigned int)total_data));
4853 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4856 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
4859 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4861 } else if (IVAL(pdata,0) != 4) {
4862 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4865 if (!check_name(directory,conn)) {
4866 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4867 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,
4871 status = create_directory(conn, directory);
4873 if (!NT_STATUS_IS_OK(status)) {
4874 return ERROR_NT(status);
4877 /* Try and set any given EA. */
4879 status = set_ea(conn, NULL, directory, ea_list);
4880 if (!NT_STATUS_IS_OK(status)) {
4881 return ERROR_NT(status);
4885 /* Realloc the parameter and data sizes */
4886 *pparams = (char *)SMB_REALLOC(*pparams,2);
4887 if(*pparams == NULL) {
4888 return ERROR_NT(NT_STATUS_NO_MEMORY);
4894 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4899 /****************************************************************************
4900 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4901 We don't actually do this - we just send a null response.
4902 ****************************************************************************/
4904 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4905 char **pparams, int total_params, char **ppdata, int total_data,
4906 unsigned int max_data_bytes)
4908 static uint16 fnf_handle = 257;
4909 char *params = *pparams;
4912 if (total_params < 6) {
4913 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4916 info_level = SVAL(params,4);
4917 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4919 switch (info_level) {
4924 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4927 /* Realloc the parameter and data sizes */
4928 *pparams = (char *)SMB_REALLOC(*pparams,6);
4929 if (*pparams == NULL) {
4930 return ERROR_NT(NT_STATUS_NO_MEMORY);
4934 SSVAL(params,0,fnf_handle);
4935 SSVAL(params,2,0); /* No changes */
4936 SSVAL(params,4,0); /* No EA errors */
4943 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
4948 /****************************************************************************
4949 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4950 changes). Currently this does nothing.
4951 ****************************************************************************/
4953 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4954 char **pparams, int total_params, char **ppdata, int total_data,
4955 unsigned int max_data_bytes)
4957 char *params = *pparams;
4959 DEBUG(3,("call_trans2findnotifynext\n"));
4961 /* Realloc the parameter and data sizes */
4962 *pparams = (char *)SMB_REALLOC(*pparams,4);
4963 if (*pparams == NULL) {
4964 return ERROR_NT(NT_STATUS_NO_MEMORY);
4968 SSVAL(params,0,0); /* No changes */
4969 SSVAL(params,2,0); /* No EA errors */
4971 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
4976 /****************************************************************************
4977 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4978 ****************************************************************************/
4980 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4981 char **pparams, int total_params, char **ppdata, int total_data,
4982 unsigned int max_data_bytes)
4984 char *params = *pparams;
4987 int max_referral_level;
4989 DEBUG(10,("call_trans2getdfsreferral\n"));
4991 if (total_params < 3) {
4992 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4995 max_referral_level = SVAL(params,0);
4997 if(!lp_host_msdfs())
4998 return ERROR_DOS(ERRDOS,ERRbadfunc);
5000 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
5001 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
5002 return UNIXERROR(ERRDOS,ERRbadfile);
5004 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5005 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
5010 #define LMCAT_SPL 0x53
5011 #define LMFUNC_GETJOBID 0x60
5013 /****************************************************************************
5014 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5015 ****************************************************************************/
5017 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5018 char **pparams, int total_params, char **ppdata, int total_data,
5019 unsigned int max_data_bytes)
5021 char *pdata = *ppdata;
5022 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
5024 /* check for an invalid fid before proceeding */
5027 return(ERROR_DOS(ERRDOS,ERRbadfid));
5029 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5030 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5031 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5032 if (*ppdata == NULL) {
5033 return ERROR_NT(NT_STATUS_NO_MEMORY);
5037 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5038 CAN ACCEPT THIS IN UNICODE. JRA. */
5040 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
5041 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5042 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5043 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5046 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5047 return ERROR_DOS(ERRSRV,ERRerror);
5051 /****************************************************************************
5052 Reply to a SMBfindclose (stop trans2 directory search).
5053 ****************************************************************************/
5055 int reply_findclose(connection_struct *conn,
5056 char *inbuf,char *outbuf,int length,int bufsize)
5059 int dptr_num=SVALS(inbuf,smb_vwv0);
5060 START_PROFILE(SMBfindclose);
5062 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5064 dptr_close(&dptr_num);
5066 outsize = set_message(outbuf,0,0,False);
5068 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5070 END_PROFILE(SMBfindclose);
5074 /****************************************************************************
5075 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5076 ****************************************************************************/
5078 int reply_findnclose(connection_struct *conn,
5079 char *inbuf,char *outbuf,int length,int bufsize)
5083 START_PROFILE(SMBfindnclose);
5085 dptr_num = SVAL(inbuf,smb_vwv0);
5087 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5089 /* We never give out valid handles for a
5090 findnotifyfirst - so any dptr_num is ok here.
5093 outsize = set_message(outbuf,0,0,False);
5095 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5097 END_PROFILE(SMBfindnclose);
5101 int handle_trans2(connection_struct *conn,
5102 struct trans_state *state,
5103 char *inbuf, char *outbuf, int size, int bufsize)
5107 if (Protocol >= PROTOCOL_NT1) {
5108 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5111 /* Now we must call the relevant TRANS2 function */
5112 switch(state->call) {
5113 case TRANSACT2_OPEN:
5115 START_PROFILE_NESTED(Trans2_open);
5116 outsize = call_trans2open(
5117 conn, inbuf, outbuf, bufsize,
5118 &state->param, state->total_param,
5119 &state->data, state->total_data,
5120 state->max_data_return);
5121 END_PROFILE_NESTED(Trans2_open);
5125 case TRANSACT2_FINDFIRST:
5127 START_PROFILE_NESTED(Trans2_findfirst);
5128 outsize = call_trans2findfirst(
5129 conn, inbuf, outbuf, bufsize,
5130 &state->param, state->total_param,
5131 &state->data, state->total_data,
5132 state->max_data_return);
5133 END_PROFILE_NESTED(Trans2_findfirst);
5137 case TRANSACT2_FINDNEXT:
5139 START_PROFILE_NESTED(Trans2_findnext);
5140 outsize = call_trans2findnext(
5141 conn, inbuf, outbuf, size, bufsize,
5142 &state->param, state->total_param,
5143 &state->data, state->total_data,
5144 state->max_data_return);
5145 END_PROFILE_NESTED(Trans2_findnext);
5149 case TRANSACT2_QFSINFO:
5151 START_PROFILE_NESTED(Trans2_qfsinfo);
5152 outsize = call_trans2qfsinfo(
5153 conn, inbuf, outbuf, size, bufsize,
5154 &state->param, state->total_param,
5155 &state->data, state->total_data,
5156 state->max_data_return);
5157 END_PROFILE_NESTED(Trans2_qfsinfo);
5161 case TRANSACT2_SETFSINFO:
5163 START_PROFILE_NESTED(Trans2_setfsinfo);
5164 outsize = call_trans2setfsinfo(
5165 conn, inbuf, outbuf, size, bufsize,
5166 &state->param, state->total_param,
5167 &state->data, state->total_data,
5168 state->max_data_return);
5169 END_PROFILE_NESTED(Trans2_setfsinfo);
5173 case TRANSACT2_QPATHINFO:
5174 case TRANSACT2_QFILEINFO:
5176 START_PROFILE_NESTED(Trans2_qpathinfo);
5177 outsize = call_trans2qfilepathinfo(
5178 conn, inbuf, outbuf, size, bufsize, state->call,
5179 &state->param, state->total_param,
5180 &state->data, state->total_data,
5181 state->max_data_return);
5182 END_PROFILE_NESTED(Trans2_qpathinfo);
5186 case TRANSACT2_SETPATHINFO:
5187 case TRANSACT2_SETFILEINFO:
5189 START_PROFILE_NESTED(Trans2_setpathinfo);
5190 outsize = call_trans2setfilepathinfo(
5191 conn, inbuf, outbuf, size, bufsize, state->call,
5192 &state->param, state->total_param,
5193 &state->data, state->total_data,
5194 state->max_data_return);
5195 END_PROFILE_NESTED(Trans2_setpathinfo);
5199 case TRANSACT2_FINDNOTIFYFIRST:
5201 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5202 outsize = call_trans2findnotifyfirst(
5203 conn, inbuf, outbuf, size, bufsize,
5204 &state->param, state->total_param,
5205 &state->data, state->total_data,
5206 state->max_data_return);
5207 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5211 case TRANSACT2_FINDNOTIFYNEXT:
5213 START_PROFILE_NESTED(Trans2_findnotifynext);
5214 outsize = call_trans2findnotifynext(
5215 conn, inbuf, outbuf, size, bufsize,
5216 &state->param, state->total_param,
5217 &state->data, state->total_data,
5218 state->max_data_return);
5219 END_PROFILE_NESTED(Trans2_findnotifynext);
5223 case TRANSACT2_MKDIR:
5225 START_PROFILE_NESTED(Trans2_mkdir);
5226 outsize = call_trans2mkdir(
5227 conn, inbuf, outbuf, size, bufsize,
5228 &state->param, state->total_param,
5229 &state->data, state->total_data,
5230 state->max_data_return);
5231 END_PROFILE_NESTED(Trans2_mkdir);
5235 case TRANSACT2_GET_DFS_REFERRAL:
5237 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5238 outsize = call_trans2getdfsreferral(
5239 conn, inbuf, outbuf, size, bufsize,
5240 &state->param, state->total_param,
5241 &state->data, state->total_data,
5242 state->max_data_return);
5243 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5247 case TRANSACT2_IOCTL:
5249 START_PROFILE_NESTED(Trans2_ioctl);
5250 outsize = call_trans2ioctl(
5251 conn, inbuf, outbuf, size, bufsize,
5252 &state->param, state->total_param,
5253 &state->data, state->total_data,
5254 state->max_data_return);
5255 END_PROFILE_NESTED(Trans2_ioctl);
5260 /* Error in request */
5261 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5262 outsize = ERROR_DOS(ERRSRV,ERRerror);
5268 /****************************************************************************
5269 Reply to a SMBtrans2.
5270 ****************************************************************************/
5272 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5273 int size, int bufsize)
5276 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5277 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5278 unsigned int psoff = SVAL(inbuf, smb_psoff);
5279 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5280 unsigned int tran_call = SVAL(inbuf, smb_setup0);
5281 struct trans_state *state;
5284 START_PROFILE(SMBtrans2);
5286 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5287 if (!NT_STATUS_IS_OK(result)) {
5288 DEBUG(2, ("Got invalid trans2 request: %s\n",
5289 nt_errstr(result)));
5290 END_PROFILE(SMBtrans2);
5291 return ERROR_NT(result);
5294 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5295 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5296 END_PROFILE(SMBtrans2);
5297 return ERROR_DOS(ERRSRV,ERRaccess);
5300 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
5301 DEBUG(0, ("talloc failed\n"));
5302 END_PROFILE(SMBtrans2);
5303 return ERROR_NT(NT_STATUS_NO_MEMORY);
5306 state->cmd = SMBtrans2;
5308 state->mid = SVAL(inbuf, smb_mid);
5309 state->vuid = SVAL(inbuf, smb_uid);
5310 state->setup_count = SVAL(inbuf, smb_suwcnt);
5311 state->setup = NULL;
5312 state->total_param = SVAL(inbuf, smb_tpscnt);
5313 state->param = NULL;
5314 state->total_data = SVAL(inbuf, smb_tdscnt);
5316 state->max_param_return = SVAL(inbuf, smb_mprcnt);
5317 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
5318 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5319 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5320 state->one_way = BITSETW(inbuf+smb_vwv5,1);
5322 state->call = tran_call;
5324 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5325 is so as a sanity check */
5326 if (state->setup_count != 1) {
5328 * Need to have rc=0 for ioctl to get job id for OS/2.
5329 * Network printing will fail if function is not successful.
5330 * Similar function in reply.c will be used if protocol
5331 * is LANMAN1.0 instead of LM1.2X002.
5332 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5333 * outbuf doesn't have to be set(only job id is used).
5335 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5336 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5337 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5338 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5340 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5341 DEBUG(2,("Transaction is %d\n",tran_call));
5343 END_PROFILE(SMBtrans2);
5344 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5348 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5351 if (state->total_data) {
5352 /* Can't use talloc here, the core routines do realloc on the
5353 * params and data. */
5354 state->data = (char *)SMB_MALLOC(state->total_data);
5355 if (state->data == NULL) {
5356 DEBUG(0,("reply_trans2: data malloc fail for %u "
5357 "bytes !\n", (unsigned int)state->total_data));
5359 END_PROFILE(SMBtrans2);
5360 return(ERROR_DOS(ERRDOS,ERRnomem));
5362 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5364 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5365 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5368 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5371 if (state->total_param) {
5372 /* Can't use talloc here, the core routines do realloc on the
5373 * params and data. */
5374 state->param = (char *)SMB_MALLOC(state->total_param);
5375 if (state->param == NULL) {
5376 DEBUG(0,("reply_trans: param malloc fail for %u "
5377 "bytes !\n", (unsigned int)state->total_param));
5378 SAFE_FREE(state->data);
5380 END_PROFILE(SMBtrans2);
5381 return(ERROR_DOS(ERRDOS,ERRnomem));
5383 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5385 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5386 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5389 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5392 state->received_data = dscnt;
5393 state->received_param = pscnt;
5395 if ((state->received_param == state->total_param) &&
5396 (state->received_data == state->total_data)) {
5398 outsize = handle_trans2(conn, state, inbuf, outbuf,
5400 SAFE_FREE(state->data);
5401 SAFE_FREE(state->param);
5403 END_PROFILE(SMBtrans2);
5407 DLIST_ADD(conn->pending_trans, state);
5409 /* We need to send an interim response then receive the rest
5410 of the parameter/data bytes */
5411 outsize = set_message(outbuf,0,0,False);
5413 END_PROFILE(SMBtrans2);
5418 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5419 SAFE_FREE(state->data);
5420 SAFE_FREE(state->param);
5422 END_PROFILE(SMBtrans2);
5423 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5427 /****************************************************************************
5428 Reply to a SMBtranss2
5429 ****************************************************************************/
5431 int reply_transs2(connection_struct *conn,
5432 char *inbuf,char *outbuf,int size,int bufsize)
5435 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5436 struct trans_state *state;
5438 START_PROFILE(SMBtranss2);
5442 for (state = conn->pending_trans; state != NULL;
5443 state = state->next) {
5444 if (state->mid == SVAL(inbuf,smb_mid)) {
5449 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5450 END_PROFILE(SMBtranss2);
5451 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5454 /* Revise state->total_param and state->total_data in case they have
5455 changed downwards */
5457 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5458 state->total_param = SVAL(inbuf, smb_tpscnt);
5459 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5460 state->total_data = SVAL(inbuf, smb_tdscnt);
5462 pcnt = SVAL(inbuf, smb_spscnt);
5463 poff = SVAL(inbuf, smb_spsoff);
5464 pdisp = SVAL(inbuf, smb_spsdisp);
5466 dcnt = SVAL(inbuf, smb_sdscnt);
5467 doff = SVAL(inbuf, smb_sdsoff);
5468 ddisp = SVAL(inbuf, smb_sdsdisp);
5470 state->received_param += pcnt;
5471 state->received_data += dcnt;
5473 if ((state->received_data > state->total_data) ||
5474 (state->received_param > state->total_param))
5478 if (pdisp+pcnt > state->total_param)
5480 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5482 if (pdisp > state->total_param)
5484 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5485 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5487 if (state->param + pdisp < state->param)
5490 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5495 if (ddisp+dcnt > state->total_data)
5497 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5499 if (ddisp > state->total_data)
5501 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5502 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5504 if (state->data + ddisp < state->data)
5507 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5511 if ((state->received_param < state->total_param) ||
5512 (state->received_data < state->total_data)) {
5513 END_PROFILE(SMBtranss2);
5517 /* construct_reply_common has done us the favor to pre-fill the
5518 * command field with SMBtranss2 which is wrong :-)
5520 SCVAL(outbuf,smb_com,SMBtrans2);
5522 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5524 DLIST_REMOVE(conn->pending_trans, state);
5525 SAFE_FREE(state->data);
5526 SAFE_FREE(state->param);
5530 END_PROFILE(SMBtranss2);
5531 return(ERROR_DOS(ERRSRV,ERRnosupport));
5534 END_PROFILE(SMBtranss2);
5539 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5540 DLIST_REMOVE(conn->pending_trans, state);
5541 SAFE_FREE(state->data);
5542 SAFE_FREE(state->param);
5544 END_PROFILE(SMBtranss2);
5545 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);