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;
755 struct ea_list *ea_list = NULL;
760 uint32 create_disposition;
761 uint32 create_options = 0;
764 * Ensure we have enough parameters to perform the operation.
767 if (total_params < 29) {
768 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
771 flags = SVAL(params, 0);
772 deny_mode = SVAL(params, 2);
773 open_attr = SVAL(params,6);
774 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
775 if (oplock_request) {
776 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
780 return_additional_info = BITSETW(params,0);
781 open_sattr = SVAL(params, 4);
782 open_time = make_unix_date3(params+8);
784 open_ofun = SVAL(params,12);
785 open_size = IVAL(params,14);
789 return(ERROR_DOS(ERRSRV,ERRaccess));
792 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
793 if (!NT_STATUS_IS_OK(status)) {
794 return ERROR_NT(status);
797 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
798 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
799 (unsigned int)open_ofun, open_size));
801 /* XXXX we need to handle passed times, sattr and flags */
803 status = unix_convert(conn, fname, False, NULL, &sbuf);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 if (!check_name(fname,conn)) {
809 return UNIXERROR(ERRDOS,ERRnoaccess);
812 if (open_ofun == 0) {
813 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
816 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
821 return ERROR_DOS(ERRDOS, ERRbadaccess);
824 /* Any data in this call is an EA list. */
825 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
826 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
829 if (total_data != 4) {
830 if (total_data < 10) {
831 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
834 if (IVAL(pdata,0) > total_data) {
835 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
836 IVAL(pdata,0), (unsigned int)total_data));
837 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
840 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
845 } else if (IVAL(pdata,0) != 4) {
846 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
849 status = open_file_ntcreate(conn,fname,&sbuf,
858 if (!NT_STATUS_IS_OK(status)) {
859 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
860 /* We have re-scheduled this call. */
863 return ERROR_NT(status);
866 size = get_file_size(sbuf);
867 fattr = dos_mode(conn,fname,&sbuf);
868 mtime = sbuf.st_mtime;
871 close_file(fsp,ERROR_CLOSE);
872 return(ERROR_DOS(ERRDOS,ERRnoaccess));
875 /* Save the requested allocation size. */
876 /* Allocate space for the file if a size hint is supplied */
877 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
878 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
879 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
880 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
881 if (fsp->is_directory) {
882 close_file(fsp,ERROR_CLOSE);
883 /* Can't set allocation size on a directory. */
884 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
886 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
887 close_file(fsp,ERROR_CLOSE);
888 return ERROR_NT(NT_STATUS_DISK_FULL);
891 /* Adjust size here to return the right size in the reply.
892 Windows does it this way. */
893 size = fsp->initial_allocation_size;
895 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
899 if (ea_list && smb_action == FILE_WAS_CREATED) {
900 status = set_ea(conn, fsp, fname, ea_list);
901 if (!NT_STATUS_IS_OK(status)) {
902 close_file(fsp,ERROR_CLOSE);
903 return ERROR_NT(status);
907 /* Realloc the size of parameters and data we will return */
908 *pparams = (char *)SMB_REALLOC(*pparams, 30);
909 if(*pparams == NULL ) {
910 return ERROR_NT(NT_STATUS_NO_MEMORY);
914 SSVAL(params,0,fsp->fnum);
915 SSVAL(params,2,fattr);
916 srv_put_dos_date2(params,4, mtime);
917 SIVAL(params,8, (uint32)size);
918 SSVAL(params,12,deny_mode);
919 SSVAL(params,14,0); /* open_type - file or directory. */
920 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
922 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
923 smb_action |= EXTENDED_OPLOCK_GRANTED;
926 SSVAL(params,18,smb_action);
929 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
931 SIVAL(params,20,inode);
932 SSVAL(params,24,0); /* Padding. */
934 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
935 SIVAL(params, 26, ea_size);
937 SIVAL(params, 26, 0);
940 /* Send the required number of replies */
941 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
946 /*********************************************************
947 Routine to check if a given string matches exactly.
948 as a special case a mask of "." does NOT match. That
949 is required for correct wildcard semantics
950 Case can be significant or not.
951 **********************************************************/
953 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
955 if (mask[0] == '.' && mask[1] == 0)
957 if (conn->case_sensitive)
958 return strcmp(str,mask)==0;
959 if (StrCaseCmp(str,mask) != 0) {
962 if (dptr_has_wild(conn->dirptr)) {
968 /****************************************************************************
969 Return the filetype for UNIX extensions.
970 ****************************************************************************/
972 static uint32 unix_filetype(mode_t mode)
975 return UNIX_TYPE_FILE;
976 else if(S_ISDIR(mode))
977 return UNIX_TYPE_DIR;
979 else if(S_ISLNK(mode))
980 return UNIX_TYPE_SYMLINK;
983 else if(S_ISCHR(mode))
984 return UNIX_TYPE_CHARDEV;
987 else if(S_ISBLK(mode))
988 return UNIX_TYPE_BLKDEV;
991 else if(S_ISFIFO(mode))
992 return UNIX_TYPE_FIFO;
995 else if(S_ISSOCK(mode))
996 return UNIX_TYPE_SOCKET;
999 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1000 return UNIX_TYPE_UNKNOWN;
1003 /****************************************************************************
1004 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1005 ****************************************************************************/
1007 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
1011 if (perms == SMB_MODE_NO_CHANGE)
1012 return pst->st_mode;
1014 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1015 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1016 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1017 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1018 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1019 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1020 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1021 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1022 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1024 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1027 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1030 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1033 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
1034 ret &= lp_dir_mask(SNUM(conn));
1035 /* Add in force bits */
1036 ret |= lp_force_dir_mode(SNUM(conn));
1038 /* Apply mode mask */
1039 ret &= lp_create_mask(SNUM(conn));
1040 /* Add in force bits */
1041 ret |= lp_force_create_mode(SNUM(conn));
1047 /****************************************************************************
1048 Get a level dependent lanman2 dir entry.
1049 ****************************************************************************/
1051 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1052 void *inbuf, char *outbuf,
1053 char *path_mask,uint32 dirtype,int info_level,
1054 int requires_resume_key,
1055 BOOL dont_descend,char **ppdata,
1056 char *base_data, int space_remaining,
1057 BOOL *out_of_space, BOOL *got_exact_match,
1058 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1062 SMB_STRUCT_STAT sbuf;
1066 char *p, *q, *pdata = *ppdata;
1070 SMB_OFF_T file_size = 0;
1071 SMB_BIG_UINT allocation_size = 0;
1073 struct timespec mdate_ts, adate_ts, create_date_ts;
1074 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1076 char *last_entry_ptr;
1078 uint32 nt_extmode; /* Used for NT connections instead of mode */
1079 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1080 BOOL check_mangled_names = lp_manglednames(conn->params);
1083 *out_of_space = False;
1084 *got_exact_match = False;
1086 ZERO_STRUCT(mdate_ts);
1087 ZERO_STRUCT(adate_ts);
1088 ZERO_STRUCT(create_date_ts);
1093 p = strrchr_m(path_mask,'/');
1096 pstrcpy(mask,"*.*");
1100 pstrcpy(mask, path_mask);
1105 BOOL ms_dfs_link = False;
1107 /* Needed if we run out of space */
1108 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1109 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1112 * Due to bugs in NT client redirectors we are not using
1113 * resume keys any more - set them to zero.
1114 * Check out the related comments in findfirst/findnext.
1120 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1121 (long)conn->dirptr,curr_dirpos));
1126 pstrcpy(fname,dname);
1128 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1129 got_match = mask_match(fname, mask, conn->case_sensitive);
1131 if(!got_match && check_mangled_names &&
1132 !mangle_is_8_3(fname, False, conn->params)) {
1135 * It turns out that NT matches wildcards against
1136 * both long *and* short names. This may explain some
1137 * of the wildcard wierdness from old DOS clients
1138 * that some people have been seeing.... JRA.
1142 pstrcpy( newname, fname);
1143 mangle_map( newname, True, False, conn->params);
1144 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1145 got_match = mask_match(newname, mask, conn->case_sensitive);
1149 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1150 if (dont_descend && !isdots)
1153 pstrcpy(pathreal,conn->dirpath);
1155 pstrcat(pathreal,"/");
1156 pstrcat(pathreal,dname);
1158 if (INFO_LEVEL_IS_UNIX(info_level)) {
1159 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1160 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1161 pathreal,strerror(errno)));
1164 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1166 /* Needed to show the msdfs symlinks as
1169 if(lp_host_msdfs() &&
1170 lp_msdfs_root(SNUM(conn)) &&
1171 ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1173 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1174 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1178 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1179 pathreal,strerror(errno)));
1185 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1187 mode = dos_mode(conn,pathreal,&sbuf);
1190 if (!dir_check_ftype(conn,mode,dirtype)) {
1191 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1196 file_size = get_file_size(sbuf);
1197 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1199 mdate_ts = get_mtimespec(&sbuf);
1200 adate_ts = get_atimespec(&sbuf);
1201 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1203 if (lp_dos_filetime_resolution(SNUM(conn))) {
1204 dos_filetime_timespec(&create_date_ts);
1205 dos_filetime_timespec(&mdate_ts);
1206 dos_filetime_timespec(&adate_ts);
1209 create_date = convert_timespec_to_time_t(create_date_ts);
1210 mdate = convert_timespec_to_time_t(mdate_ts);
1211 adate = convert_timespec_to_time_t(adate_ts);
1213 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1217 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1221 mangle_map(fname,False,True,conn->params);
1226 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1228 switch (info_level) {
1229 case SMB_FIND_INFO_STANDARD:
1230 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1231 if(requires_resume_key) {
1235 srv_put_dos_date2(p,0,create_date);
1236 srv_put_dos_date2(p,4,adate);
1237 srv_put_dos_date2(p,8,mdate);
1238 SIVAL(p,12,(uint32)file_size);
1239 SIVAL(p,16,(uint32)allocation_size);
1243 p += align_string(outbuf, p, 0);
1244 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1245 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1247 SCVAL(nameptr, -1, len - 2);
1249 SCVAL(nameptr, -1, 0);
1253 SCVAL(nameptr, -1, len - 1);
1255 SCVAL(nameptr, -1, 0);
1261 case SMB_FIND_EA_SIZE:
1262 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1263 if(requires_resume_key) {
1267 srv_put_dos_date2(p,0,create_date);
1268 srv_put_dos_date2(p,4,adate);
1269 srv_put_dos_date2(p,8,mdate);
1270 SIVAL(p,12,(uint32)file_size);
1271 SIVAL(p,16,(uint32)allocation_size);
1274 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1275 SIVAL(p,22,ea_size); /* Extended attributes */
1279 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1280 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1293 SCVAL(nameptr,0,len);
1295 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1298 case SMB_FIND_EA_LIST:
1300 struct ea_list *file_list = NULL;
1303 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1307 if(requires_resume_key) {
1311 srv_put_dos_date2(p,0,create_date);
1312 srv_put_dos_date2(p,4,adate);
1313 srv_put_dos_date2(p,8,mdate);
1314 SIVAL(p,12,(uint32)file_size);
1315 SIVAL(p,16,(uint32)allocation_size);
1317 p += 22; /* p now points to the EA area. */
1319 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1320 name_list = ea_list_union(name_list, file_list, &ea_len);
1322 /* We need to determine if this entry will fit in the space available. */
1323 /* Max string size is 255 bytes. */
1324 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1325 /* Move the dirptr back to prev_dirpos */
1326 dptr_SeekDir(conn->dirptr, prev_dirpos);
1327 *out_of_space = True;
1328 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1329 return False; /* Not finished - just out of space */
1332 /* Push the ea_data followed by the name. */
1333 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1335 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1336 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1349 SCVAL(nameptr,0,len);
1351 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1355 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1356 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1357 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1359 SIVAL(p,0,reskey); p += 4;
1360 put_long_date_timespec(p,create_date_ts); p += 8;
1361 put_long_date_timespec(p,adate_ts); p += 8;
1362 put_long_date_timespec(p,mdate_ts); p += 8;
1363 put_long_date_timespec(p,mdate_ts); p += 8;
1364 SOFF_T(p,0,file_size); p += 8;
1365 SOFF_T(p,0,allocation_size); p += 8;
1366 SIVAL(p,0,nt_extmode); p += 4;
1367 q = p; p += 4; /* q is placeholder for name length. */
1369 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1370 SIVAL(p,0,ea_size); /* Extended attributes */
1373 /* Clear the short name buffer. This is
1374 * IMPORTANT as not doing so will trigger
1375 * a Win2k client bug. JRA.
1377 if (!was_8_3 && check_mangled_names) {
1378 pstring mangled_name;
1379 pstrcpy(mangled_name, fname);
1380 mangle_map(mangled_name,True,True,
1382 mangled_name[12] = 0;
1383 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1385 memset(p + 2 + len,'\0',24 - len);
1392 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1395 SIVAL(p,0,0); /* Ensure any padding is null. */
1396 len = PTR_DIFF(p, pdata);
1397 len = (len + 3) & ~3;
1402 case SMB_FIND_FILE_DIRECTORY_INFO:
1403 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1405 SIVAL(p,0,reskey); p += 4;
1406 put_long_date_timespec(p,create_date_ts); p += 8;
1407 put_long_date_timespec(p,adate_ts); p += 8;
1408 put_long_date_timespec(p,mdate_ts); p += 8;
1409 put_long_date_timespec(p,mdate_ts); p += 8;
1410 SOFF_T(p,0,file_size); p += 8;
1411 SOFF_T(p,0,allocation_size); p += 8;
1412 SIVAL(p,0,nt_extmode); p += 4;
1413 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1416 SIVAL(p,0,0); /* Ensure any padding is null. */
1417 len = PTR_DIFF(p, pdata);
1418 len = (len + 3) & ~3;
1423 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1424 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1426 SIVAL(p,0,reskey); p += 4;
1427 put_long_date_timespec(p,create_date_ts); p += 8;
1428 put_long_date_timespec(p,adate_ts); p += 8;
1429 put_long_date_timespec(p,mdate_ts); p += 8;
1430 put_long_date_timespec(p,mdate_ts); p += 8;
1431 SOFF_T(p,0,file_size); p += 8;
1432 SOFF_T(p,0,allocation_size); p += 8;
1433 SIVAL(p,0,nt_extmode); p += 4;
1434 q = p; p += 4; /* q is placeholder for name length. */
1436 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1437 SIVAL(p,0,ea_size); /* Extended attributes */
1440 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1444 SIVAL(p,0,0); /* Ensure any padding is null. */
1445 len = PTR_DIFF(p, pdata);
1446 len = (len + 3) & ~3;
1451 case SMB_FIND_FILE_NAMES_INFO:
1452 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1454 SIVAL(p,0,reskey); p += 4;
1456 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1457 acl on a dir (tridge) */
1458 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1461 SIVAL(p,0,0); /* Ensure any padding is null. */
1462 len = PTR_DIFF(p, pdata);
1463 len = (len + 3) & ~3;
1468 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1469 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1471 SIVAL(p,0,reskey); p += 4;
1472 put_long_date_timespec(p,create_date_ts); p += 8;
1473 put_long_date_timespec(p,adate_ts); p += 8;
1474 put_long_date_timespec(p,mdate_ts); p += 8;
1475 put_long_date_timespec(p,mdate_ts); p += 8;
1476 SOFF_T(p,0,file_size); p += 8;
1477 SOFF_T(p,0,allocation_size); p += 8;
1478 SIVAL(p,0,nt_extmode); p += 4;
1479 q = p; p += 4; /* q is placeholder for name length. */
1481 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1482 SIVAL(p,0,ea_size); /* Extended attributes */
1485 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1486 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1487 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1488 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1491 SIVAL(p,0,0); /* Ensure any padding is null. */
1492 len = PTR_DIFF(p, pdata);
1493 len = (len + 3) & ~3;
1498 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1500 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1502 SIVAL(p,0,reskey); p += 4;
1503 put_long_date_timespec(p,create_date_ts); p += 8;
1504 put_long_date_timespec(p,adate_ts); p += 8;
1505 put_long_date_timespec(p,mdate_ts); p += 8;
1506 put_long_date_timespec(p,mdate_ts); p += 8;
1507 SOFF_T(p,0,file_size); p += 8;
1508 SOFF_T(p,0,allocation_size); p += 8;
1509 SIVAL(p,0,nt_extmode); p += 4;
1510 q = p; p += 4; /* q is placeholder for name length */
1512 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1513 SIVAL(p,0,ea_size); /* Extended attributes */
1516 /* Clear the short name buffer. This is
1517 * IMPORTANT as not doing so will trigger
1518 * a Win2k client bug. JRA.
1520 if (!was_8_3 && check_mangled_names) {
1521 pstring mangled_name;
1522 pstrcpy(mangled_name, fname);
1523 mangle_map(mangled_name,True,True,
1525 mangled_name[12] = 0;
1526 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1529 memset(p + 2 + len,'\0',24 - len);
1536 SSVAL(p,0,0); p += 2; /* Reserved ? */
1537 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1538 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1539 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1542 SIVAL(p,0,0); /* Ensure any padding is null. */
1543 len = PTR_DIFF(p, pdata);
1544 len = (len + 3) & ~3;
1549 /* CIFS UNIX Extension. */
1551 case SMB_FIND_FILE_UNIX:
1552 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1554 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1556 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1557 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1560 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1563 put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */
1564 put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
1565 put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
1568 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1572 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1576 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1579 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1583 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1587 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1590 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1594 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1598 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1600 SIVAL(p,0,0); /* Ensure any padding is null. */
1602 len = PTR_DIFF(p, pdata);
1603 len = (len + 3) & ~3;
1604 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1606 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1615 if (PTR_DIFF(p,pdata) > space_remaining) {
1616 /* Move the dirptr back to prev_dirpos */
1617 dptr_SeekDir(conn->dirptr, prev_dirpos);
1618 *out_of_space = True;
1619 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1620 return False; /* Not finished - just out of space */
1623 /* Setup the last entry pointer, as an offset from base_data */
1624 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1625 /* Advance the data pointer to the next slot */
1631 /****************************************************************************
1632 Reply to a TRANS2_FINDFIRST.
1633 ****************************************************************************/
1635 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1636 char **pparams, int total_params, char **ppdata, int total_data,
1637 unsigned int max_data_bytes)
1639 /* We must be careful here that we don't return more than the
1640 allowed number of data bytes. If this means returning fewer than
1641 maxentries then so be it. We assume that the redirector has
1642 enough room for the fixed number of parameter bytes it has
1644 char *params = *pparams;
1645 char *pdata = *ppdata;
1648 uint16 findfirst_flags;
1649 BOOL close_after_first;
1651 BOOL requires_resume_key;
1656 int last_entry_off=0;
1660 BOOL finished = False;
1661 BOOL dont_descend = False;
1662 BOOL out_of_space = False;
1663 int space_remaining;
1664 BOOL mask_contains_wcard = False;
1665 SMB_STRUCT_STAT sbuf;
1666 TALLOC_CTX *ea_ctx = NULL;
1667 struct ea_list *ea_list = NULL;
1668 NTSTATUS ntstatus = NT_STATUS_OK;
1670 if (total_params < 13) {
1671 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1674 dirtype = SVAL(params,0);
1675 maxentries = SVAL(params,2);
1676 findfirst_flags = SVAL(params,4);
1677 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1678 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1679 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1680 info_level = SVAL(params,6);
1682 *directory = *mask = 0;
1684 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1685 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1686 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1687 info_level, max_data_bytes));
1690 /* W2K3 seems to treat zero as 1. */
1694 switch (info_level) {
1695 case SMB_FIND_INFO_STANDARD:
1696 case SMB_FIND_EA_SIZE:
1697 case SMB_FIND_EA_LIST:
1698 case SMB_FIND_FILE_DIRECTORY_INFO:
1699 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1700 case SMB_FIND_FILE_NAMES_INFO:
1701 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1702 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1703 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1705 case SMB_FIND_FILE_UNIX:
1706 if (!lp_unix_extensions()) {
1707 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1711 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1714 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1715 if (!NT_STATUS_IS_OK(ntstatus)) {
1716 return ERROR_NT(ntstatus);
1719 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1721 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1722 if (!NT_STATUS_IS_OK(ntstatus)) {
1723 return ERROR_NT(ntstatus);
1725 if(!check_name(directory,conn)) {
1726 return UNIXERROR(ERRDOS,ERRbadpath);
1729 p = strrchr_m(directory,'/');
1731 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1732 if((directory[0] == '.') && (directory[1] == '\0')) {
1734 mask_contains_wcard = True;
1736 pstrcpy(mask,directory);
1738 pstrcpy(directory,"./");
1744 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1746 if (info_level == SMB_FIND_EA_LIST) {
1749 if (total_data < 4) {
1750 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1753 ea_size = IVAL(pdata,0);
1754 if (ea_size != total_data) {
1755 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1756 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1757 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1760 if (!lp_ea_support(SNUM(conn))) {
1761 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1764 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1765 return ERROR_NT(NT_STATUS_NO_MEMORY);
1768 /* Pull out the list of names. */
1769 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1771 talloc_destroy(ea_ctx);
1772 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1776 *ppdata = (char *)SMB_REALLOC(
1777 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1778 if(*ppdata == NULL ) {
1779 talloc_destroy(ea_ctx);
1780 return ERROR_NT(NT_STATUS_NO_MEMORY);
1784 /* Realloc the params space */
1785 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1786 if (*pparams == NULL) {
1787 talloc_destroy(ea_ctx);
1788 return ERROR_NT(NT_STATUS_NO_MEMORY);
1792 /* Save the wildcard match and attribs we are using on this directory -
1793 needed as lanman2 assumes these are being saved between calls */
1795 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1797 talloc_destroy(ea_ctx);
1798 return(UNIXERROR(ERRDOS,ERRbadfile));
1801 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1803 /* We don't need to check for VOL here as this is returned by
1804 a different TRANS2 call. */
1806 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1807 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1808 dont_descend = True;
1811 space_remaining = max_data_bytes;
1812 out_of_space = False;
1814 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1815 BOOL got_exact_match = False;
1817 /* this is a heuristic to avoid seeking the dirptr except when
1818 absolutely necessary. It allows for a filename of about 40 chars */
1819 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1820 out_of_space = True;
1823 finished = !get_lanman2_dir_entry(conn,
1825 mask,dirtype,info_level,
1826 requires_resume_key,dont_descend,
1827 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1828 &last_entry_off, ea_list, ea_ctx);
1831 if (finished && out_of_space)
1834 if (!finished && !out_of_space)
1838 * As an optimisation if we know we aren't looking
1839 * for a wildcard name (ie. the name matches the wildcard exactly)
1840 * then we can finish on any (first) match.
1841 * This speeds up large directory searches. JRA.
1847 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1850 talloc_destroy(ea_ctx);
1852 /* Check if we can close the dirptr */
1853 if(close_after_first || (finished && close_if_end)) {
1854 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1855 dptr_close(&dptr_num);
1859 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1860 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1861 * the protocol level is less than NT1. Tested with smbclient. JRA.
1862 * This should fix the OS/2 client bug #2335.
1865 if(numentries == 0) {
1866 dptr_close(&dptr_num);
1867 if (Protocol < PROTOCOL_NT1) {
1868 return ERROR_DOS(ERRDOS,ERRnofiles);
1870 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1874 /* At this point pdata points to numentries directory entries. */
1876 /* Set up the return parameter block */
1877 SSVAL(params,0,dptr_num);
1878 SSVAL(params,2,numentries);
1879 SSVAL(params,4,finished);
1880 SSVAL(params,6,0); /* Never an EA error */
1881 SSVAL(params,8,last_entry_off);
1883 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1885 if ((! *directory) && dptr_path(dptr_num))
1886 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1888 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1889 smb_fn_name(CVAL(inbuf,smb_com)),
1890 mask, directory, dirtype, numentries ) );
1893 * Force a name mangle here to ensure that the
1894 * mask as an 8.3 name is top of the mangled cache.
1895 * The reasons for this are subtle. Don't remove
1896 * this code unless you know what you are doing
1897 * (see PR#13758). JRA.
1900 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1901 mangle_map(mask, True, True, conn->params);
1906 /****************************************************************************
1907 Reply to a TRANS2_FINDNEXT.
1908 ****************************************************************************/
1910 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1911 char **pparams, int total_params, char **ppdata, int total_data,
1912 unsigned int max_data_bytes)
1914 /* We must be careful here that we don't return more than the
1915 allowed number of data bytes. If this means returning fewer than
1916 maxentries then so be it. We assume that the redirector has
1917 enough room for the fixed number of parameter bytes it has
1919 char *params = *pparams;
1920 char *pdata = *ppdata;
1925 uint16 findnext_flags;
1926 BOOL close_after_request;
1928 BOOL requires_resume_key;
1930 BOOL mask_contains_wcard = False;
1931 pstring resume_name;
1937 int i, last_entry_off=0;
1938 BOOL finished = False;
1939 BOOL dont_descend = False;
1940 BOOL out_of_space = False;
1941 int space_remaining;
1942 TALLOC_CTX *ea_ctx = NULL;
1943 struct ea_list *ea_list = NULL;
1944 NTSTATUS ntstatus = NT_STATUS_OK;
1946 if (total_params < 13) {
1947 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1950 dptr_num = SVAL(params,0);
1951 maxentries = SVAL(params,2);
1952 info_level = SVAL(params,4);
1953 resume_key = IVAL(params,6);
1954 findnext_flags = SVAL(params,10);
1955 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1956 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1957 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1958 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1960 *mask = *directory = *resume_name = 0;
1962 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1963 if (!NT_STATUS_IS_OK(ntstatus)) {
1964 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1965 complain (it thinks we're asking for the directory above the shared
1966 path or an invalid name). Catch this as the resume name is only compared, never used in
1967 a file access. JRA. */
1968 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1969 pstrcpy(resume_name, "..");
1970 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1971 pstrcpy(resume_name, ".");
1973 return ERROR_NT(ntstatus);
1977 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1978 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1979 resume_key = %d resume name = %s continue=%d level = %d\n",
1980 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1981 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1984 /* W2K3 seems to treat zero as 1. */
1988 switch (info_level) {
1989 case SMB_FIND_INFO_STANDARD:
1990 case SMB_FIND_EA_SIZE:
1991 case SMB_FIND_EA_LIST:
1992 case SMB_FIND_FILE_DIRECTORY_INFO:
1993 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1994 case SMB_FIND_FILE_NAMES_INFO:
1995 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1996 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1997 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1999 case SMB_FIND_FILE_UNIX:
2000 if (!lp_unix_extensions()) {
2001 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2005 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2008 if (info_level == SMB_FIND_EA_LIST) {
2011 if (total_data < 4) {
2012 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2015 ea_size = IVAL(pdata,0);
2016 if (ea_size != total_data) {
2017 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2018 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2019 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2022 if (!lp_ea_support(SNUM(conn))) {
2023 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2026 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2027 return ERROR_NT(NT_STATUS_NO_MEMORY);
2030 /* Pull out the list of names. */
2031 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2033 talloc_destroy(ea_ctx);
2034 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2038 *ppdata = (char *)SMB_REALLOC(
2039 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2040 if(*ppdata == NULL) {
2041 talloc_destroy(ea_ctx);
2042 return ERROR_NT(NT_STATUS_NO_MEMORY);
2047 /* Realloc the params space */
2048 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2049 if(*pparams == NULL ) {
2050 talloc_destroy(ea_ctx);
2051 return ERROR_NT(NT_STATUS_NO_MEMORY);
2056 /* Check that the dptr is valid */
2057 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2058 talloc_destroy(ea_ctx);
2059 return ERROR_DOS(ERRDOS,ERRnofiles);
2062 string_set(&conn->dirpath,dptr_path(dptr_num));
2064 /* Get the wildcard mask from the dptr */
2065 if((p = dptr_wcard(dptr_num))== NULL) {
2066 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2067 talloc_destroy(ea_ctx);
2068 return ERROR_DOS(ERRDOS,ERRnofiles);
2072 pstrcpy(directory,conn->dirpath);
2074 /* Get the attr mask from the dptr */
2075 dirtype = dptr_attr(dptr_num);
2077 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2078 dptr_num, mask, dirtype,
2080 dptr_TellDir(conn->dirptr)));
2082 /* We don't need to check for VOL here as this is returned by
2083 a different TRANS2 call. */
2085 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2086 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2087 dont_descend = True;
2090 space_remaining = max_data_bytes;
2091 out_of_space = False;
2094 * Seek to the correct position. We no longer use the resume key but
2095 * depend on the last file name instead.
2098 if(*resume_name && !continue_bit) {
2101 long current_pos = 0;
2103 * Remember, mangle_map is called by
2104 * get_lanman2_dir_entry(), so the resume name
2105 * could be mangled. Ensure we check the unmangled name.
2108 if (mangle_is_mangled(resume_name, conn->params)) {
2109 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2114 * Fix for NT redirector problem triggered by resume key indexes
2115 * changing between directory scans. We now return a resume key of 0
2116 * and instead look for the filename to continue from (also given
2117 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2118 * findfirst/findnext (as is usual) then the directory pointer
2119 * should already be at the correct place.
2122 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2123 } /* end if resume_name && !continue_bit */
2125 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2126 BOOL got_exact_match = False;
2128 /* this is a heuristic to avoid seeking the dirptr except when
2129 absolutely necessary. It allows for a filename of about 40 chars */
2130 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2131 out_of_space = True;
2134 finished = !get_lanman2_dir_entry(conn,
2136 mask,dirtype,info_level,
2137 requires_resume_key,dont_descend,
2138 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2139 &last_entry_off, ea_list, ea_ctx);
2142 if (finished && out_of_space)
2145 if (!finished && !out_of_space)
2149 * As an optimisation if we know we aren't looking
2150 * for a wildcard name (ie. the name matches the wildcard exactly)
2151 * then we can finish on any (first) match.
2152 * This speeds up large directory searches. JRA.
2158 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2161 talloc_destroy(ea_ctx);
2163 /* Check if we can close the dirptr */
2164 if(close_after_request || (finished && close_if_end)) {
2165 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2166 dptr_close(&dptr_num); /* This frees up the saved mask */
2169 /* Set up the return parameter block */
2170 SSVAL(params,0,numentries);
2171 SSVAL(params,2,finished);
2172 SSVAL(params,4,0); /* Never an EA error */
2173 SSVAL(params,6,last_entry_off);
2175 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2177 if ((! *directory) && dptr_path(dptr_num))
2178 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2180 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2181 smb_fn_name(CVAL(inbuf,smb_com)),
2182 mask, directory, dirtype, numentries ) );
2187 /****************************************************************************
2188 Reply to a TRANS2_QFSINFO (query filesystem info).
2189 ****************************************************************************/
2191 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2192 char **pparams, int total_params, char **ppdata, int total_data,
2193 unsigned int max_data_bytes)
2195 char *pdata = *ppdata;
2196 char *params = *pparams;
2200 char *vname = volume_label(SNUM(conn));
2201 int snum = SNUM(conn);
2202 char *fstype = lp_fstype(SNUM(conn));
2205 if (total_params < 2) {
2206 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2209 info_level = SVAL(params,0);
2211 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2213 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2214 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2215 return ERROR_DOS(ERRSRV,ERRinvdevice);
2218 *ppdata = (char *)SMB_REALLOC(
2219 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2220 if (*ppdata == NULL ) {
2221 return ERROR_NT(NT_STATUS_NO_MEMORY);
2225 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2227 switch (info_level) {
2228 case SMB_INFO_ALLOCATION:
2230 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2232 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2233 return(UNIXERROR(ERRHRD,ERRgeneral));
2236 block_size = lp_block_size(snum);
2237 if (bsize < block_size) {
2238 SMB_BIG_UINT factor = block_size/bsize;
2243 if (bsize > block_size) {
2244 SMB_BIG_UINT factor = bsize/block_size;
2249 bytes_per_sector = 512;
2250 sectors_per_unit = bsize/bytes_per_sector;
2252 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2253 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2254 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2256 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2257 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2258 SIVAL(pdata,l1_cUnit,dsize);
2259 SIVAL(pdata,l1_cUnitAvail,dfree);
2260 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2264 case SMB_INFO_VOLUME:
2265 /* Return volume name */
2267 * Add volume serial number - hash of a combination of
2268 * the called hostname and the service name.
2270 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2272 * Win2k3 and previous mess this up by sending a name length
2273 * one byte short. I believe only older clients (OS/2 Win9x) use
2274 * this call so try fixing this by adding a terminating null to
2275 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2277 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2278 SCVAL(pdata,l2_vol_cch,len);
2279 data_len = l2_vol_szVolLabel + len;
2280 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2281 (unsigned)st.st_ctime, len, vname));
2284 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2285 case SMB_FS_ATTRIBUTE_INFORMATION:
2288 #if defined(HAVE_SYS_QUOTAS)
2289 quota_flag = FILE_VOLUME_QUOTAS;
2292 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2293 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2294 quota_flag); /* FS ATTRIBUTES */
2296 SIVAL(pdata,4,255); /* Max filename component length */
2297 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2298 and will think we can't do long filenames */
2299 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2301 data_len = 12 + len;
2304 case SMB_QUERY_FS_LABEL_INFO:
2305 case SMB_FS_LABEL_INFORMATION:
2306 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2311 case SMB_QUERY_FS_VOLUME_INFO:
2312 case SMB_FS_VOLUME_INFORMATION:
2315 * Add volume serial number - hash of a combination of
2316 * the called hostname and the service name.
2318 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2319 (str_checksum(get_local_machine_name())<<16));
2321 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2322 SIVAL(pdata,12,len);
2324 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2325 (int)strlen(vname),vname, lp_servicename(snum)));
2328 case SMB_QUERY_FS_SIZE_INFO:
2329 case SMB_FS_SIZE_INFORMATION:
2331 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2333 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2334 return(UNIXERROR(ERRHRD,ERRgeneral));
2336 block_size = lp_block_size(snum);
2337 if (bsize < block_size) {
2338 SMB_BIG_UINT factor = block_size/bsize;
2343 if (bsize > block_size) {
2344 SMB_BIG_UINT factor = bsize/block_size;
2349 bytes_per_sector = 512;
2350 sectors_per_unit = bsize/bytes_per_sector;
2351 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2352 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2353 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2354 SBIG_UINT(pdata,0,dsize);
2355 SBIG_UINT(pdata,8,dfree);
2356 SIVAL(pdata,16,sectors_per_unit);
2357 SIVAL(pdata,20,bytes_per_sector);
2361 case SMB_FS_FULL_SIZE_INFORMATION:
2363 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2365 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2366 return(UNIXERROR(ERRHRD,ERRgeneral));
2368 block_size = lp_block_size(snum);
2369 if (bsize < block_size) {
2370 SMB_BIG_UINT factor = block_size/bsize;
2375 if (bsize > block_size) {
2376 SMB_BIG_UINT factor = bsize/block_size;
2381 bytes_per_sector = 512;
2382 sectors_per_unit = bsize/bytes_per_sector;
2383 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2384 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2385 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2386 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2387 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2388 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2389 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2390 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2394 case SMB_QUERY_FS_DEVICE_INFO:
2395 case SMB_FS_DEVICE_INFORMATION:
2397 SIVAL(pdata,0,0); /* dev type */
2398 SIVAL(pdata,4,0); /* characteristics */
2401 #ifdef HAVE_SYS_QUOTAS
2402 case SMB_FS_QUOTA_INFORMATION:
2404 * what we have to send --metze:
2406 * Unknown1: 24 NULL bytes
2407 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2408 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2409 * Quota Flags: 2 byte :
2410 * Unknown3: 6 NULL bytes
2414 * details for Quota Flags:
2416 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2417 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2418 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2419 * 0x0001 Enable Quotas: enable quota for this fs
2423 /* we need to fake up a fsp here,
2424 * because its not send in this call
2427 SMB_NTQUOTA_STRUCT quotas;
2430 ZERO_STRUCT(quotas);
2436 if (current_user.ut.uid != 0) {
2437 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2438 lp_servicename(SNUM(conn)),conn->user));
2439 return ERROR_DOS(ERRDOS,ERRnoaccess);
2442 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2443 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2444 return ERROR_DOS(ERRSRV,ERRerror);
2449 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2451 /* Unknown1 24 NULL bytes*/
2452 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2453 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2454 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2456 /* Default Soft Quota 8 bytes */
2457 SBIG_UINT(pdata,24,quotas.softlim);
2459 /* Default Hard Quota 8 bytes */
2460 SBIG_UINT(pdata,32,quotas.hardlim);
2462 /* Quota flag 2 bytes */
2463 SSVAL(pdata,40,quotas.qflags);
2465 /* Unknown3 6 NULL bytes */
2471 #endif /* HAVE_SYS_QUOTAS */
2472 case SMB_FS_OBJECTID_INFORMATION:
2477 * Query the version and capabilities of the CIFS UNIX extensions
2481 case SMB_QUERY_CIFS_UNIX_INFO:
2482 if (!lp_unix_extensions()) {
2483 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2486 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2487 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2488 /* We have POSIX ACLs, pathname and locking capability. */
2489 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2490 CIFS_UNIX_POSIX_ACLS_CAP|
2491 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2492 CIFS_UNIX_FCNTL_LOCKS_CAP)));
2495 case SMB_QUERY_POSIX_FS_INFO:
2498 vfs_statvfs_struct svfs;
2500 if (!lp_unix_extensions()) {
2501 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2504 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2508 SIVAL(pdata,0,svfs.OptimalTransferSize);
2509 SIVAL(pdata,4,svfs.BlockSize);
2510 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2511 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2512 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2513 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2514 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2515 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2516 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2518 } else if (rc == EOPNOTSUPP) {
2519 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2520 #endif /* EOPNOTSUPP */
2522 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2523 return ERROR_DOS(ERRSRV,ERRerror);
2528 case SMB_MAC_QUERY_FS_INFO:
2530 * Thursby MAC extension... ONLY on NTFS filesystems
2531 * once we do streams then we don't need this
2533 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2535 SIVAL(pdata,84,0x100); /* Don't support mac... */
2540 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2544 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2546 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2551 /****************************************************************************
2552 Reply to a TRANS2_SETFSINFO (set filesystem info).
2553 ****************************************************************************/
2555 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2556 char **pparams, int total_params, char **ppdata, int total_data,
2557 unsigned int max_data_bytes)
2559 char *pdata = *ppdata;
2560 char *params = *pparams;
2564 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2567 if (total_params < 4) {
2568 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2570 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2573 info_level = SVAL(params,2);
2575 switch(info_level) {
2576 case SMB_SET_CIFS_UNIX_INFO:
2578 uint16 client_unix_major;
2579 uint16 client_unix_minor;
2580 uint32 client_unix_cap_low;
2581 uint32 client_unix_cap_high;
2583 if (!lp_unix_extensions()) {
2584 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2587 /* There should be 12 bytes of capabilities set. */
2588 if (total_data < 8) {
2589 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2591 client_unix_major = SVAL(pdata,0);
2592 client_unix_minor = SVAL(pdata,2);
2593 client_unix_cap_low = IVAL(pdata,4);
2594 client_unix_cap_high = IVAL(pdata,8);
2595 /* Just print these values for now. */
2596 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2597 cap_low = 0x%x, cap_high = 0x%x\n",
2598 (unsigned int)client_unix_major,
2599 (unsigned int)client_unix_minor,
2600 (unsigned int)client_unix_cap_low,
2601 (unsigned int)client_unix_cap_high ));
2603 /* Here is where we must switch to posix pathname processing... */
2604 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2605 lp_set_posix_pathnames();
2606 mangle_change_to_posix();
2609 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2610 lp_set_posix_cifsx_locktype(POSIX_LOCK);
2614 case SMB_FS_QUOTA_INFORMATION:
2616 files_struct *fsp = NULL;
2617 SMB_NTQUOTA_STRUCT quotas;
2619 ZERO_STRUCT(quotas);
2622 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2623 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2624 lp_servicename(SNUM(conn)),conn->user));
2625 return ERROR_DOS(ERRSRV,ERRaccess);
2628 /* note: normaly there're 48 bytes,
2629 * but we didn't use the last 6 bytes for now
2632 fsp = file_fsp(params,0);
2633 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2634 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2635 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2638 if (total_data < 42) {
2639 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2641 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2644 /* unknown_1 24 NULL bytes in pdata*/
2646 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2647 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2648 #ifdef LARGE_SMB_OFF_T
2649 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2650 #else /* LARGE_SMB_OFF_T */
2651 if ((IVAL(pdata,28) != 0)&&
2652 ((quotas.softlim != 0xFFFFFFFF)||
2653 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2654 /* more than 32 bits? */
2655 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2657 #endif /* LARGE_SMB_OFF_T */
2659 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2660 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2661 #ifdef LARGE_SMB_OFF_T
2662 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2663 #else /* LARGE_SMB_OFF_T */
2664 if ((IVAL(pdata,36) != 0)&&
2665 ((quotas.hardlim != 0xFFFFFFFF)||
2666 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2667 /* more than 32 bits? */
2668 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2670 #endif /* LARGE_SMB_OFF_T */
2672 /* quota_flags 2 bytes **/
2673 quotas.qflags = SVAL(pdata,40);
2675 /* unknown_2 6 NULL bytes follow*/
2677 /* now set the quotas */
2678 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2679 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2680 return ERROR_DOS(ERRSRV,ERRerror);
2686 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2688 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2693 * sending this reply works fine,
2694 * but I'm not sure it's the same
2695 * like windows do...
2698 outsize = set_message(outbuf,10,0,True);
2703 #if defined(HAVE_POSIX_ACLS)
2704 /****************************************************************************
2705 Utility function to count the number of entries in a POSIX acl.
2706 ****************************************************************************/
2708 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2710 unsigned int ace_count = 0;
2711 int entry_id = SMB_ACL_FIRST_ENTRY;
2712 SMB_ACL_ENTRY_T entry;
2714 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2716 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2717 entry_id = SMB_ACL_NEXT_ENTRY;
2724 /****************************************************************************
2725 Utility function to marshall a POSIX acl into wire format.
2726 ****************************************************************************/
2728 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2730 int entry_id = SMB_ACL_FIRST_ENTRY;
2731 SMB_ACL_ENTRY_T entry;
2733 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2734 SMB_ACL_TAG_T tagtype;
2735 SMB_ACL_PERMSET_T permset;
2736 unsigned char perms = 0;
2737 unsigned int own_grp;
2740 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2741 entry_id = SMB_ACL_NEXT_ENTRY;
2744 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2745 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2749 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2750 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2754 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2755 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2756 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2758 SCVAL(pdata,1,perms);
2761 case SMB_ACL_USER_OBJ:
2762 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2763 own_grp = (unsigned int)pst->st_uid;
2764 SIVAL(pdata,2,own_grp);
2769 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2771 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2773 own_grp = (unsigned int)*puid;
2774 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2775 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2776 SIVAL(pdata,2,own_grp);
2780 case SMB_ACL_GROUP_OBJ:
2781 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2782 own_grp = (unsigned int)pst->st_gid;
2783 SIVAL(pdata,2,own_grp);
2788 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2790 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2792 own_grp = (unsigned int)*pgid;
2793 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2794 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2795 SIVAL(pdata,2,own_grp);
2800 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2801 SIVAL(pdata,2,0xFFFFFFFF);
2802 SIVAL(pdata,6,0xFFFFFFFF);
2805 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2806 SIVAL(pdata,2,0xFFFFFFFF);
2807 SIVAL(pdata,6,0xFFFFFFFF);
2810 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2813 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2820 /****************************************************************************
2821 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2822 file name or file id).
2823 ****************************************************************************/
2825 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2826 unsigned int tran_call,
2827 char **pparams, int total_params, char **ppdata, int total_data,
2828 unsigned int max_data_bytes)
2830 char *params = *pparams;
2831 char *pdata = *ppdata;
2835 SMB_OFF_T file_size=0;
2836 SMB_BIG_UINT allocation_size=0;
2837 unsigned int data_size = 0;
2838 unsigned int param_size = 2;
2839 SMB_STRUCT_STAT sbuf;
2840 pstring fname, dos_fname;
2845 BOOL delete_pending = False;
2847 time_t create_time, mtime, atime;
2848 struct timespec create_time_ts, mtime_ts, atime_ts;
2849 files_struct *fsp = NULL;
2850 TALLOC_CTX *data_ctx = NULL;
2851 struct ea_list *ea_list = NULL;
2852 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2853 char *lock_data = NULL;
2856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2860 if (tran_call == TRANSACT2_QFILEINFO) {
2861 if (total_params < 4) {
2862 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2865 fsp = file_fsp(params,0);
2866 info_level = SVAL(params,2);
2868 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2870 if(fsp && (fsp->fake_file_handle)) {
2872 * This is actually for the QUOTA_FAKE_FILE --metze
2875 pstrcpy(fname, fsp->fsp_name);
2876 /* We know this name is ok, it's already passed the checks. */
2878 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2880 * This is actually a QFILEINFO on a directory
2881 * handle (returned from an NT SMB). NT5.0 seems
2882 * to do this call. JRA.
2884 /* We know this name is ok, it's already passed the checks. */
2885 pstrcpy(fname, fsp->fsp_name);
2887 if (INFO_LEVEL_IS_UNIX(info_level)) {
2888 /* Always do lstat for UNIX calls. */
2889 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2890 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2891 return UNIXERROR(ERRDOS,ERRbadpath);
2893 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2894 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2895 return UNIXERROR(ERRDOS,ERRbadpath);
2898 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2901 * Original code - this is an open file.
2903 CHECK_FSP(fsp,conn);
2905 pstrcpy(fname, fsp->fsp_name);
2906 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2907 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2908 return(UNIXERROR(ERRDOS,ERRbadfid));
2910 pos = fsp->fh->position_information;
2911 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2912 access_mask = fsp->access_mask;
2915 NTSTATUS status = NT_STATUS_OK;
2918 if (total_params < 7) {
2919 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2922 info_level = SVAL(params,0);
2924 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2926 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
2927 if (!NT_STATUS_IS_OK(status)) {
2928 return ERROR_NT(status);
2931 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2933 status = unix_convert(conn, fname, False, NULL, &sbuf);
2934 if (!NT_STATUS_IS_OK(status)) {
2935 return ERROR_NT(status);
2937 if (!check_name(fname,conn)) {
2938 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2939 return UNIXERROR(ERRDOS,ERRbadpath);
2942 if (INFO_LEVEL_IS_UNIX(info_level)) {
2943 /* Always do lstat for UNIX calls. */
2944 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2945 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2946 return UNIXERROR(ERRDOS,ERRbadpath);
2948 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2949 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2950 return UNIXERROR(ERRDOS,ERRbadpath);
2953 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2954 if (delete_pending) {
2955 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2959 nlink = sbuf.st_nlink;
2961 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2962 /* NTFS does not seem to count ".." */
2966 if ((nlink > 0) && delete_pending) {
2970 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2971 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2974 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2975 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2977 p = strrchr_m(fname,'/');
2983 mode = dos_mode(conn,fname,&sbuf);
2985 mode = FILE_ATTRIBUTE_NORMAL;
2987 fullpathname = fname;
2989 file_size = get_file_size(sbuf);
2991 /* Pull out any data sent here before we realloc. */
2992 switch (info_level) {
2993 case SMB_INFO_QUERY_EAS_FROM_LIST:
2995 /* Pull any EA list from the data portion. */
2998 if (total_data < 4) {
2999 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3001 ea_size = IVAL(pdata,0);
3003 if (total_data > 0 && ea_size != total_data) {
3004 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3005 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3006 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3009 if (!lp_ea_support(SNUM(conn))) {
3010 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3013 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3014 return ERROR_NT(NT_STATUS_NO_MEMORY);
3017 /* Pull out the list of names. */
3018 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3020 talloc_destroy(data_ctx);
3021 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3026 case SMB_QUERY_POSIX_LOCK:
3028 if (fsp == NULL || fsp->fh->fd == -1) {
3029 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3032 if (total_data != POSIX_LOCK_DATA_SIZE) {
3033 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3036 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3037 return ERROR_NT(NT_STATUS_NO_MEMORY);
3040 /* Copy the lock range data. */
3041 lock_data = (char *)talloc_memdup(
3042 data_ctx, pdata, total_data);
3044 talloc_destroy(data_ctx);
3045 return ERROR_NT(NT_STATUS_NO_MEMORY);
3052 *pparams = (char *)SMB_REALLOC(*pparams,2);
3053 if (*pparams == NULL) {
3054 talloc_destroy(data_ctx);
3055 return ERROR_NT(NT_STATUS_NO_MEMORY);
3059 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3060 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3061 if (*ppdata == NULL ) {
3062 talloc_destroy(data_ctx);
3063 return ERROR_NT(NT_STATUS_NO_MEMORY);
3067 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3068 mtime_ts = get_mtimespec(&sbuf);
3069 atime_ts = get_atimespec(&sbuf);
3071 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3074 if (fsp->pending_modtime) {
3075 /* the pending modtime overrides the current modtime */
3076 mtime_ts.tv_sec = fsp->pending_modtime;
3077 mtime_ts.tv_nsec = 0;
3080 /* Do we have this path open ? */
3081 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3082 if (fsp1 && fsp1->pending_modtime) {
3083 /* the pending modtime overrides the current modtime */
3084 mtime_ts.tv_sec = fsp1->pending_modtime;
3085 mtime_ts.tv_nsec = 0;
3087 if (fsp1 && fsp1->initial_allocation_size) {
3088 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3092 if (lp_dos_filetime_resolution(SNUM(conn))) {
3093 dos_filetime_timespec(&create_time_ts);
3094 dos_filetime_timespec(&mtime_ts);
3095 dos_filetime_timespec(&atime_ts);
3098 create_time = convert_timespec_to_time_t(create_time_ts);
3099 mtime = convert_timespec_to_time_t(mtime_ts);
3100 atime = convert_timespec_to_time_t(atime_ts);
3102 /* NT expects the name to be in an exact form of the *full*
3103 filename. See the trans2 torture test */
3104 if (strequal(base_name,".")) {
3105 pstrcpy(dos_fname, "\\");
3107 pstr_sprintf(dos_fname, "\\%s", fname);
3108 string_replace(dos_fname, '/', '\\');
3111 switch (info_level) {
3112 case SMB_INFO_STANDARD:
3113 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3115 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3116 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3117 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3118 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3119 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3120 SSVAL(pdata,l1_attrFile,mode);
3123 case SMB_INFO_QUERY_EA_SIZE:
3125 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3126 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3128 srv_put_dos_date2(pdata,0,create_time);
3129 srv_put_dos_date2(pdata,4,atime);
3130 srv_put_dos_date2(pdata,8,mtime); /* write time */
3131 SIVAL(pdata,12,(uint32)file_size);
3132 SIVAL(pdata,16,(uint32)allocation_size);
3133 SSVAL(pdata,20,mode);
3134 SIVAL(pdata,22,ea_size);
3138 case SMB_INFO_IS_NAME_VALID:
3139 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3140 if (tran_call == TRANSACT2_QFILEINFO) {
3141 /* os/2 needs this ? really ?*/
3142 return ERROR_DOS(ERRDOS,ERRbadfunc);
3148 case SMB_INFO_QUERY_EAS_FROM_LIST:
3150 size_t total_ea_len = 0;
3151 struct ea_list *ea_file_list = NULL;
3153 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3155 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3156 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3158 if (!ea_list || (total_ea_len > data_size)) {
3159 talloc_destroy(data_ctx);
3161 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3165 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3166 talloc_destroy(data_ctx);
3170 case SMB_INFO_QUERY_ALL_EAS:
3172 /* We have data_size bytes to put EA's into. */
3173 size_t total_ea_len = 0;
3175 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3177 data_ctx = talloc_init("ea_ctx");
3179 return ERROR_NT(NT_STATUS_NO_MEMORY);
3182 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3183 if (!ea_list || (total_ea_len > data_size)) {
3184 talloc_destroy(data_ctx);
3186 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3190 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3191 talloc_destroy(data_ctx);
3195 case SMB_FILE_BASIC_INFORMATION:
3196 case SMB_QUERY_FILE_BASIC_INFO:
3198 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3199 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3200 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3202 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3206 put_long_date_timespec(pdata,create_time_ts);
3207 put_long_date_timespec(pdata+8,atime_ts);
3208 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3209 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3210 SIVAL(pdata,32,mode);
3212 DEBUG(5,("SMB_QFBI - "));
3213 DEBUG(5,("create: %s ", ctime(&create_time)));
3214 DEBUG(5,("access: %s ", ctime(&atime)));
3215 DEBUG(5,("write: %s ", ctime(&mtime)));
3216 DEBUG(5,("change: %s ", ctime(&mtime)));
3217 DEBUG(5,("mode: %x\n", mode));
3220 case SMB_FILE_STANDARD_INFORMATION:
3221 case SMB_QUERY_FILE_STANDARD_INFO:
3223 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3225 SOFF_T(pdata,0,allocation_size);
3226 SOFF_T(pdata,8,file_size);
3227 SIVAL(pdata,16,nlink);
3228 SCVAL(pdata,20,delete_pending?1:0);
3229 SCVAL(pdata,21,(mode&aDIR)?1:0);
3230 SSVAL(pdata,22,0); /* Padding. */
3233 case SMB_FILE_EA_INFORMATION:
3234 case SMB_QUERY_FILE_EA_INFO:
3236 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3237 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3239 SIVAL(pdata,0,ea_size);
3243 /* Get the 8.3 name - used if NT SMB was negotiated. */
3244 case SMB_QUERY_FILE_ALT_NAME_INFO:
3245 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3249 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3250 pstrcpy(short_name,base_name);
3251 /* Mangle if not already 8.3 */
3252 if(!mangle_is_8_3(short_name, True, conn->params)) {
3253 mangle_map(short_name,True,True,conn->params);
3255 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3256 data_size = 4 + len;
3261 case SMB_QUERY_FILE_NAME_INFO:
3263 this must be *exactly* right for ACLs on mapped drives to work
3265 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3266 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3267 data_size = 4 + len;
3271 case SMB_FILE_ALLOCATION_INFORMATION:
3272 case SMB_QUERY_FILE_ALLOCATION_INFO:
3273 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3275 SOFF_T(pdata,0,allocation_size);
3278 case SMB_FILE_END_OF_FILE_INFORMATION:
3279 case SMB_QUERY_FILE_END_OF_FILEINFO:
3280 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3282 SOFF_T(pdata,0,file_size);
3285 case SMB_QUERY_FILE_ALL_INFO:
3286 case SMB_FILE_ALL_INFORMATION:
3288 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3289 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3290 put_long_date_timespec(pdata,create_time_ts);
3291 put_long_date_timespec(pdata+8,atime_ts);
3292 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3293 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3294 SIVAL(pdata,32,mode);
3295 SIVAL(pdata,36,0); /* padding. */
3297 SOFF_T(pdata,0,allocation_size);
3298 SOFF_T(pdata,8,file_size);
3299 SIVAL(pdata,16,nlink);
3300 SCVAL(pdata,20,delete_pending);
3301 SCVAL(pdata,21,(mode&aDIR)?1:0);
3304 SIVAL(pdata,0,ea_size);
3305 pdata += 4; /* EA info */
3306 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3309 data_size = PTR_DIFF(pdata,(*ppdata));
3312 case SMB_FILE_INTERNAL_INFORMATION:
3313 /* This should be an index number - looks like
3316 I think this causes us to fail the IFSKIT
3317 BasicFileInformationTest. -tpot */
3319 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3320 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3321 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3325 case SMB_FILE_ACCESS_INFORMATION:
3326 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3327 SIVAL(pdata,0,access_mask);
3331 case SMB_FILE_NAME_INFORMATION:
3332 /* Pathname with leading '\'. */
3335 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3336 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3337 SIVAL(pdata,0,byte_len);
3338 data_size = 4 + byte_len;
3342 case SMB_FILE_DISPOSITION_INFORMATION:
3343 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3345 SCVAL(pdata,0,delete_pending);
3348 case SMB_FILE_POSITION_INFORMATION:
3349 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3351 SOFF_T(pdata,0,pos);
3354 case SMB_FILE_MODE_INFORMATION:
3355 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3356 SIVAL(pdata,0,mode);
3360 case SMB_FILE_ALIGNMENT_INFORMATION:
3361 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3362 SIVAL(pdata,0,0); /* No alignment needed. */
3368 * NT4 server just returns "invalid query" to this - if we try to answer
3369 * it then NTws gets a BSOD! (tridge).
3370 * W2K seems to want this. JRA.
3372 case SMB_QUERY_FILE_STREAM_INFO:
3374 case SMB_FILE_STREAM_INFORMATION:
3375 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3379 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3380 SIVAL(pdata,0,0); /* ??? */
3381 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3382 SOFF_T(pdata,8,file_size);
3383 SIVAL(pdata,16,allocation_size);
3384 SIVAL(pdata,20,0); /* ??? */
3385 data_size = 24 + byte_len;
3389 case SMB_QUERY_COMPRESSION_INFO:
3390 case SMB_FILE_COMPRESSION_INFORMATION:
3391 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3392 SOFF_T(pdata,0,file_size);
3393 SIVAL(pdata,8,0); /* ??? */
3394 SIVAL(pdata,12,0); /* ??? */
3398 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3399 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3400 put_long_date_timespec(pdata,create_time_ts);
3401 put_long_date_timespec(pdata+8,atime_ts);
3402 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3403 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3404 SIVAL(pdata,32,allocation_size);
3405 SOFF_T(pdata,40,file_size);
3406 SIVAL(pdata,48,mode);
3407 SIVAL(pdata,52,0); /* ??? */
3411 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3412 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3413 SIVAL(pdata,0,mode);
3419 * CIFS UNIX Extensions.
3422 case SMB_QUERY_FILE_UNIX_BASIC:
3424 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3425 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3427 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3430 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3433 put_long_date_timespec(pdata,get_ctimespec(&sbuf)); /* Creation Time 64 Bit */
3434 put_long_date_timespec(pdata+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
3435 put_long_date_timespec(pdata+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
3438 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3442 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3446 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3449 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3453 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3457 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3460 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3464 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3467 data_size = PTR_DIFF(pdata,(*ppdata));
3471 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3473 for (i=0; i<100; i++)
3474 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3480 case SMB_QUERY_FILE_UNIX_LINK:
3484 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3486 if(!S_ISLNK(sbuf.st_mode))
3487 return(UNIXERROR(ERRSRV,ERRbadlink));
3489 return(UNIXERROR(ERRDOS,ERRbadlink));
3491 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3493 return(UNIXERROR(ERRDOS,ERRnoaccess));
3495 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3497 data_size = PTR_DIFF(pdata,(*ppdata));
3502 #if defined(HAVE_POSIX_ACLS)
3503 case SMB_QUERY_POSIX_ACL:
3505 SMB_ACL_T file_acl = NULL;
3506 SMB_ACL_T def_acl = NULL;
3507 uint16 num_file_acls = 0;
3508 uint16 num_def_acls = 0;
3510 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3511 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3513 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3516 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3517 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3519 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3522 if (S_ISDIR(sbuf.st_mode)) {
3523 if (fsp && fsp->is_directory) {
3524 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3526 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3528 def_acl = free_empty_sys_acl(conn, def_acl);
3531 num_file_acls = count_acl_entries(conn, file_acl);
3532 num_def_acls = count_acl_entries(conn, def_acl);
3534 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3535 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3537 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3538 SMB_POSIX_ACL_HEADER_SIZE) ));
3540 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3543 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3545 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3548 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3549 SSVAL(pdata,2,num_file_acls);
3550 SSVAL(pdata,4,num_def_acls);
3551 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3553 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3556 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3558 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3560 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
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_INTERNAL_ERROR);
3571 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3574 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3576 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3582 case SMB_QUERY_POSIX_LOCK:
3584 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3586 SMB_BIG_UINT offset;
3588 enum brl_type lock_type;
3590 if (total_data != POSIX_LOCK_DATA_SIZE) {
3591 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3594 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3595 case POSIX_LOCK_TYPE_READ:
3596 lock_type = READ_LOCK;
3598 case POSIX_LOCK_TYPE_WRITE:
3599 lock_type = WRITE_LOCK;
3601 case POSIX_LOCK_TYPE_UNLOCK:
3603 /* There's no point in asking for an unlock... */
3604 talloc_destroy(data_ctx);
3605 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3608 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3609 #if defined(HAVE_LONGLONG)
3610 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3611 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3612 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3613 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3614 #else /* HAVE_LONGLONG */
3615 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3616 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3617 #endif /* HAVE_LONGLONG */
3619 status = query_lock(fsp,
3626 if (ERROR_WAS_LOCK_DENIED(status)) {
3627 /* Here we need to report who has it locked... */
3628 data_size = POSIX_LOCK_DATA_SIZE;
3630 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3631 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3632 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3633 #if defined(HAVE_LONGLONG)
3634 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3635 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3636 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3637 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3638 #else /* HAVE_LONGLONG */
3639 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3640 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3641 #endif /* HAVE_LONGLONG */
3643 } else if (NT_STATUS_IS_OK(status)) {
3644 /* For success we just return a copy of what we sent
3645 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3646 data_size = POSIX_LOCK_DATA_SIZE;
3647 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3648 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3650 return ERROR_NT(status);
3656 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3659 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3664 /****************************************************************************
3665 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3667 ****************************************************************************/
3669 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3671 SMB_STRUCT_STAT sbuf1, sbuf2;
3672 pstring last_component_oldname;
3673 pstring last_component_newname;
3674 NTSTATUS status = NT_STATUS_OK;
3679 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3680 if (!NT_STATUS_IS_OK(status)) {
3684 /* source must already exist. */
3685 if (!VALID_STAT(sbuf1)) {
3686 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3689 if (!check_name(oldname,conn)) {
3690 return NT_STATUS_ACCESS_DENIED;
3693 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
3694 if (!NT_STATUS_IS_OK(status)) {
3698 /* Disallow if newname already exists. */
3699 if (VALID_STAT(sbuf2)) {
3700 return NT_STATUS_OBJECT_NAME_COLLISION;
3703 if (!check_name(newname,conn)) {
3704 return NT_STATUS_ACCESS_DENIED;
3707 /* No links from a directory. */
3708 if (S_ISDIR(sbuf1.st_mode)) {
3709 return NT_STATUS_FILE_IS_A_DIRECTORY;
3712 /* Ensure this is within the share. */
3713 if (!reduce_name(conn, oldname) != 0)
3714 return NT_STATUS_ACCESS_DENIED;
3716 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3718 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3719 status = map_nt_error_from_unix(errno);
3720 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3721 nt_errstr(status), newname, oldname));
3727 /****************************************************************************
3728 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3729 ****************************************************************************/
3731 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3732 unsigned int tran_call,
3733 char **pparams, int total_params, char **ppdata, int total_data,
3734 unsigned int max_data_bytes)
3736 char *params = *pparams;
3737 char *pdata = *ppdata;
3742 SMB_STRUCT_STAT sbuf;
3745 files_struct *fsp = NULL;
3746 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3747 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3748 mode_t unixmode = 0;
3749 NTSTATUS status = NT_STATUS_OK;
3752 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3757 if (tran_call == TRANSACT2_SETFILEINFO) {
3758 if (total_params < 4) {
3759 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3762 fsp = file_fsp(params,0);
3763 info_level = SVAL(params,2);
3765 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3767 * This is actually a SETFILEINFO on a directory
3768 * handle (returned from an NT SMB). NT5.0 seems
3769 * to do this call. JRA.
3771 pstrcpy(fname, fsp->fsp_name);
3772 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3773 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3774 return UNIXERROR(ERRDOS,ERRbadpath);
3776 } else if (fsp && fsp->print_file) {
3778 * Doing a DELETE_ON_CLOSE should cancel a print job.
3780 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3781 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3783 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3786 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
3789 return (UNIXERROR(ERRDOS,ERRbadpath));
3792 * Original code - this is an open file.
3794 CHECK_FSP(fsp,conn);
3796 pstrcpy(fname, fsp->fsp_name);
3799 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3800 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3801 return(UNIXERROR(ERRDOS,ERRbadfid));
3806 if (total_params < 7) {
3807 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3810 info_level = SVAL(params,0);
3811 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3812 if (!NT_STATUS_IS_OK(status)) {
3813 return ERROR_NT(status);
3815 status = unix_convert(conn, fname, False, NULL, &sbuf);
3816 if (!NT_STATUS_IS_OK(status)) {
3817 return ERROR_NT(status);
3821 * For CIFS UNIX extensions the target name may not exist.
3824 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3825 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3826 return UNIXERROR(ERRDOS,ERRbadpath);
3829 if(!check_name(fname, conn)) {
3830 return UNIXERROR(ERRDOS,ERRbadpath);
3835 if (!CAN_WRITE(conn))
3836 return ERROR_DOS(ERRSRV,ERRaccess);
3838 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3839 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3842 if (VALID_STAT(sbuf))
3843 unixmode = sbuf.st_mode;
3845 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3846 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3848 /* Realloc the parameter size */
3849 *pparams = (char *)SMB_REALLOC(*pparams,2);
3850 if (*pparams == NULL) {
3851 return ERROR_NT(NT_STATUS_NO_MEMORY);
3857 if (fsp && fsp->pending_modtime) {
3858 /* the pending modtime overrides the current modtime */
3859 sbuf.st_mtime = fsp->pending_modtime;
3862 size = get_file_size(sbuf);
3863 tvs.modtime = sbuf.st_mtime;
3864 tvs.actime = sbuf.st_atime;
3865 dosmode = dos_mode(conn,fname,&sbuf);
3866 unixmode = sbuf.st_mode;
3868 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3869 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3871 switch (info_level) {
3872 case SMB_INFO_STANDARD:
3874 if (total_data < 12) {
3875 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3879 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3881 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3885 case SMB_INFO_SET_EA:
3887 struct ea_list *ea_list = NULL;
3888 TALLOC_CTX *ctx = NULL;
3890 if (total_data < 10) {
3892 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3893 length. They seem to have no effect. Bug #3212. JRA */
3895 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3896 /* We're done. We only get EA info in this call. */
3898 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
3902 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3905 if (IVAL(pdata,0) > total_data) {
3906 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3907 IVAL(pdata,0), (unsigned int)total_data));
3908 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3911 ctx = talloc_init("SMB_INFO_SET_EA");
3913 return ERROR_NT(NT_STATUS_NO_MEMORY);
3915 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3917 talloc_destroy(ctx);
3918 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3920 status = set_ea(conn, fsp, fname, ea_list);
3921 talloc_destroy(ctx);
3923 if (!NT_STATUS_IS_OK(status)) {
3924 return ERROR_NT(status);
3927 /* We're done. We only get EA info in this call. */
3929 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
3934 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3935 /* XXXX um, i don't think this is right.
3936 it's also not in the cifs6.txt spec.
3938 case SMB_INFO_QUERY_EAS_FROM_LIST:
3939 if (total_data < 28)
3940 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3942 tvs.actime = make_unix_date2(pdata+8);
3943 tvs.modtime = make_unix_date2(pdata+12);
3944 size = IVAL(pdata,16);
3945 dosmode = IVAL(pdata,24);
3948 /* XXXX nor this. not in cifs6.txt, either. */
3949 case SMB_INFO_QUERY_ALL_EAS:
3950 if (total_data < 28)
3951 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3953 tvs.actime = make_unix_date2(pdata+8);
3954 tvs.modtime = make_unix_date2(pdata+12);
3955 size = IVAL(pdata,16);
3956 dosmode = IVAL(pdata,24);
3960 case SMB_SET_FILE_BASIC_INFO:
3961 case SMB_FILE_BASIC_INFORMATION:
3963 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3965 time_t changed_time;
3967 if (total_data < 36) {
3968 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3971 /* Ignore create time at offset pdata. */
3974 tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
3976 write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
3977 changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
3979 tvs.modtime = MIN(write_time, changed_time);
3981 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3982 tvs.modtime = write_time;
3984 /* Prefer a defined time to an undefined one. */
3985 if (null_mtime(tvs.modtime)) {
3986 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3990 dosmode = IVAL(pdata,32);
3994 case SMB_FILE_ALLOCATION_INFORMATION:
3995 case SMB_SET_FILE_ALLOCATION_INFO:
3998 SMB_BIG_UINT allocation_size;
4000 if (total_data < 8) {
4001 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4004 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4005 #ifdef LARGE_SMB_OFF_T
4006 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4007 #else /* LARGE_SMB_OFF_T */
4008 if (IVAL(pdata,4) != 0) {
4009 /* more than 32 bits? */
4010 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4012 #endif /* LARGE_SMB_OFF_T */
4013 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4014 fname, (double)allocation_size ));
4016 if (allocation_size) {
4017 allocation_size = smb_roundup(conn, allocation_size);
4020 if(allocation_size != get_file_size(sbuf)) {
4021 SMB_STRUCT_STAT new_sbuf;
4023 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4024 fname, (double)allocation_size ));
4027 files_struct *new_fsp = NULL;
4029 status = open_file_ntcreate(conn, fname, &sbuf,
4031 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4034 FILE_ATTRIBUTE_NORMAL,
4035 FORCE_OPLOCK_BREAK_TO_NONE,
4038 if (!NT_STATUS_IS_OK(status)) {
4039 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4040 /* We have re-scheduled this call. */
4043 return(UNIXERROR(ERRDOS,ERRnoaccess));
4045 ret = vfs_allocate_file_space(new_fsp, allocation_size);
4046 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4047 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4048 new_fsp->fnum, strerror(errno)));
4051 close_file(new_fsp,NORMAL_CLOSE);
4053 ret = vfs_allocate_file_space(fsp, allocation_size);
4054 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4055 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4056 fsp->fnum, strerror(errno)));
4061 return ERROR_NT(NT_STATUS_DISK_FULL);
4063 /* Allocate can truncate size... */
4064 size = get_file_size(new_sbuf);
4070 case SMB_FILE_END_OF_FILE_INFORMATION:
4071 case SMB_SET_FILE_END_OF_FILE_INFO:
4073 if (total_data < 8) {
4074 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4077 size = IVAL(pdata,0);
4078 #ifdef LARGE_SMB_OFF_T
4079 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4080 #else /* LARGE_SMB_OFF_T */
4081 if (IVAL(pdata,4) != 0) {
4082 /* more than 32 bits? */
4083 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4085 #endif /* LARGE_SMB_OFF_T */
4086 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4090 case SMB_FILE_DISPOSITION_INFORMATION:
4091 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4093 BOOL delete_on_close;
4095 if (total_data < 1) {
4096 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4099 delete_on_close = (CVAL(pdata,0) ? True : False);
4101 /* Just ignore this set on a path. */
4102 if (tran_call != TRANSACT2_SETFILEINFO)
4106 return(UNIXERROR(ERRDOS,ERRbadfid));
4108 status = can_set_delete_on_close(fsp, delete_on_close,
4111 if (!NT_STATUS_IS_OK(status)) {
4112 return ERROR_NT(status);
4115 /* The set is across all open files on this dev/inode pair. */
4116 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4117 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4121 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4125 case SMB_FILE_POSITION_INFORMATION:
4127 SMB_BIG_UINT position_information;
4129 if (total_data < 8) {
4130 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4133 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4134 #ifdef LARGE_SMB_OFF_T
4135 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4136 #else /* LARGE_SMB_OFF_T */
4137 if (IVAL(pdata,4) != 0) {
4138 /* more than 32 bits? */
4139 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4141 #endif /* LARGE_SMB_OFF_T */
4142 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4143 fname, (double)position_information ));
4145 fsp->fh->position_information = position_information;
4148 /* We're done. We only get position info in this call. */
4150 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4154 /* From tridge Samba4 :
4155 * MODE_INFORMATION in setfileinfo (I have no
4156 * idea what "mode information" on a file is - it takes a value of 0,
4157 * 2, 4 or 6. What could it be?).
4160 case SMB_FILE_MODE_INFORMATION:
4164 if (total_data < 4) {
4165 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4167 mode = IVAL(pdata,0);
4168 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4169 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4172 /* We're done. We only get mode info in this call. */
4174 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4179 * CIFS UNIX extensions.
4182 case SMB_SET_FILE_UNIX_BASIC:
4184 uint32 raw_unixmode;
4186 if (total_data < 100) {
4187 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4190 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4191 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4192 size=IVAL(pdata,0); /* first 8 Bytes are size */
4193 #ifdef LARGE_SMB_OFF_T
4194 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4195 #else /* LARGE_SMB_OFF_T */
4196 if (IVAL(pdata,4) != 0) {
4197 /* more than 32 bits? */
4198 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4200 #endif /* LARGE_SMB_OFF_T */
4202 pdata+=24; /* ctime & st_blocks are not changed */
4203 tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */
4204 tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */
4206 set_owner = (uid_t)IVAL(pdata,0);
4208 set_grp = (gid_t)IVAL(pdata,0);
4210 raw_unixmode = IVAL(pdata,28);
4211 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4212 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4214 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4215 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4216 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4218 if (!VALID_STAT(sbuf)) {
4221 * The only valid use of this is to create character and block
4222 * devices, and named pipes. This is deprecated (IMHO) and
4223 * a new info level should be used for mknod. JRA.
4226 uint32 file_type = IVAL(pdata,0);
4227 #if defined(HAVE_MAKEDEV)
4228 uint32 dev_major = IVAL(pdata,4);
4229 uint32 dev_minor = IVAL(pdata,12);
4232 uid_t myuid = geteuid();
4233 gid_t mygid = getegid();
4234 SMB_DEV_T dev = (SMB_DEV_T)0;
4236 if (tran_call == TRANSACT2_SETFILEINFO)
4237 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4239 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4240 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4243 #if defined(HAVE_MAKEDEV)
4244 dev = makedev(dev_major, dev_minor);
4247 /* We can only create as the owner/group we are. */
4249 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4250 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4251 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4252 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4254 switch (file_type) {
4255 #if defined(S_IFIFO)
4256 case UNIX_TYPE_FIFO:
4257 unixmode |= S_IFIFO;
4260 #if defined(S_IFSOCK)
4261 case UNIX_TYPE_SOCKET:
4262 unixmode |= S_IFSOCK;
4265 #if defined(S_IFCHR)
4266 case UNIX_TYPE_CHARDEV:
4267 unixmode |= S_IFCHR;
4270 #if defined(S_IFBLK)
4271 case UNIX_TYPE_BLKDEV:
4272 unixmode |= S_IFBLK;
4276 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4279 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4280 0%o for file %s\n", (double)dev, unixmode, fname ));
4282 /* Ok - do the mknod. */
4283 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4284 return(UNIXERROR(ERRDOS,ERRnoaccess));
4286 if (lp_inherit_perms(SNUM(conn))) {
4288 conn, parent_dirname(fname),
4293 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4298 * Deal with the UNIX specific mode set.
4301 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4302 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4303 (unsigned int)unixmode, fname ));
4304 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4305 return(UNIXERROR(ERRDOS,ERRnoaccess));
4309 * Deal with the UNIX specific uid set.
4312 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4313 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4314 (unsigned int)set_owner, fname ));
4315 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4316 return(UNIXERROR(ERRDOS,ERRnoaccess));
4320 * Deal with the UNIX specific gid set.
4323 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4324 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4325 (unsigned int)set_owner, fname ));
4326 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4327 return(UNIXERROR(ERRDOS,ERRnoaccess));
4332 case SMB_SET_FILE_UNIX_LINK:
4334 pstring link_target;
4335 char *newname = fname;
4337 /* Set a symbolic link. */
4338 /* Don't allow this if follow links is false. */
4340 if (total_data == 0) {
4341 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4344 if (!lp_symlinks(SNUM(conn)))
4345 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4347 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4349 /* !widelinks forces the target path to be within the share. */
4350 /* This means we can interpret the target as a pathname. */
4351 if (!lp_widelinks(SNUM(conn))) {
4353 char *last_dirp = NULL;
4355 unix_format(link_target);
4356 if (*link_target == '/') {
4357 /* No absolute paths allowed. */
4358 return(UNIXERROR(ERRDOS,ERRnoaccess));
4360 pstrcpy(rel_name, newname);
4361 last_dirp = strrchr_m(rel_name, '/');
4363 last_dirp[1] = '\0';
4365 pstrcpy(rel_name, "./");
4367 pstrcat(rel_name, link_target);
4369 if (!check_name(rel_name, conn)) {
4370 return(UNIXERROR(ERRDOS,ERRnoaccess));
4374 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4375 fname, link_target ));
4377 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4378 return(UNIXERROR(ERRDOS,ERRnoaccess));
4380 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4384 case SMB_SET_FILE_UNIX_HLINK:
4387 char *newname = fname;
4389 /* Set a hard link. */
4390 if (total_data == 0) {
4391 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4394 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4395 if (!NT_STATUS_IS_OK(status)) {
4396 return ERROR_NT(status);
4399 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4402 status = hardlink_internals(conn, oldname, newname);
4403 if (!NT_STATUS_IS_OK(status)) {
4404 return ERROR_NT(status);
4408 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4412 case SMB_FILE_RENAME_INFORMATION:
4415 /* uint32 root_fid; */ /* Not used */
4421 if (total_data < 13) {
4422 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4425 overwrite = (CVAL(pdata,0) ? True : False);
4426 /* root_fid = IVAL(pdata,4); */
4427 len = IVAL(pdata,8);
4429 if (len > (total_data - 12) || (len == 0)) {
4430 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4433 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4434 if (!NT_STATUS_IS_OK(status)) {
4435 return ERROR_NT(status);
4438 /* Check the new name has no '/' characters. */
4439 if (strchr_m(newname, '/'))
4440 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4442 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4444 /* Create the base directory. */
4445 pstrcpy(base_name, fname);
4446 p = strrchr_m(base_name, '/');
4449 /* Append the new name. */
4450 pstrcat(base_name, "/");
4451 pstrcat(base_name, newname);
4454 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4455 fsp->fnum, fsp->fsp_name, base_name ));
4456 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4458 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4460 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4463 if (!NT_STATUS_IS_OK(status)) {
4464 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4465 /* We have re-scheduled this call. */
4468 return ERROR_NT(status);
4471 process_pending_change_notify_queue((time_t)0);
4473 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4477 #if defined(HAVE_POSIX_ACLS)
4478 case SMB_SET_POSIX_ACL:
4480 uint16 posix_acl_version;
4481 uint16 num_file_acls;
4482 uint16 num_def_acls;
4483 BOOL valid_file_acls = True;
4484 BOOL valid_def_acls = True;
4486 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4487 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4489 posix_acl_version = SVAL(pdata,0);
4490 num_file_acls = SVAL(pdata,2);
4491 num_def_acls = SVAL(pdata,4);
4493 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4494 valid_file_acls = False;
4498 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4499 valid_def_acls = False;
4503 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4504 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4507 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4508 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4509 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4512 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4513 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4514 return(UNIXERROR(ERRDOS,ERRnoaccess));
4517 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4518 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4519 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4520 return(UNIXERROR(ERRDOS,ERRnoaccess));
4524 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4529 case SMB_SET_POSIX_LOCK:
4532 SMB_BIG_UINT offset;
4534 BOOL blocking_lock = False;
4535 enum brl_type lock_type;
4537 if (fsp == NULL || fsp->fh->fd == -1) {
4538 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4541 if (total_data != POSIX_LOCK_DATA_SIZE) {
4542 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4545 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4546 case POSIX_LOCK_TYPE_READ:
4547 lock_type = READ_LOCK;
4549 case POSIX_LOCK_TYPE_WRITE:
4550 /* Return the right POSIX-mappable error code for files opened read-only. */
4551 if (!fsp->can_write) {
4552 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4554 lock_type = WRITE_LOCK;
4556 case POSIX_LOCK_TYPE_UNLOCK:
4557 lock_type = UNLOCK_LOCK;
4560 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4563 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4564 blocking_lock = False;
4565 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4566 blocking_lock = True;
4568 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4571 if (!lp_blocking_locks(SNUM(conn))) {
4572 blocking_lock = False;
4575 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4576 #if defined(HAVE_LONGLONG)
4577 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4578 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4579 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4580 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4581 #else /* HAVE_LONGLONG */
4582 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4583 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4584 #endif /* HAVE_LONGLONG */
4586 if (lock_type == UNLOCK_LOCK) {
4587 status = do_unlock(fsp,
4593 struct byte_range_lock *br_lck = do_lock(fsp,
4602 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4604 * A blocking lock was requested. Package up
4605 * this smb into a queued request and push it
4606 * onto the blocking lock queue.
4608 if(push_blocking_lock_request(br_lck,
4611 -1, /* infinite timeout. */
4618 TALLOC_FREE(br_lck);
4622 TALLOC_FREE(br_lck);
4625 if (!NT_STATUS_IS_OK(status)) {
4626 return ERROR_NT(status);
4630 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4635 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4638 /* get some defaults (no modifications) if any info is zero or -1. */
4639 if (null_mtime(tvs.actime)) {
4640 tvs.actime = sbuf.st_atime;
4643 if (null_mtime(tvs.modtime)) {
4644 tvs.modtime = sbuf.st_mtime;
4647 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4648 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4649 DEBUG(6,("size: %.0f ", (double)size));
4652 if (S_ISDIR(sbuf.st_mode))
4658 DEBUG(6,("dosmode: %x\n" , dosmode));
4660 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4661 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4662 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4663 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4666 * Only do this test if we are not explicitly
4667 * changing the size of a file.
4670 size = get_file_size(sbuf);
4674 * Try and set the times, size and mode of this file -
4675 * if they are different from the current values
4678 /* check the mode isn't different, before changing it */
4679 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4681 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4683 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4684 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4685 return(UNIXERROR(ERRDOS,ERRnoaccess));
4690 if (size != get_file_size(sbuf)) {
4694 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4695 fname, (double)size ));
4698 files_struct *new_fsp = NULL;
4700 status = open_file_ntcreate(conn, fname, &sbuf,
4702 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4705 FILE_ATTRIBUTE_NORMAL,
4706 FORCE_OPLOCK_BREAK_TO_NONE,
4709 if (!NT_STATUS_IS_OK(status)) {
4710 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4711 /* We have re-scheduled this call. */
4714 return(UNIXERROR(ERRDOS,ERRnoaccess));
4716 ret = vfs_set_filelen(new_fsp, size);
4717 close_file(new_fsp,NORMAL_CLOSE);
4719 ret = vfs_set_filelen(fsp, size);
4723 return (UNIXERROR(ERRHRD,ERRdiskfull));
4728 * Finally the times.
4730 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4733 * This was a setfileinfo on an open file.
4734 * NT does this a lot. We also need to
4735 * set the time here, as it can be read by
4736 * FindFirst/FindNext and with the patch for bug #2045
4737 * in smbd/fileio.c it ensures that this timestamp is
4738 * kept sticky even after a write. We save the request
4739 * away and will set it on file close and after a write. JRA.
4742 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4743 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4744 fsp_set_pending_modtime(fsp, tvs.modtime);
4748 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4750 if(file_utime(conn, fname, &tvs)!=0) {
4751 return(UNIXERROR(ERRDOS,ERRnoaccess));
4756 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4761 /****************************************************************************
4762 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4763 ****************************************************************************/
4765 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4766 char **pparams, int total_params, char **ppdata, int total_data,
4767 unsigned int max_data_bytes)
4769 char *params = *pparams;
4770 char *pdata = *ppdata;
4772 SMB_STRUCT_STAT sbuf;
4773 NTSTATUS status = NT_STATUS_OK;
4774 struct ea_list *ea_list = NULL;
4776 if (!CAN_WRITE(conn))
4777 return ERROR_DOS(ERRSRV,ERRaccess);
4779 if (total_params < 5) {
4780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4783 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
4784 if (!NT_STATUS_IS_OK(status)) {
4785 return ERROR_NT(status);
4788 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4790 status = unix_convert(conn, directory, False, NULL, &sbuf);
4791 if (!NT_STATUS_IS_OK(status)) {
4792 return ERROR_NT(status);
4795 /* Any data in this call is an EA list. */
4796 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4797 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4801 * OS/2 workplace shell seems to send SET_EA requests of "null"
4802 * length (4 bytes containing IVAL 4).
4803 * They seem to have no effect. Bug #3212. JRA.
4806 if (total_data != 4) {
4807 if (total_data < 10) {
4808 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4811 if (IVAL(pdata,0) > total_data) {
4812 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4813 IVAL(pdata,0), (unsigned int)total_data));
4814 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4817 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
4820 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4822 } else if (IVAL(pdata,0) != 4) {
4823 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4826 if (!check_name(directory,conn)) {
4827 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4828 return UNIXERROR(ERRDOS, ERRnoaccess);
4831 status = create_directory(conn, directory);
4833 if (!NT_STATUS_IS_OK(status)) {
4834 return ERROR_NT(status);
4837 /* Try and set any given EA. */
4839 status = set_ea(conn, NULL, directory, ea_list);
4840 if (!NT_STATUS_IS_OK(status)) {
4841 return ERROR_NT(status);
4845 /* Realloc the parameter and data sizes */
4846 *pparams = (char *)SMB_REALLOC(*pparams,2);
4847 if(*pparams == NULL) {
4848 return ERROR_NT(NT_STATUS_NO_MEMORY);
4854 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4859 /****************************************************************************
4860 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4861 We don't actually do this - we just send a null response.
4862 ****************************************************************************/
4864 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4865 char **pparams, int total_params, char **ppdata, int total_data,
4866 unsigned int max_data_bytes)
4868 static uint16 fnf_handle = 257;
4869 char *params = *pparams;
4872 if (total_params < 6) {
4873 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4876 info_level = SVAL(params,4);
4877 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4879 switch (info_level) {
4884 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4887 /* Realloc the parameter and data sizes */
4888 *pparams = (char *)SMB_REALLOC(*pparams,6);
4889 if (*pparams == NULL) {
4890 return ERROR_NT(NT_STATUS_NO_MEMORY);
4894 SSVAL(params,0,fnf_handle);
4895 SSVAL(params,2,0); /* No changes */
4896 SSVAL(params,4,0); /* No EA errors */
4903 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
4908 /****************************************************************************
4909 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4910 changes). Currently this does nothing.
4911 ****************************************************************************/
4913 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4914 char **pparams, int total_params, char **ppdata, int total_data,
4915 unsigned int max_data_bytes)
4917 char *params = *pparams;
4919 DEBUG(3,("call_trans2findnotifynext\n"));
4921 /* Realloc the parameter and data sizes */
4922 *pparams = (char *)SMB_REALLOC(*pparams,4);
4923 if (*pparams == NULL) {
4924 return ERROR_NT(NT_STATUS_NO_MEMORY);
4928 SSVAL(params,0,0); /* No changes */
4929 SSVAL(params,2,0); /* No EA errors */
4931 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
4936 /****************************************************************************
4937 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4938 ****************************************************************************/
4940 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4941 char **pparams, int total_params, char **ppdata, int total_data,
4942 unsigned int max_data_bytes)
4944 char *params = *pparams;
4947 int max_referral_level;
4949 DEBUG(10,("call_trans2getdfsreferral\n"));
4951 if (total_params < 3) {
4952 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4955 max_referral_level = SVAL(params,0);
4957 if(!lp_host_msdfs())
4958 return ERROR_DOS(ERRDOS,ERRbadfunc);
4960 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
4961 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4962 return UNIXERROR(ERRDOS,ERRbadfile);
4964 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4965 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
4970 #define LMCAT_SPL 0x53
4971 #define LMFUNC_GETJOBID 0x60
4973 /****************************************************************************
4974 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4975 ****************************************************************************/
4977 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4978 char **pparams, int total_params, char **ppdata, int total_data,
4979 unsigned int max_data_bytes)
4981 char *pdata = *ppdata;
4982 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4984 /* check for an invalid fid before proceeding */
4987 return(ERROR_DOS(ERRDOS,ERRbadfid));
4989 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4990 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4991 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
4992 if (*ppdata == NULL) {
4993 return ERROR_NT(NT_STATUS_NO_MEMORY);
4997 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4998 CAN ACCEPT THIS IN UNICODE. JRA. */
5000 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
5001 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5002 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5003 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5006 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5007 return ERROR_DOS(ERRSRV,ERRerror);
5011 /****************************************************************************
5012 Reply to a SMBfindclose (stop trans2 directory search).
5013 ****************************************************************************/
5015 int reply_findclose(connection_struct *conn,
5016 char *inbuf,char *outbuf,int length,int bufsize)
5019 int dptr_num=SVALS(inbuf,smb_vwv0);
5020 START_PROFILE(SMBfindclose);
5022 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5024 dptr_close(&dptr_num);
5026 outsize = set_message(outbuf,0,0,False);
5028 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5030 END_PROFILE(SMBfindclose);
5034 /****************************************************************************
5035 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5036 ****************************************************************************/
5038 int reply_findnclose(connection_struct *conn,
5039 char *inbuf,char *outbuf,int length,int bufsize)
5043 START_PROFILE(SMBfindnclose);
5045 dptr_num = SVAL(inbuf,smb_vwv0);
5047 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5049 /* We never give out valid handles for a
5050 findnotifyfirst - so any dptr_num is ok here.
5053 outsize = set_message(outbuf,0,0,False);
5055 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5057 END_PROFILE(SMBfindnclose);
5061 int handle_trans2(connection_struct *conn,
5062 struct trans_state *state,
5063 char *inbuf, char *outbuf, int size, int bufsize)
5067 if (Protocol >= PROTOCOL_NT1) {
5068 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5071 /* Now we must call the relevant TRANS2 function */
5072 switch(state->call) {
5073 case TRANSACT2_OPEN:
5075 START_PROFILE_NESTED(Trans2_open);
5076 outsize = call_trans2open(
5077 conn, inbuf, outbuf, bufsize,
5078 &state->param, state->total_param,
5079 &state->data, state->total_data,
5080 state->max_data_return);
5081 END_PROFILE_NESTED(Trans2_open);
5085 case TRANSACT2_FINDFIRST:
5087 START_PROFILE_NESTED(Trans2_findfirst);
5088 outsize = call_trans2findfirst(
5089 conn, inbuf, outbuf, bufsize,
5090 &state->param, state->total_param,
5091 &state->data, state->total_data,
5092 state->max_data_return);
5093 END_PROFILE_NESTED(Trans2_findfirst);
5097 case TRANSACT2_FINDNEXT:
5099 START_PROFILE_NESTED(Trans2_findnext);
5100 outsize = call_trans2findnext(
5101 conn, inbuf, outbuf, size, bufsize,
5102 &state->param, state->total_param,
5103 &state->data, state->total_data,
5104 state->max_data_return);
5105 END_PROFILE_NESTED(Trans2_findnext);
5109 case TRANSACT2_QFSINFO:
5111 START_PROFILE_NESTED(Trans2_qfsinfo);
5112 outsize = call_trans2qfsinfo(
5113 conn, inbuf, outbuf, size, bufsize,
5114 &state->param, state->total_param,
5115 &state->data, state->total_data,
5116 state->max_data_return);
5117 END_PROFILE_NESTED(Trans2_qfsinfo);
5121 case TRANSACT2_SETFSINFO:
5123 START_PROFILE_NESTED(Trans2_setfsinfo);
5124 outsize = call_trans2setfsinfo(
5125 conn, inbuf, outbuf, size, bufsize,
5126 &state->param, state->total_param,
5127 &state->data, state->total_data,
5128 state->max_data_return);
5129 END_PROFILE_NESTED(Trans2_setfsinfo);
5133 case TRANSACT2_QPATHINFO:
5134 case TRANSACT2_QFILEINFO:
5136 START_PROFILE_NESTED(Trans2_qpathinfo);
5137 outsize = call_trans2qfilepathinfo(
5138 conn, inbuf, outbuf, size, bufsize, state->call,
5139 &state->param, state->total_param,
5140 &state->data, state->total_data,
5141 state->max_data_return);
5142 END_PROFILE_NESTED(Trans2_qpathinfo);
5146 case TRANSACT2_SETPATHINFO:
5147 case TRANSACT2_SETFILEINFO:
5149 START_PROFILE_NESTED(Trans2_setpathinfo);
5150 outsize = call_trans2setfilepathinfo(
5151 conn, inbuf, outbuf, size, bufsize, state->call,
5152 &state->param, state->total_param,
5153 &state->data, state->total_data,
5154 state->max_data_return);
5155 END_PROFILE_NESTED(Trans2_setpathinfo);
5159 case TRANSACT2_FINDNOTIFYFIRST:
5161 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5162 outsize = call_trans2findnotifyfirst(
5163 conn, inbuf, outbuf, size, bufsize,
5164 &state->param, state->total_param,
5165 &state->data, state->total_data,
5166 state->max_data_return);
5167 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5171 case TRANSACT2_FINDNOTIFYNEXT:
5173 START_PROFILE_NESTED(Trans2_findnotifynext);
5174 outsize = call_trans2findnotifynext(
5175 conn, inbuf, outbuf, size, bufsize,
5176 &state->param, state->total_param,
5177 &state->data, state->total_data,
5178 state->max_data_return);
5179 END_PROFILE_NESTED(Trans2_findnotifynext);
5183 case TRANSACT2_MKDIR:
5185 START_PROFILE_NESTED(Trans2_mkdir);
5186 outsize = call_trans2mkdir(
5187 conn, inbuf, outbuf, size, bufsize,
5188 &state->param, state->total_param,
5189 &state->data, state->total_data,
5190 state->max_data_return);
5191 END_PROFILE_NESTED(Trans2_mkdir);
5195 case TRANSACT2_GET_DFS_REFERRAL:
5197 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5198 outsize = call_trans2getdfsreferral(
5199 conn, inbuf, outbuf, size, bufsize,
5200 &state->param, state->total_param,
5201 &state->data, state->total_data,
5202 state->max_data_return);
5203 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5207 case TRANSACT2_IOCTL:
5209 START_PROFILE_NESTED(Trans2_ioctl);
5210 outsize = call_trans2ioctl(
5211 conn, inbuf, outbuf, size, bufsize,
5212 &state->param, state->total_param,
5213 &state->data, state->total_data,
5214 state->max_data_return);
5215 END_PROFILE_NESTED(Trans2_ioctl);
5220 /* Error in request */
5221 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5222 outsize = ERROR_DOS(ERRSRV,ERRerror);
5228 /****************************************************************************
5229 Reply to a SMBtrans2.
5230 ****************************************************************************/
5232 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5233 int size, int bufsize)
5236 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5237 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5238 unsigned int psoff = SVAL(inbuf, smb_psoff);
5239 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5240 unsigned int tran_call = SVAL(inbuf, smb_setup0);
5241 struct trans_state *state;
5244 START_PROFILE(SMBtrans2);
5246 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5247 if (!NT_STATUS_IS_OK(result)) {
5248 DEBUG(2, ("Got invalid trans2 request: %s\n",
5249 nt_errstr(result)));
5250 END_PROFILE(SMBtrans2);
5251 return ERROR_NT(result);
5254 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5255 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5256 END_PROFILE(SMBtrans2);
5257 return ERROR_DOS(ERRSRV,ERRaccess);
5260 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
5261 DEBUG(0, ("talloc failed\n"));
5262 END_PROFILE(SMBtrans2);
5263 return ERROR_NT(NT_STATUS_NO_MEMORY);
5266 state->cmd = SMBtrans2;
5268 state->mid = SVAL(inbuf, smb_mid);
5269 state->vuid = SVAL(inbuf, smb_uid);
5270 state->setup_count = SVAL(inbuf, smb_suwcnt);
5271 state->setup = NULL;
5272 state->total_param = SVAL(inbuf, smb_tpscnt);
5273 state->param = NULL;
5274 state->total_data = SVAL(inbuf, smb_tdscnt);
5276 state->max_param_return = SVAL(inbuf, smb_mprcnt);
5277 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
5278 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5279 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5280 state->one_way = BITSETW(inbuf+smb_vwv5,1);
5282 state->call = tran_call;
5284 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5285 is so as a sanity check */
5286 if (state->setup_count != 1) {
5288 * Need to have rc=0 for ioctl to get job id for OS/2.
5289 * Network printing will fail if function is not successful.
5290 * Similar function in reply.c will be used if protocol
5291 * is LANMAN1.0 instead of LM1.2X002.
5292 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5293 * outbuf doesn't have to be set(only job id is used).
5295 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5296 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5297 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5298 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5300 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5301 DEBUG(2,("Transaction is %d\n",tran_call));
5303 END_PROFILE(SMBtrans2);
5304 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5308 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5311 if (state->total_data) {
5312 /* Can't use talloc here, the core routines do realloc on the
5313 * params and data. */
5314 state->data = (char *)SMB_MALLOC(state->total_data);
5315 if (state->data == NULL) {
5316 DEBUG(0,("reply_trans2: data malloc fail for %u "
5317 "bytes !\n", (unsigned int)state->total_data));
5319 END_PROFILE(SMBtrans2);
5320 return(ERROR_DOS(ERRDOS,ERRnomem));
5322 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5324 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5325 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5328 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5331 if (state->total_param) {
5332 /* Can't use talloc here, the core routines do realloc on the
5333 * params and data. */
5334 state->param = (char *)SMB_MALLOC(state->total_param);
5335 if (state->param == NULL) {
5336 DEBUG(0,("reply_trans: param malloc fail for %u "
5337 "bytes !\n", (unsigned int)state->total_param));
5338 SAFE_FREE(state->data);
5340 END_PROFILE(SMBtrans2);
5341 return(ERROR_DOS(ERRDOS,ERRnomem));
5343 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5345 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5346 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5349 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5352 state->received_data = dscnt;
5353 state->received_param = pscnt;
5355 if ((state->received_param == state->total_param) &&
5356 (state->received_data == state->total_data)) {
5358 outsize = handle_trans2(conn, state, inbuf, outbuf,
5360 SAFE_FREE(state->data);
5361 SAFE_FREE(state->param);
5363 END_PROFILE(SMBtrans2);
5367 DLIST_ADD(conn->pending_trans, state);
5369 /* We need to send an interim response then receive the rest
5370 of the parameter/data bytes */
5371 outsize = set_message(outbuf,0,0,False);
5373 END_PROFILE(SMBtrans2);
5378 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5379 SAFE_FREE(state->data);
5380 SAFE_FREE(state->param);
5382 END_PROFILE(SMBtrans2);
5383 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5387 /****************************************************************************
5388 Reply to a SMBtranss2
5389 ****************************************************************************/
5391 int reply_transs2(connection_struct *conn,
5392 char *inbuf,char *outbuf,int size,int bufsize)
5395 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5396 struct trans_state *state;
5398 START_PROFILE(SMBtranss2);
5402 for (state = conn->pending_trans; state != NULL;
5403 state = state->next) {
5404 if (state->mid == SVAL(inbuf,smb_mid)) {
5409 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5410 END_PROFILE(SMBtranss2);
5411 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5414 /* Revise state->total_param and state->total_data in case they have
5415 changed downwards */
5417 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5418 state->total_param = SVAL(inbuf, smb_tpscnt);
5419 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5420 state->total_data = SVAL(inbuf, smb_tdscnt);
5422 pcnt = SVAL(inbuf, smb_spscnt);
5423 poff = SVAL(inbuf, smb_spsoff);
5424 pdisp = SVAL(inbuf, smb_spsdisp);
5426 dcnt = SVAL(inbuf, smb_sdscnt);
5427 doff = SVAL(inbuf, smb_sdsoff);
5428 ddisp = SVAL(inbuf, smb_sdsdisp);
5430 state->received_param += pcnt;
5431 state->received_data += dcnt;
5433 if ((state->received_data > state->total_data) ||
5434 (state->received_param > state->total_param))
5438 if (pdisp+pcnt > state->total_param)
5440 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5442 if (pdisp > state->total_param)
5444 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5445 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5447 if (state->param + pdisp < state->param)
5450 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5455 if (ddisp+dcnt > state->total_data)
5457 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5459 if (ddisp > state->total_data)
5461 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5462 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5464 if (state->data + ddisp < state->data)
5467 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5471 if ((state->received_param < state->total_param) ||
5472 (state->received_data < state->total_data)) {
5473 END_PROFILE(SMBtranss2);
5477 /* construct_reply_common has done us the favor to pre-fill the
5478 * command field with SMBtranss2 which is wrong :-)
5480 SCVAL(outbuf,smb_com,SMBtrans2);
5482 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5484 DLIST_REMOVE(conn->pending_trans, state);
5485 SAFE_FREE(state->data);
5486 SAFE_FREE(state->param);
5490 END_PROFILE(SMBtranss2);
5491 return(ERROR_DOS(ERRSRV,ERRnosupport));
5494 END_PROFILE(SMBtranss2);
5499 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5500 DLIST_REMOVE(conn->pending_trans, state);
5501 SAFE_FREE(state->data);
5502 SAFE_FREE(state->param);
5504 END_PROFILE(SMBtranss2);
5505 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);