2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct *conn,
41 const SMB_STRUCT_STAT *psbuf);
43 static char *store_file_unix_basic_info2(connection_struct *conn,
46 const SMB_STRUCT_STAT *psbuf);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
55 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type = get_remote_arch();
59 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60 val = SMB_ROUNDUP(val,rval);
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
68 ********************************************************************/
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
74 if(S_ISDIR(sbuf->st_mode)) {
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
81 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
84 if (fsp && fsp->initial_allocation_size)
85 ret = MAX(ret,fsp->initial_allocation_size);
87 return smb_roundup(conn, ret);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120 const char *fname, char *ea_name, struct ea_struct *pea)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size = 256;
129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 if (fsp && fsp->fh->fd != -1) {
135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150 dump_data(10, (uint8 *)val, sizeret);
153 if (strnequal(ea_name, "user.", 5)) {
154 pea->name = &ea_name[5];
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168 const char *fname, size_t *pea_total_len)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size = 1024;
176 struct ea_list *ea_list_head = NULL;
180 if (!lp_ea_support(SNUM(conn))) {
184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
191 if (fsp && fsp->fh->fd != -1) {
192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
197 if (sizeret == -1 && errno == ERANGE) {
198 ea_namelist_size *= 2;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211 struct ea_list *listp;
213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
216 listp = TALLOC_P(mem_ctx, struct ea_list);
220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
226 push_ascii_fstring(dos_ea_name, listp->ea.name);
227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len, dos_ea_name,
230 (unsigned int)listp->ea.value.length ));
232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
234 /* Add on 4 for total length. */
235 if (*pea_total_len) {
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250 connection_struct *conn, struct ea_list *ea_list)
252 unsigned int ret_data_size = 4;
255 SMB_ASSERT(total_data_size >= 4);
257 if (!lp_ea_support(SNUM(conn))) {
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
270 if (ea_list->ea.value.length > 65535) {
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290 SIVAL(pdata,0,ret_data_size);
291 return ret_data_size;
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
296 size_t total_ea_len = 0;
297 TALLOC_CTX *mem_ctx = NULL;
299 if (!lp_ea_support(SNUM(conn))) {
302 mem_ctx = talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304 talloc_destroy(mem_ctx);
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
318 for (; ea_list; ea_list = ea_list->next) {
319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name[5], ea_list->ea.name));
322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
326 talloc_destroy(mem_ctx);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
335 if (!lp_ea_support(SNUM(conn))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED;
339 for (;ea_list; ea_list = ea_list->next) {
341 fstring unix_ea_name;
343 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name, ea_list->ea.name);
346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
350 if (samba_private_attr_name(unix_ea_name)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352 return NT_STATUS_ACCESS_DENIED;
355 if (ea_list->ea.value.length == 0) {
356 /* Remove the attribute. */
357 if (fsp && (fsp->fh->fd != -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name, fsp->fsp_name));
360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name, fname));
364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
367 /* Removing a non existent attribute always succeeds. */
368 if (ret == -1 && errno == ENOATTR) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
375 if (fsp && (fsp->fh->fd != -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name, fsp->fsp_name));
378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name, fname));
383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
390 if (errno == ENOTSUP) {
391 return NT_STATUS_EAS_NOT_SUPPORTED;
394 return map_nt_error_from_unix(errno);
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
406 struct ea_list *ea_list_head = NULL;
409 while (offset + 2 < data_size) {
410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411 unsigned int namelen = CVAL(pdata,offset);
413 offset++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417 (offset > data_size) || (namelen > data_size) ||
418 (offset + namelen >= data_size)) {
421 /* Ensure the name is null terminated. */
422 if (pdata[offset + namelen] != '\0') {
425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
430 offset += (namelen + 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
446 unsigned int namelen;
456 eal->ea.flags = CVAL(pdata,0);
457 namelen = CVAL(pdata,1);
458 val_len = SVAL(pdata,2);
460 if (4 + namelen + 1 + val_len > data_size) {
464 /* Ensure the name is null terminated. */
465 if (pdata[namelen + 4] != '\0') {
468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474 if (!eal->ea.value.data) {
478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal->ea.value.data[val_len] = '\0';
482 /* But don't count the null. */
483 eal->ea.value.length--;
486 *pbytes_used = 4 + namelen + 1 + val_len;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490 dump_data(10, eal->ea.value.data, eal->ea.value.length);
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
501 struct ea_list *ea_list_head = NULL;
503 size_t bytes_used = 0;
505 while (offset < data_size) {
506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513 offset += bytes_used;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list *ealist)
526 struct ea_list *listp;
529 for (listp = ealist; listp; listp = listp->next) {
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 /* Add on 4 for total length. */
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
549 struct ea_list *nlistp, *flistp;
551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552 for (flistp = file_list; flistp; flistp = flistp->next) {
553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
559 /* Copy the data from this entry. */
560 nlistp->ea.flags = flistp->ea.flags;
561 nlistp->ea.value = flistp->ea.value;
564 nlistp->ea.flags = 0;
565 ZERO_STRUCT(nlistp->ea.value);
569 *total_ea_len = ea_list_size(name_list);
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(char *outbuf,
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
738 /****************************************************************************
739 Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
742 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
743 char **pparams, int total_params, char **ppdata, int total_data,
744 unsigned int max_data_bytes)
746 char *params = *pparams;
747 char *pdata = *ppdata;
752 BOOL return_additional_info;
763 SMB_STRUCT_STAT sbuf;
766 struct ea_list *ea_list = NULL;
771 uint32 create_disposition;
772 uint32 create_options = 0;
775 * Ensure we have enough parameters to perform the operation.
778 if (total_params < 29) {
779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
782 flags = SVAL(params, 0);
783 deny_mode = SVAL(params, 2);
784 open_attr = SVAL(params,6);
785 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
786 if (oplock_request) {
787 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
791 return_additional_info = BITSETW(params,0);
792 open_sattr = SVAL(params, 4);
793 open_time = make_unix_date3(params+8);
795 open_ofun = SVAL(params,12);
796 open_size = IVAL(params,14);
800 return(ERROR_DOS(ERRSRV,ERRaccess));
803 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
809 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
810 (unsigned int)open_ofun, open_size));
812 /* XXXX we need to handle passed times, sattr and flags */
814 status = unix_convert(conn, fname, False, NULL, &sbuf);
815 if (!NT_STATUS_IS_OK(status)) {
816 return ERROR_NT(status);
819 status = check_name(conn, fname);
820 if (!NT_STATUS_IS_OK(status)) {
821 return ERROR_NT(status);
824 if (open_ofun == 0) {
825 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
828 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
833 return ERROR_DOS(ERRDOS, ERRbadaccess);
836 /* Any data in this call is an EA list. */
837 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
838 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
841 if (total_data != 4) {
842 if (total_data < 10) {
843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 if (IVAL(pdata,0) > total_data) {
847 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
848 IVAL(pdata,0), (unsigned int)total_data));
849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
852 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
857 } else if (IVAL(pdata,0) != 4) {
858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
861 status = open_file_ntcreate(conn,fname,&sbuf,
870 if (!NT_STATUS_IS_OK(status)) {
871 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
872 /* We have re-scheduled this call. */
875 return ERROR_NT(status);
878 size = get_file_size(sbuf);
879 fattr = dos_mode(conn,fname,&sbuf);
880 mtime = sbuf.st_mtime;
883 close_file(fsp,ERROR_CLOSE);
884 return(ERROR_DOS(ERRDOS,ERRnoaccess));
887 /* Save the requested allocation size. */
888 /* Allocate space for the file if a size hint is supplied */
889 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
890 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
891 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
892 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
893 if (fsp->is_directory) {
894 close_file(fsp,ERROR_CLOSE);
895 /* Can't set allocation size on a directory. */
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
898 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
899 close_file(fsp,ERROR_CLOSE);
900 return ERROR_NT(NT_STATUS_DISK_FULL);
903 /* Adjust size here to return the right size in the reply.
904 Windows does it this way. */
905 size = fsp->initial_allocation_size;
907 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
911 if (ea_list && smb_action == FILE_WAS_CREATED) {
912 status = set_ea(conn, fsp, fname, ea_list);
913 if (!NT_STATUS_IS_OK(status)) {
914 close_file(fsp,ERROR_CLOSE);
915 return ERROR_NT(status);
919 /* Realloc the size of parameters and data we will return */
920 *pparams = (char *)SMB_REALLOC(*pparams, 30);
921 if(*pparams == NULL ) {
922 return ERROR_NT(NT_STATUS_NO_MEMORY);
926 SSVAL(params,0,fsp->fnum);
927 SSVAL(params,2,fattr);
928 srv_put_dos_date2(params,4, mtime);
929 SIVAL(params,8, (uint32)size);
930 SSVAL(params,12,deny_mode);
931 SSVAL(params,14,0); /* open_type - file or directory. */
932 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
934 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
935 smb_action |= EXTENDED_OPLOCK_GRANTED;
938 SSVAL(params,18,smb_action);
941 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
943 SIVAL(params,20,inode);
944 SSVAL(params,24,0); /* Padding. */
946 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
947 SIVAL(params, 26, ea_size);
949 SIVAL(params, 26, 0);
952 /* Send the required number of replies */
953 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
958 /*********************************************************
959 Routine to check if a given string matches exactly.
960 as a special case a mask of "." does NOT match. That
961 is required for correct wildcard semantics
962 Case can be significant or not.
963 **********************************************************/
965 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
967 if (mask[0] == '.' && mask[1] == 0)
969 if (conn->case_sensitive)
970 return strcmp(str,mask)==0;
971 if (StrCaseCmp(str,mask) != 0) {
974 if (dptr_has_wild(conn->dirptr)) {
980 /****************************************************************************
981 Return the filetype for UNIX extensions.
982 ****************************************************************************/
984 static uint32 unix_filetype(mode_t mode)
987 return UNIX_TYPE_FILE;
988 else if(S_ISDIR(mode))
989 return UNIX_TYPE_DIR;
991 else if(S_ISLNK(mode))
992 return UNIX_TYPE_SYMLINK;
995 else if(S_ISCHR(mode))
996 return UNIX_TYPE_CHARDEV;
999 else if(S_ISBLK(mode))
1000 return UNIX_TYPE_BLKDEV;
1003 else if(S_ISFIFO(mode))
1004 return UNIX_TYPE_FIFO;
1007 else if(S_ISSOCK(mode))
1008 return UNIX_TYPE_SOCKET;
1011 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1012 return UNIX_TYPE_UNKNOWN;
1015 /****************************************************************************
1016 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1017 ****************************************************************************/
1019 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1021 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1022 SMB_STRUCT_STAT *psbuf,
1024 enum perm_type ptype,
1029 if (perms == SMB_MODE_NO_CHANGE) {
1030 if (!VALID_STAT(*psbuf)) {
1031 return NT_STATUS_INVALID_PARAMETER;
1033 *ret_perms = psbuf->st_mode;
1034 return NT_STATUS_OK;
1038 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1039 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1040 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1041 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1042 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1043 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1044 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1045 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1046 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1048 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1051 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1054 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1059 /* Apply mode mask */
1060 ret &= lp_create_mask(SNUM(conn));
1061 /* Add in force bits */
1062 ret |= lp_force_create_mode(SNUM(conn));
1065 ret &= lp_dir_mask(SNUM(conn));
1066 /* Add in force bits */
1067 ret |= lp_force_dir_mode(SNUM(conn));
1069 case PERM_EXISTING_FILE:
1070 /* Apply mode mask */
1071 ret &= lp_security_mask(SNUM(conn));
1072 /* Add in force bits */
1073 ret |= lp_force_security_mode(SNUM(conn));
1075 case PERM_EXISTING_DIR:
1076 /* Apply mode mask */
1077 ret &= lp_dir_security_mask(SNUM(conn));
1078 /* Add in force bits */
1079 ret |= lp_force_dir_security_mode(SNUM(conn));
1084 return NT_STATUS_OK;
1087 /****************************************************************************
1088 Get a level dependent lanman2 dir entry.
1089 ****************************************************************************/
1091 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1092 void *inbuf, char *outbuf,
1093 char *path_mask,uint32 dirtype,int info_level,
1094 int requires_resume_key,
1095 BOOL dont_descend,char **ppdata,
1096 char *base_data, int space_remaining,
1097 BOOL *out_of_space, BOOL *got_exact_match,
1098 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1102 SMB_STRUCT_STAT sbuf;
1106 char *p, *q, *pdata = *ppdata;
1110 SMB_OFF_T file_size = 0;
1111 SMB_BIG_UINT allocation_size = 0;
1113 struct timespec mdate_ts, adate_ts, create_date_ts;
1114 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1116 char *last_entry_ptr;
1118 uint32 nt_extmode; /* Used for NT connections instead of mode */
1119 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1120 BOOL check_mangled_names = lp_manglednames(conn->params);
1123 *out_of_space = False;
1124 *got_exact_match = False;
1126 ZERO_STRUCT(mdate_ts);
1127 ZERO_STRUCT(adate_ts);
1128 ZERO_STRUCT(create_date_ts);
1133 p = strrchr_m(path_mask,'/');
1136 pstrcpy(mask,"*.*");
1140 pstrcpy(mask, path_mask);
1145 BOOL ms_dfs_link = False;
1147 /* Needed if we run out of space */
1148 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1149 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1152 * Due to bugs in NT client redirectors we are not using
1153 * resume keys any more - set them to zero.
1154 * Check out the related comments in findfirst/findnext.
1160 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1161 (long)conn->dirptr,curr_dirpos));
1168 * fname may get mangled, dname is never mangled.
1169 * Whenever we're accessing the filesystem we use
1170 * pathreal which is composed from dname.
1173 pstrcpy(fname,dname);
1175 /* This will mangle fname if it's an illegal name. */
1176 mangle_map(fname,False,True,conn->params);
1178 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1179 got_match = mask_match(fname, mask, conn->case_sensitive);
1182 if(!got_match && check_mangled_names &&
1183 !mangle_is_8_3(fname, False, conn->params)) {
1184 pstring mangled_name;
1187 * It turns out that NT matches wildcards against
1188 * both long *and* short names. This may explain some
1189 * of the wildcard wierdness from old DOS clients
1190 * that some people have been seeing.... JRA.
1193 pstrcpy(mangled_name, fname);
1195 /* Force the mangling into 8.3. */
1196 mangle_map( mangled_name, True, False, conn->params);
1197 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1198 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1203 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1204 if (dont_descend && !isdots) {
1208 pstrcpy(pathreal,conn->dirpath);
1210 pstrcat(pathreal,"/");
1212 pstrcat(pathreal,dname);
1214 if (INFO_LEVEL_IS_UNIX(info_level)) {
1215 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1216 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1217 pathreal,strerror(errno)));
1220 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1221 pstring link_target;
1223 /* Needed to show the msdfs symlinks as
1226 if(lp_host_msdfs() &&
1227 lp_msdfs_root(SNUM(conn)) &&
1228 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1229 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1232 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1236 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1237 pathreal,strerror(errno)));
1243 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1245 mode = dos_mode(conn,pathreal,&sbuf);
1248 if (!dir_check_ftype(conn,mode,dirtype)) {
1249 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1253 if (!(mode & aDIR)) {
1254 file_size = get_file_size(sbuf);
1256 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1258 mdate_ts = get_mtimespec(&sbuf);
1259 adate_ts = get_atimespec(&sbuf);
1260 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1262 if (lp_dos_filetime_resolution(SNUM(conn))) {
1263 dos_filetime_timespec(&create_date_ts);
1264 dos_filetime_timespec(&mdate_ts);
1265 dos_filetime_timespec(&adate_ts);
1268 create_date = convert_timespec_to_time_t(create_date_ts);
1269 mdate = convert_timespec_to_time_t(mdate_ts);
1270 adate = convert_timespec_to_time_t(adate_ts);
1272 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1276 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1283 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1285 switch (info_level) {
1286 case SMB_FIND_INFO_STANDARD:
1287 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1288 if(requires_resume_key) {
1292 srv_put_dos_date2(p,0,create_date);
1293 srv_put_dos_date2(p,4,adate);
1294 srv_put_dos_date2(p,8,mdate);
1295 SIVAL(p,12,(uint32)file_size);
1296 SIVAL(p,16,(uint32)allocation_size);
1300 p += align_string(outbuf, p, 0);
1301 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1302 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1304 SCVAL(nameptr, -1, len - 2);
1306 SCVAL(nameptr, -1, 0);
1310 SCVAL(nameptr, -1, len - 1);
1312 SCVAL(nameptr, -1, 0);
1318 case SMB_FIND_EA_SIZE:
1319 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1320 if(requires_resume_key) {
1324 srv_put_dos_date2(p,0,create_date);
1325 srv_put_dos_date2(p,4,adate);
1326 srv_put_dos_date2(p,8,mdate);
1327 SIVAL(p,12,(uint32)file_size);
1328 SIVAL(p,16,(uint32)allocation_size);
1331 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1332 SIVAL(p,22,ea_size); /* Extended attributes */
1336 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1337 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1350 SCVAL(nameptr,0,len);
1352 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1355 case SMB_FIND_EA_LIST:
1357 struct ea_list *file_list = NULL;
1360 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1364 if(requires_resume_key) {
1368 srv_put_dos_date2(p,0,create_date);
1369 srv_put_dos_date2(p,4,adate);
1370 srv_put_dos_date2(p,8,mdate);
1371 SIVAL(p,12,(uint32)file_size);
1372 SIVAL(p,16,(uint32)allocation_size);
1374 p += 22; /* p now points to the EA area. */
1376 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1377 name_list = ea_list_union(name_list, file_list, &ea_len);
1379 /* We need to determine if this entry will fit in the space available. */
1380 /* Max string size is 255 bytes. */
1381 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1382 /* Move the dirptr back to prev_dirpos */
1383 dptr_SeekDir(conn->dirptr, prev_dirpos);
1384 *out_of_space = True;
1385 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1386 return False; /* Not finished - just out of space */
1389 /* Push the ea_data followed by the name. */
1390 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1392 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1393 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1406 SCVAL(nameptr,0,len);
1408 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1412 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1413 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1414 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1416 SIVAL(p,0,reskey); p += 4;
1417 put_long_date_timespec(p,create_date_ts); p += 8;
1418 put_long_date_timespec(p,adate_ts); p += 8;
1419 put_long_date_timespec(p,mdate_ts); p += 8;
1420 put_long_date_timespec(p,mdate_ts); p += 8;
1421 SOFF_T(p,0,file_size); p += 8;
1422 SOFF_T(p,0,allocation_size); p += 8;
1423 SIVAL(p,0,nt_extmode); p += 4;
1424 q = p; p += 4; /* q is placeholder for name length. */
1426 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1427 SIVAL(p,0,ea_size); /* Extended attributes */
1430 /* Clear the short name buffer. This is
1431 * IMPORTANT as not doing so will trigger
1432 * a Win2k client bug. JRA.
1434 if (!was_8_3 && check_mangled_names) {
1435 pstring mangled_name;
1436 pstrcpy(mangled_name, fname);
1437 mangle_map(mangled_name,True,True,
1439 mangled_name[12] = 0;
1440 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1442 memset(p + 2 + len,'\0',24 - len);
1449 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1452 SIVAL(p,0,0); /* Ensure any padding is null. */
1453 len = PTR_DIFF(p, pdata);
1454 len = (len + 3) & ~3;
1459 case SMB_FIND_FILE_DIRECTORY_INFO:
1460 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1462 SIVAL(p,0,reskey); p += 4;
1463 put_long_date_timespec(p,create_date_ts); p += 8;
1464 put_long_date_timespec(p,adate_ts); p += 8;
1465 put_long_date_timespec(p,mdate_ts); p += 8;
1466 put_long_date_timespec(p,mdate_ts); p += 8;
1467 SOFF_T(p,0,file_size); p += 8;
1468 SOFF_T(p,0,allocation_size); p += 8;
1469 SIVAL(p,0,nt_extmode); p += 4;
1470 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1473 SIVAL(p,0,0); /* Ensure any padding is null. */
1474 len = PTR_DIFF(p, pdata);
1475 len = (len + 3) & ~3;
1480 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1481 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1483 SIVAL(p,0,reskey); p += 4;
1484 put_long_date_timespec(p,create_date_ts); p += 8;
1485 put_long_date_timespec(p,adate_ts); p += 8;
1486 put_long_date_timespec(p,mdate_ts); p += 8;
1487 put_long_date_timespec(p,mdate_ts); p += 8;
1488 SOFF_T(p,0,file_size); p += 8;
1489 SOFF_T(p,0,allocation_size); p += 8;
1490 SIVAL(p,0,nt_extmode); p += 4;
1491 q = p; p += 4; /* q is placeholder for name length. */
1493 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1494 SIVAL(p,0,ea_size); /* Extended attributes */
1497 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1501 SIVAL(p,0,0); /* Ensure any padding is null. */
1502 len = PTR_DIFF(p, pdata);
1503 len = (len + 3) & ~3;
1508 case SMB_FIND_FILE_NAMES_INFO:
1509 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1511 SIVAL(p,0,reskey); p += 4;
1513 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1514 acl on a dir (tridge) */
1515 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1518 SIVAL(p,0,0); /* Ensure any padding is null. */
1519 len = PTR_DIFF(p, pdata);
1520 len = (len + 3) & ~3;
1525 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1526 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1528 SIVAL(p,0,reskey); p += 4;
1529 put_long_date_timespec(p,create_date_ts); p += 8;
1530 put_long_date_timespec(p,adate_ts); p += 8;
1531 put_long_date_timespec(p,mdate_ts); p += 8;
1532 put_long_date_timespec(p,mdate_ts); p += 8;
1533 SOFF_T(p,0,file_size); p += 8;
1534 SOFF_T(p,0,allocation_size); p += 8;
1535 SIVAL(p,0,nt_extmode); p += 4;
1536 q = p; p += 4; /* q is placeholder for name length. */
1538 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1539 SIVAL(p,0,ea_size); /* Extended attributes */
1542 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1543 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1544 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1545 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1548 SIVAL(p,0,0); /* Ensure any padding is null. */
1549 len = PTR_DIFF(p, pdata);
1550 len = (len + 3) & ~3;
1555 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1556 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1557 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1559 SIVAL(p,0,reskey); p += 4;
1560 put_long_date_timespec(p,create_date_ts); p += 8;
1561 put_long_date_timespec(p,adate_ts); p += 8;
1562 put_long_date_timespec(p,mdate_ts); p += 8;
1563 put_long_date_timespec(p,mdate_ts); p += 8;
1564 SOFF_T(p,0,file_size); p += 8;
1565 SOFF_T(p,0,allocation_size); p += 8;
1566 SIVAL(p,0,nt_extmode); p += 4;
1567 q = p; p += 4; /* q is placeholder for name length */
1569 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1570 SIVAL(p,0,ea_size); /* Extended attributes */
1573 /* Clear the short name buffer. This is
1574 * IMPORTANT as not doing so will trigger
1575 * a Win2k client bug. JRA.
1577 if (!was_8_3 && check_mangled_names) {
1578 pstring mangled_name;
1579 pstrcpy(mangled_name, fname);
1580 mangle_map(mangled_name,True,True,
1582 mangled_name[12] = 0;
1583 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1586 memset(p + 2 + len,'\0',24 - len);
1593 SSVAL(p,0,0); p += 2; /* Reserved ? */
1594 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1595 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1596 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1599 SIVAL(p,0,0); /* Ensure any padding is null. */
1600 len = PTR_DIFF(p, pdata);
1601 len = (len + 3) & ~3;
1606 /* CIFS UNIX Extension. */
1608 case SMB_FIND_FILE_UNIX:
1609 case SMB_FIND_FILE_UNIX_INFO2:
1611 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1613 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1615 if (info_level == SMB_FIND_FILE_UNIX) {
1616 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1617 p = store_file_unix_basic(conn, p,
1619 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1621 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1622 p = store_file_unix_basic_info2(conn, p,
1626 len = srvstr_push(outbuf, p, fname, -1, 0);
1627 SIVAL(nameptr, 0, len);
1631 SIVAL(p,0,0); /* Ensure any padding is null. */
1633 len = PTR_DIFF(p, pdata);
1634 len = (len + 3) & ~3;
1635 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1637 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1646 if (PTR_DIFF(p,pdata) > space_remaining) {
1647 /* Move the dirptr back to prev_dirpos */
1648 dptr_SeekDir(conn->dirptr, prev_dirpos);
1649 *out_of_space = True;
1650 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1651 return False; /* Not finished - just out of space */
1654 /* Setup the last entry pointer, as an offset from base_data */
1655 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1656 /* Advance the data pointer to the next slot */
1662 /****************************************************************************
1663 Reply to a TRANS2_FINDFIRST.
1664 ****************************************************************************/
1666 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1667 char **pparams, int total_params, char **ppdata, int total_data,
1668 unsigned int max_data_bytes)
1670 /* We must be careful here that we don't return more than the
1671 allowed number of data bytes. If this means returning fewer than
1672 maxentries then so be it. We assume that the redirector has
1673 enough room for the fixed number of parameter bytes it has
1675 char *params = *pparams;
1676 char *pdata = *ppdata;
1679 uint16 findfirst_flags;
1680 BOOL close_after_first;
1682 BOOL requires_resume_key;
1687 int last_entry_off=0;
1691 BOOL finished = False;
1692 BOOL dont_descend = False;
1693 BOOL out_of_space = False;
1694 int space_remaining;
1695 BOOL mask_contains_wcard = False;
1696 SMB_STRUCT_STAT sbuf;
1697 TALLOC_CTX *ea_ctx = NULL;
1698 struct ea_list *ea_list = NULL;
1699 NTSTATUS ntstatus = NT_STATUS_OK;
1701 if (total_params < 13) {
1702 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1705 dirtype = SVAL(params,0);
1706 maxentries = SVAL(params,2);
1707 findfirst_flags = SVAL(params,4);
1708 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1709 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1710 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1711 info_level = SVAL(params,6);
1713 *directory = *mask = 0;
1715 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1716 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1717 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1718 info_level, max_data_bytes));
1721 /* W2K3 seems to treat zero as 1. */
1725 switch (info_level) {
1726 case SMB_FIND_INFO_STANDARD:
1727 case SMB_FIND_EA_SIZE:
1728 case SMB_FIND_EA_LIST:
1729 case SMB_FIND_FILE_DIRECTORY_INFO:
1730 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1731 case SMB_FIND_FILE_NAMES_INFO:
1732 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1733 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1734 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1736 case SMB_FIND_FILE_UNIX:
1737 case SMB_FIND_FILE_UNIX_INFO2:
1738 if (!lp_unix_extensions()) {
1739 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1743 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1746 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1747 if (!NT_STATUS_IS_OK(ntstatus)) {
1748 return ERROR_NT(ntstatus);
1751 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1752 if (!NT_STATUS_IS_OK(ntstatus)) {
1753 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1754 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1756 return ERROR_NT(ntstatus);
1759 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1760 if (!NT_STATUS_IS_OK(ntstatus)) {
1761 return ERROR_NT(ntstatus);
1763 ntstatus = check_name(conn, directory);
1764 if (!NT_STATUS_IS_OK(ntstatus)) {
1765 return ERROR_NT(ntstatus);
1768 p = strrchr_m(directory,'/');
1770 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1771 if((directory[0] == '.') && (directory[1] == '\0')) {
1773 mask_contains_wcard = True;
1775 pstrcpy(mask,directory);
1777 pstrcpy(directory,"./");
1783 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1785 if (info_level == SMB_FIND_EA_LIST) {
1788 if (total_data < 4) {
1789 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1792 ea_size = IVAL(pdata,0);
1793 if (ea_size != total_data) {
1794 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1795 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1799 if (!lp_ea_support(SNUM(conn))) {
1800 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1803 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1804 return ERROR_NT(NT_STATUS_NO_MEMORY);
1807 /* Pull out the list of names. */
1808 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1810 talloc_destroy(ea_ctx);
1811 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1815 *ppdata = (char *)SMB_REALLOC(
1816 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1817 if(*ppdata == NULL ) {
1818 talloc_destroy(ea_ctx);
1819 return ERROR_NT(NT_STATUS_NO_MEMORY);
1823 /* Realloc the params space */
1824 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1825 if (*pparams == NULL) {
1826 talloc_destroy(ea_ctx);
1827 return ERROR_NT(NT_STATUS_NO_MEMORY);
1831 /* Save the wildcard match and attribs we are using on this directory -
1832 needed as lanman2 assumes these are being saved between calls */
1834 ntstatus = dptr_create(conn,
1838 SVAL(inbuf,smb_pid),
1840 mask_contains_wcard,
1844 if (!NT_STATUS_IS_OK(ntstatus)) {
1845 talloc_destroy(ea_ctx);
1846 return ERROR_NT(ntstatus);
1849 dptr_num = dptr_dnum(conn->dirptr);
1850 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1852 /* We don't need to check for VOL here as this is returned by
1853 a different TRANS2 call. */
1855 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1856 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1857 dont_descend = True;
1860 space_remaining = max_data_bytes;
1861 out_of_space = False;
1863 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1864 BOOL got_exact_match = False;
1866 /* this is a heuristic to avoid seeking the dirptr except when
1867 absolutely necessary. It allows for a filename of about 40 chars */
1868 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1869 out_of_space = True;
1872 finished = !get_lanman2_dir_entry(conn,
1874 mask,dirtype,info_level,
1875 requires_resume_key,dont_descend,
1876 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1877 &last_entry_off, ea_list, ea_ctx);
1880 if (finished && out_of_space)
1883 if (!finished && !out_of_space)
1887 * As an optimisation if we know we aren't looking
1888 * for a wildcard name (ie. the name matches the wildcard exactly)
1889 * then we can finish on any (first) match.
1890 * This speeds up large directory searches. JRA.
1896 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1899 talloc_destroy(ea_ctx);
1901 /* Check if we can close the dirptr */
1902 if(close_after_first || (finished && close_if_end)) {
1903 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1904 dptr_close(&dptr_num);
1908 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1909 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1910 * the protocol level is less than NT1. Tested with smbclient. JRA.
1911 * This should fix the OS/2 client bug #2335.
1914 if(numentries == 0) {
1915 dptr_close(&dptr_num);
1916 if (Protocol < PROTOCOL_NT1) {
1917 return ERROR_DOS(ERRDOS,ERRnofiles);
1919 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1923 /* At this point pdata points to numentries directory entries. */
1925 /* Set up the return parameter block */
1926 SSVAL(params,0,dptr_num);
1927 SSVAL(params,2,numentries);
1928 SSVAL(params,4,finished);
1929 SSVAL(params,6,0); /* Never an EA error */
1930 SSVAL(params,8,last_entry_off);
1932 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1934 if ((! *directory) && dptr_path(dptr_num))
1935 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1937 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1938 smb_fn_name(CVAL(inbuf,smb_com)),
1939 mask, directory, dirtype, numentries ) );
1942 * Force a name mangle here to ensure that the
1943 * mask as an 8.3 name is top of the mangled cache.
1944 * The reasons for this are subtle. Don't remove
1945 * this code unless you know what you are doing
1946 * (see PR#13758). JRA.
1949 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1950 mangle_map(mask, True, True, conn->params);
1955 /****************************************************************************
1956 Reply to a TRANS2_FINDNEXT.
1957 ****************************************************************************/
1959 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1960 char **pparams, int total_params, char **ppdata, int total_data,
1961 unsigned int max_data_bytes)
1963 /* We must be careful here that we don't return more than the
1964 allowed number of data bytes. If this means returning fewer than
1965 maxentries then so be it. We assume that the redirector has
1966 enough room for the fixed number of parameter bytes it has
1968 char *params = *pparams;
1969 char *pdata = *ppdata;
1974 uint16 findnext_flags;
1975 BOOL close_after_request;
1977 BOOL requires_resume_key;
1979 BOOL mask_contains_wcard = False;
1980 pstring resume_name;
1986 int i, last_entry_off=0;
1987 BOOL finished = False;
1988 BOOL dont_descend = False;
1989 BOOL out_of_space = False;
1990 int space_remaining;
1991 TALLOC_CTX *ea_ctx = NULL;
1992 struct ea_list *ea_list = NULL;
1993 NTSTATUS ntstatus = NT_STATUS_OK;
1995 if (total_params < 13) {
1996 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1999 dptr_num = SVAL(params,0);
2000 maxentries = SVAL(params,2);
2001 info_level = SVAL(params,4);
2002 resume_key = IVAL(params,6);
2003 findnext_flags = SVAL(params,10);
2004 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2005 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2006 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2007 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2009 *mask = *directory = *resume_name = 0;
2011 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2012 if (!NT_STATUS_IS_OK(ntstatus)) {
2013 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2014 complain (it thinks we're asking for the directory above the shared
2015 path or an invalid name). Catch this as the resume name is only compared, never used in
2016 a file access. JRA. */
2017 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2018 pstrcpy(resume_name, "..");
2019 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2020 pstrcpy(resume_name, ".");
2022 return ERROR_NT(ntstatus);
2026 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2027 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2028 resume_key = %d resume name = %s continue=%d level = %d\n",
2029 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2030 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2033 /* W2K3 seems to treat zero as 1. */
2037 switch (info_level) {
2038 case SMB_FIND_INFO_STANDARD:
2039 case SMB_FIND_EA_SIZE:
2040 case SMB_FIND_EA_LIST:
2041 case SMB_FIND_FILE_DIRECTORY_INFO:
2042 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2043 case SMB_FIND_FILE_NAMES_INFO:
2044 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2045 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2046 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2048 case SMB_FIND_FILE_UNIX:
2049 case SMB_FIND_FILE_UNIX_INFO2:
2050 if (!lp_unix_extensions()) {
2051 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2055 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2058 if (info_level == SMB_FIND_EA_LIST) {
2061 if (total_data < 4) {
2062 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2065 ea_size = IVAL(pdata,0);
2066 if (ea_size != total_data) {
2067 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2068 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2069 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2072 if (!lp_ea_support(SNUM(conn))) {
2073 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2076 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2077 return ERROR_NT(NT_STATUS_NO_MEMORY);
2080 /* Pull out the list of names. */
2081 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2083 talloc_destroy(ea_ctx);
2084 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2088 *ppdata = (char *)SMB_REALLOC(
2089 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2090 if(*ppdata == NULL) {
2091 talloc_destroy(ea_ctx);
2092 return ERROR_NT(NT_STATUS_NO_MEMORY);
2097 /* Realloc the params space */
2098 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2099 if(*pparams == NULL ) {
2100 talloc_destroy(ea_ctx);
2101 return ERROR_NT(NT_STATUS_NO_MEMORY);
2106 /* Check that the dptr is valid */
2107 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2108 talloc_destroy(ea_ctx);
2109 return ERROR_DOS(ERRDOS,ERRnofiles);
2112 string_set(&conn->dirpath,dptr_path(dptr_num));
2114 /* Get the wildcard mask from the dptr */
2115 if((p = dptr_wcard(dptr_num))== NULL) {
2116 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2117 talloc_destroy(ea_ctx);
2118 return ERROR_DOS(ERRDOS,ERRnofiles);
2122 pstrcpy(directory,conn->dirpath);
2124 /* Get the attr mask from the dptr */
2125 dirtype = dptr_attr(dptr_num);
2127 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2128 dptr_num, mask, dirtype,
2130 dptr_TellDir(conn->dirptr)));
2132 /* We don't need to check for VOL here as this is returned by
2133 a different TRANS2 call. */
2135 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2136 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2137 dont_descend = True;
2140 space_remaining = max_data_bytes;
2141 out_of_space = False;
2144 * Seek to the correct position. We no longer use the resume key but
2145 * depend on the last file name instead.
2148 if(*resume_name && !continue_bit) {
2151 long current_pos = 0;
2153 * Remember, mangle_map is called by
2154 * get_lanman2_dir_entry(), so the resume name
2155 * could be mangled. Ensure we check the unmangled name.
2158 if (mangle_is_mangled(resume_name, conn->params)) {
2159 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2164 * Fix for NT redirector problem triggered by resume key indexes
2165 * changing between directory scans. We now return a resume key of 0
2166 * and instead look for the filename to continue from (also given
2167 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2168 * findfirst/findnext (as is usual) then the directory pointer
2169 * should already be at the correct place.
2172 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2173 } /* end if resume_name && !continue_bit */
2175 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2176 BOOL got_exact_match = False;
2178 /* this is a heuristic to avoid seeking the dirptr except when
2179 absolutely necessary. It allows for a filename of about 40 chars */
2180 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2181 out_of_space = True;
2184 finished = !get_lanman2_dir_entry(conn,
2186 mask,dirtype,info_level,
2187 requires_resume_key,dont_descend,
2188 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2189 &last_entry_off, ea_list, ea_ctx);
2192 if (finished && out_of_space)
2195 if (!finished && !out_of_space)
2199 * As an optimisation if we know we aren't looking
2200 * for a wildcard name (ie. the name matches the wildcard exactly)
2201 * then we can finish on any (first) match.
2202 * This speeds up large directory searches. JRA.
2208 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2211 talloc_destroy(ea_ctx);
2213 /* Check if we can close the dirptr */
2214 if(close_after_request || (finished && close_if_end)) {
2215 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2216 dptr_close(&dptr_num); /* This frees up the saved mask */
2219 /* Set up the return parameter block */
2220 SSVAL(params,0,numentries);
2221 SSVAL(params,2,finished);
2222 SSVAL(params,4,0); /* Never an EA error */
2223 SSVAL(params,6,last_entry_off);
2225 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2227 if ((! *directory) && dptr_path(dptr_num))
2228 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2230 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2231 smb_fn_name(CVAL(inbuf,smb_com)),
2232 mask, directory, dirtype, numentries ) );
2237 /****************************************************************************
2238 Reply to a TRANS2_QFSINFO (query filesystem info).
2239 ****************************************************************************/
2241 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2242 char **pparams, int total_params, char **ppdata, int total_data,
2243 unsigned int max_data_bytes)
2246 char *params = *pparams;
2250 char *vname = volume_label(SNUM(conn));
2251 int snum = SNUM(conn);
2252 char *fstype = lp_fstype(SNUM(conn));
2255 if (total_params < 2) {
2256 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2259 info_level = SVAL(params,0);
2261 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2263 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2264 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2265 return ERROR_DOS(ERRSRV,ERRinvdevice);
2268 *ppdata = (char *)SMB_REALLOC(
2269 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2270 if (*ppdata == NULL ) {
2271 return ERROR_NT(NT_STATUS_NO_MEMORY);
2275 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2277 switch (info_level) {
2278 case SMB_INFO_ALLOCATION:
2280 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2282 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2283 return(UNIXERROR(ERRHRD,ERRgeneral));
2286 block_size = lp_block_size(snum);
2287 if (bsize < block_size) {
2288 SMB_BIG_UINT factor = block_size/bsize;
2293 if (bsize > block_size) {
2294 SMB_BIG_UINT factor = bsize/block_size;
2299 bytes_per_sector = 512;
2300 sectors_per_unit = bsize/bytes_per_sector;
2302 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2303 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2304 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2306 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2307 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2308 SIVAL(pdata,l1_cUnit,dsize);
2309 SIVAL(pdata,l1_cUnitAvail,dfree);
2310 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2314 case SMB_INFO_VOLUME:
2315 /* Return volume name */
2317 * Add volume serial number - hash of a combination of
2318 * the called hostname and the service name.
2320 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2322 * Win2k3 and previous mess this up by sending a name length
2323 * one byte short. I believe only older clients (OS/2 Win9x) use
2324 * this call so try fixing this by adding a terminating null to
2325 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2327 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2328 SCVAL(pdata,l2_vol_cch,len);
2329 data_len = l2_vol_szVolLabel + len;
2330 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2331 (unsigned)st.st_ctime, len, vname));
2334 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2335 case SMB_FS_ATTRIBUTE_INFORMATION:
2338 #if defined(HAVE_SYS_QUOTAS)
2339 quota_flag = FILE_VOLUME_QUOTAS;
2342 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2343 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2344 quota_flag); /* FS ATTRIBUTES */
2346 SIVAL(pdata,4,255); /* Max filename component length */
2347 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2348 and will think we can't do long filenames */
2349 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2351 data_len = 12 + len;
2354 case SMB_QUERY_FS_LABEL_INFO:
2355 case SMB_FS_LABEL_INFORMATION:
2356 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2361 case SMB_QUERY_FS_VOLUME_INFO:
2362 case SMB_FS_VOLUME_INFORMATION:
2365 * Add volume serial number - hash of a combination of
2366 * the called hostname and the service name.
2368 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2369 (str_checksum(get_local_machine_name())<<16));
2371 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2372 SIVAL(pdata,12,len);
2374 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2375 (int)strlen(vname),vname, lp_servicename(snum)));
2378 case SMB_QUERY_FS_SIZE_INFO:
2379 case SMB_FS_SIZE_INFORMATION:
2381 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2383 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2384 return(UNIXERROR(ERRHRD,ERRgeneral));
2386 block_size = lp_block_size(snum);
2387 if (bsize < block_size) {
2388 SMB_BIG_UINT factor = block_size/bsize;
2393 if (bsize > block_size) {
2394 SMB_BIG_UINT factor = bsize/block_size;
2399 bytes_per_sector = 512;
2400 sectors_per_unit = bsize/bytes_per_sector;
2401 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2402 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2403 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2404 SBIG_UINT(pdata,0,dsize);
2405 SBIG_UINT(pdata,8,dfree);
2406 SIVAL(pdata,16,sectors_per_unit);
2407 SIVAL(pdata,20,bytes_per_sector);
2411 case SMB_FS_FULL_SIZE_INFORMATION:
2413 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2415 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2416 return(UNIXERROR(ERRHRD,ERRgeneral));
2418 block_size = lp_block_size(snum);
2419 if (bsize < block_size) {
2420 SMB_BIG_UINT factor = block_size/bsize;
2425 if (bsize > block_size) {
2426 SMB_BIG_UINT factor = bsize/block_size;
2431 bytes_per_sector = 512;
2432 sectors_per_unit = bsize/bytes_per_sector;
2433 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2434 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2435 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2436 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2437 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2438 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2439 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2440 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2444 case SMB_QUERY_FS_DEVICE_INFO:
2445 case SMB_FS_DEVICE_INFORMATION:
2447 SIVAL(pdata,0,0); /* dev type */
2448 SIVAL(pdata,4,0); /* characteristics */
2451 #ifdef HAVE_SYS_QUOTAS
2452 case SMB_FS_QUOTA_INFORMATION:
2454 * what we have to send --metze:
2456 * Unknown1: 24 NULL bytes
2457 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2458 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2459 * Quota Flags: 2 byte :
2460 * Unknown3: 6 NULL bytes
2464 * details for Quota Flags:
2466 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2467 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2468 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2469 * 0x0001 Enable Quotas: enable quota for this fs
2473 /* we need to fake up a fsp here,
2474 * because its not send in this call
2477 SMB_NTQUOTA_STRUCT quotas;
2480 ZERO_STRUCT(quotas);
2486 if (current_user.ut.uid != 0) {
2487 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2488 lp_servicename(SNUM(conn)),conn->user));
2489 return ERROR_DOS(ERRDOS,ERRnoaccess);
2492 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2493 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2494 return ERROR_DOS(ERRSRV,ERRerror);
2499 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2501 /* Unknown1 24 NULL bytes*/
2502 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2503 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2504 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2506 /* Default Soft Quota 8 bytes */
2507 SBIG_UINT(pdata,24,quotas.softlim);
2509 /* Default Hard Quota 8 bytes */
2510 SBIG_UINT(pdata,32,quotas.hardlim);
2512 /* Quota flag 2 bytes */
2513 SSVAL(pdata,40,quotas.qflags);
2515 /* Unknown3 6 NULL bytes */
2521 #endif /* HAVE_SYS_QUOTAS */
2522 case SMB_FS_OBJECTID_INFORMATION:
2527 * Query the version and capabilities of the CIFS UNIX extensions
2531 case SMB_QUERY_CIFS_UNIX_INFO:
2532 if (!lp_unix_extensions()) {
2533 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2536 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2537 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2538 /* We have POSIX ACLs, pathname and locking capability. */
2539 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2540 CIFS_UNIX_POSIX_ACLS_CAP|
2541 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2542 CIFS_UNIX_FCNTL_LOCKS_CAP|
2543 CIFS_UNIX_EXTATTR_CAP|
2544 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2547 case SMB_QUERY_POSIX_FS_INFO:
2550 vfs_statvfs_struct svfs;
2552 if (!lp_unix_extensions()) {
2553 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2556 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2560 SIVAL(pdata,0,svfs.OptimalTransferSize);
2561 SIVAL(pdata,4,svfs.BlockSize);
2562 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2563 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2564 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2565 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2566 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2567 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2568 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2570 } else if (rc == EOPNOTSUPP) {
2571 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2572 #endif /* EOPNOTSUPP */
2574 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2575 return ERROR_DOS(ERRSRV,ERRerror);
2580 case SMB_QUERY_POSIX_WHOAMI:
2586 if (!lp_unix_extensions()) {
2587 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2590 if (max_data_bytes < 40) {
2591 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2594 /* We ARE guest if global_sid_Builtin_Guests is
2595 * in our list of SIDs.
2597 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2598 current_user.nt_user_token)) {
2599 flags |= SMB_WHOAMI_GUEST;
2602 /* We are NOT guest if global_sid_Authenticated_Users
2603 * is in our list of SIDs.
2605 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2606 current_user.nt_user_token)) {
2607 flags &= ~SMB_WHOAMI_GUEST;
2610 /* NOTE: 8 bytes for UID/GID, irrespective of native
2611 * platform size. This matches
2612 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2614 data_len = 4 /* flags */
2621 + 4 /* pad/reserved */
2622 + (current_user.ut.ngroups * 8)
2624 + (current_user.nt_user_token->num_sids *
2628 SIVAL(pdata, 0, flags);
2629 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2630 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2631 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2634 if (data_len >= max_data_bytes) {
2635 /* Potential overflow, skip the GIDs and SIDs. */
2637 SIVAL(pdata, 24, 0); /* num_groups */
2638 SIVAL(pdata, 28, 0); /* num_sids */
2639 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2640 SIVAL(pdata, 36, 0); /* reserved */
2646 SIVAL(pdata, 24, current_user.ut.ngroups);
2648 current_user.nt_user_token->num_sids);
2650 /* We walk the SID list twice, but this call is fairly
2651 * infrequent, and I don't expect that it's performance
2652 * sensitive -- jpeach
2654 for (i = 0, sid_bytes = 0;
2655 i < current_user.nt_user_token->num_sids; ++i) {
2657 sid_size(¤t_user.nt_user_token->user_sids[i]);
2660 /* SID list byte count */
2661 SIVAL(pdata, 32, sid_bytes);
2663 /* 4 bytes pad/reserved - must be zero */
2664 SIVAL(pdata, 36, 0);
2668 for (i = 0; i < current_user.ut.ngroups; ++i) {
2669 SBIG_UINT(pdata, data_len,
2670 (SMB_BIG_UINT)current_user.ut.groups[i]);
2676 i < current_user.nt_user_token->num_sids; ++i) {
2678 sid_size(¤t_user.nt_user_token->user_sids[i]);
2680 sid_linearize(pdata + data_len, sid_len,
2681 ¤t_user.nt_user_token->user_sids[i]);
2682 data_len += sid_len;
2688 case SMB_MAC_QUERY_FS_INFO:
2690 * Thursby MAC extension... ONLY on NTFS filesystems
2691 * once we do streams then we don't need this
2693 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2695 SIVAL(pdata,84,0x100); /* Don't support mac... */
2700 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2704 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2706 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2711 /****************************************************************************
2712 Reply to a TRANS2_SETFSINFO (set filesystem info).
2713 ****************************************************************************/
2715 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2716 char **pparams, int total_params, char **ppdata, int total_data,
2717 unsigned int max_data_bytes)
2719 char *pdata = *ppdata;
2720 char *params = *pparams;
2724 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2727 if (total_params < 4) {
2728 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2730 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2733 info_level = SVAL(params,2);
2735 switch(info_level) {
2736 case SMB_SET_CIFS_UNIX_INFO:
2738 uint16 client_unix_major;
2739 uint16 client_unix_minor;
2740 uint32 client_unix_cap_low;
2741 uint32 client_unix_cap_high;
2743 if (!lp_unix_extensions()) {
2744 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2747 /* There should be 12 bytes of capabilities set. */
2748 if (total_data < 8) {
2749 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2751 client_unix_major = SVAL(pdata,0);
2752 client_unix_minor = SVAL(pdata,2);
2753 client_unix_cap_low = IVAL(pdata,4);
2754 client_unix_cap_high = IVAL(pdata,8);
2755 /* Just print these values for now. */
2756 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2757 cap_low = 0x%x, cap_high = 0x%x\n",
2758 (unsigned int)client_unix_major,
2759 (unsigned int)client_unix_minor,
2760 (unsigned int)client_unix_cap_low,
2761 (unsigned int)client_unix_cap_high ));
2763 /* Here is where we must switch to posix pathname processing... */
2764 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2765 lp_set_posix_pathnames();
2766 mangle_change_to_posix();
2769 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2770 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2771 /* Client that knows how to do posix locks,
2772 * but not posix open/mkdir operations. Set a
2773 * default type for read/write checks. */
2775 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2780 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2783 size_t param_len = 0;
2784 size_t data_len = total_data;
2786 if (!lp_unix_extensions()) {
2787 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2790 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2792 status = srv_request_encryption_setup(conn,
2793 (unsigned char **)ppdata,
2795 (unsigned char **)pparams,
2799 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2800 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2801 } else if (!NT_STATUS_IS_OK(status)) {
2802 return ERROR_NT(status);
2805 send_trans2_replies(outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2807 if (NT_STATUS_IS_OK(status)) {
2808 /* Server-side transport encryption is now *on*. */
2809 status = srv_encryption_start(conn);
2810 if (!NT_STATUS_IS_OK(status)) {
2811 exit_server_cleanly("Failure in setting up encrypted transport");
2816 case SMB_FS_QUOTA_INFORMATION:
2818 files_struct *fsp = NULL;
2819 SMB_NTQUOTA_STRUCT quotas;
2821 ZERO_STRUCT(quotas);
2824 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2825 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2826 lp_servicename(SNUM(conn)),conn->user));
2827 return ERROR_DOS(ERRSRV,ERRaccess);
2830 /* note: normaly there're 48 bytes,
2831 * but we didn't use the last 6 bytes for now
2834 fsp = file_fsp(params,0);
2835 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2836 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2837 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2840 if (total_data < 42) {
2841 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2846 /* unknown_1 24 NULL bytes in pdata*/
2848 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2849 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2850 #ifdef LARGE_SMB_OFF_T
2851 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2852 #else /* LARGE_SMB_OFF_T */
2853 if ((IVAL(pdata,28) != 0)&&
2854 ((quotas.softlim != 0xFFFFFFFF)||
2855 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2856 /* more than 32 bits? */
2857 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2859 #endif /* LARGE_SMB_OFF_T */
2861 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2862 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2863 #ifdef LARGE_SMB_OFF_T
2864 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2865 #else /* LARGE_SMB_OFF_T */
2866 if ((IVAL(pdata,36) != 0)&&
2867 ((quotas.hardlim != 0xFFFFFFFF)||
2868 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2869 /* more than 32 bits? */
2870 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2872 #endif /* LARGE_SMB_OFF_T */
2874 /* quota_flags 2 bytes **/
2875 quotas.qflags = SVAL(pdata,40);
2877 /* unknown_2 6 NULL bytes follow*/
2879 /* now set the quotas */
2880 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2881 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2882 return ERROR_DOS(ERRSRV,ERRerror);
2888 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2890 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2895 * sending this reply works fine,
2896 * but I'm not sure it's the same
2897 * like windows do...
2900 outsize = set_message(outbuf,10,0,True);
2905 #if defined(HAVE_POSIX_ACLS)
2906 /****************************************************************************
2907 Utility function to count the number of entries in a POSIX acl.
2908 ****************************************************************************/
2910 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2912 unsigned int ace_count = 0;
2913 int entry_id = SMB_ACL_FIRST_ENTRY;
2914 SMB_ACL_ENTRY_T entry;
2916 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2918 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2919 entry_id = SMB_ACL_NEXT_ENTRY;
2926 /****************************************************************************
2927 Utility function to marshall a POSIX acl into wire format.
2928 ****************************************************************************/
2930 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2932 int entry_id = SMB_ACL_FIRST_ENTRY;
2933 SMB_ACL_ENTRY_T entry;
2935 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2936 SMB_ACL_TAG_T tagtype;
2937 SMB_ACL_PERMSET_T permset;
2938 unsigned char perms = 0;
2939 unsigned int own_grp;
2942 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2943 entry_id = SMB_ACL_NEXT_ENTRY;
2946 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2947 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2951 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2952 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2956 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2957 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2958 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2960 SCVAL(pdata,1,perms);
2963 case SMB_ACL_USER_OBJ:
2964 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2965 own_grp = (unsigned int)pst->st_uid;
2966 SIVAL(pdata,2,own_grp);
2971 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2973 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2975 own_grp = (unsigned int)*puid;
2976 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2977 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2978 SIVAL(pdata,2,own_grp);
2982 case SMB_ACL_GROUP_OBJ:
2983 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2984 own_grp = (unsigned int)pst->st_gid;
2985 SIVAL(pdata,2,own_grp);
2990 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2992 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2994 own_grp = (unsigned int)*pgid;
2995 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2996 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2997 SIVAL(pdata,2,own_grp);
3002 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3003 SIVAL(pdata,2,0xFFFFFFFF);
3004 SIVAL(pdata,6,0xFFFFFFFF);
3007 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3008 SIVAL(pdata,2,0xFFFFFFFF);
3009 SIVAL(pdata,6,0xFFFFFFFF);
3012 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3015 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3022 /****************************************************************************
3023 Store the FILE_UNIX_BASIC info.
3024 ****************************************************************************/
3026 static char *store_file_unix_basic(connection_struct *conn,
3029 const SMB_STRUCT_STAT *psbuf)
3031 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3032 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3034 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3037 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3040 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3041 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3042 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3045 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3049 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3053 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3056 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3060 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3064 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3067 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3071 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3078 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3079 * the chflags(2) (or equivalent) flags.
3081 * XXX: this really should be behind the VFS interface. To do this, we would
3082 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3083 * Each VFS module could then implement it's own mapping as appropriate for the
3084 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3086 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3090 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3094 { UF_IMMUTABLE, EXT_IMMUTABLE },
3098 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3102 { UF_HIDDEN, EXT_HIDDEN },
3105 /* Do not remove. We need to guarantee that this array has at least one
3106 * entry to build on HP-UX.
3112 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3113 uint32 *smb_fflags, uint32 *smb_fmask)
3115 #ifdef HAVE_STAT_ST_FLAGS
3118 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3119 *smb_fmask |= info2_flags_map[i].smb_fflag;
3120 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3121 *smb_fflags |= info2_flags_map[i].smb_fflag;
3124 #endif /* HAVE_STAT_ST_FLAGS */
3127 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3128 const uint32 smb_fflags,
3129 const uint32 smb_fmask,
3132 #ifdef HAVE_STAT_ST_FLAGS
3133 uint32 max_fmask = 0;
3136 *stat_fflags = psbuf->st_flags;
3138 /* For each flags requested in smb_fmask, check the state of the
3139 * corresponding flag in smb_fflags and set or clear the matching
3143 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3144 max_fmask |= info2_flags_map[i].smb_fflag;
3145 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3146 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3147 *stat_fflags |= info2_flags_map[i].stat_fflag;
3149 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3154 /* If smb_fmask is asking to set any bits that are not supported by
3155 * our flag mappings, we should fail.
3157 if ((smb_fmask & max_fmask) != smb_fmask) {
3164 #endif /* HAVE_STAT_ST_FLAGS */
3168 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3169 * of file flags and birth (create) time.
3171 static char *store_file_unix_basic_info2(connection_struct *conn,
3174 const SMB_STRUCT_STAT *psbuf)
3176 uint32 file_flags = 0;
3177 uint32 flags_mask = 0;
3179 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3181 /* Create (birth) time 64 bit */
3182 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3185 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3186 SIVAL(pdata, 0, file_flags); /* flags */
3187 SIVAL(pdata, 4, flags_mask); /* mask */
3193 /****************************************************************************
3194 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3195 file name or file id).
3196 ****************************************************************************/
3198 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3199 unsigned int tran_call,
3200 char **pparams, int total_params, char **ppdata, int total_data,
3201 unsigned int max_data_bytes)
3203 char *params = *pparams;
3204 char *pdata = *ppdata;
3208 SMB_OFF_T file_size=0;
3209 SMB_BIG_UINT allocation_size=0;
3210 unsigned int data_size = 0;
3211 unsigned int param_size = 2;
3212 SMB_STRUCT_STAT sbuf;
3213 pstring fname, dos_fname;
3218 BOOL delete_pending = False;
3220 time_t create_time, mtime, atime;
3221 struct timespec create_time_ts, mtime_ts, atime_ts;
3222 files_struct *fsp = NULL;
3223 TALLOC_CTX *data_ctx = NULL;
3224 struct ea_list *ea_list = NULL;
3225 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3226 char *lock_data = NULL;
3229 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3233 if (tran_call == TRANSACT2_QFILEINFO) {
3234 if (total_params < 4) {
3235 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3238 fsp = file_fsp(params,0);
3239 info_level = SVAL(params,2);
3241 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3243 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3244 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3247 if(fsp && (fsp->fake_file_handle)) {
3249 * This is actually for the QUOTA_FAKE_FILE --metze
3252 pstrcpy(fname, fsp->fsp_name);
3253 /* We know this name is ok, it's already passed the checks. */
3255 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3257 * This is actually a QFILEINFO on a directory
3258 * handle (returned from an NT SMB). NT5.0 seems
3259 * to do this call. JRA.
3261 /* We know this name is ok, it's already passed the checks. */
3262 pstrcpy(fname, fsp->fsp_name);
3264 if (INFO_LEVEL_IS_UNIX(info_level)) {
3265 /* Always do lstat for UNIX calls. */
3266 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3267 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3268 return UNIXERROR(ERRDOS,ERRbadpath);
3270 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3271 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3272 return UNIXERROR(ERRDOS,ERRbadpath);
3275 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3278 * Original code - this is an open file.
3280 CHECK_FSP(fsp,conn);
3282 pstrcpy(fname, fsp->fsp_name);
3283 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3284 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3285 return(UNIXERROR(ERRDOS,ERRbadfid));
3287 pos = fsp->fh->position_information;
3288 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3289 access_mask = fsp->access_mask;
3292 NTSTATUS status = NT_STATUS_OK;
3295 if (total_params < 7) {
3296 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3299 info_level = SVAL(params,0);
3301 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3303 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3304 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3307 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3308 if (!NT_STATUS_IS_OK(status)) {
3309 return ERROR_NT(status);
3312 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3315 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3317 return ERROR_NT(status);
3320 status = unix_convert(conn, fname, False, NULL, &sbuf);
3321 if (!NT_STATUS_IS_OK(status)) {
3322 return ERROR_NT(status);
3324 status = check_name(conn, fname);
3325 if (!NT_STATUS_IS_OK(status)) {
3326 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3327 return ERROR_NT(status);
3330 if (INFO_LEVEL_IS_UNIX(info_level)) {
3331 /* Always do lstat for UNIX calls. */
3332 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3333 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3334 return UNIXERROR(ERRDOS,ERRbadpath);
3336 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3337 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3338 return UNIXERROR(ERRDOS,ERRbadpath);
3341 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3342 if (delete_pending) {
3343 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3347 nlink = sbuf.st_nlink;
3349 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3350 /* NTFS does not seem to count ".." */
3354 if ((nlink > 0) && delete_pending) {
3358 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3359 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3362 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3363 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3365 p = strrchr_m(fname,'/');
3371 mode = dos_mode(conn,fname,&sbuf);
3373 mode = FILE_ATTRIBUTE_NORMAL;
3375 fullpathname = fname;
3377 file_size = get_file_size(sbuf);
3379 /* Pull out any data sent here before we realloc. */
3380 switch (info_level) {
3381 case SMB_INFO_QUERY_EAS_FROM_LIST:
3383 /* Pull any EA list from the data portion. */
3386 if (total_data < 4) {
3387 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3389 ea_size = IVAL(pdata,0);
3391 if (total_data > 0 && ea_size != total_data) {
3392 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3393 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3394 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3397 if (!lp_ea_support(SNUM(conn))) {
3398 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3401 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3402 return ERROR_NT(NT_STATUS_NO_MEMORY);
3405 /* Pull out the list of names. */
3406 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3408 talloc_destroy(data_ctx);
3409 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3414 case SMB_QUERY_POSIX_LOCK:
3416 if (fsp == NULL || fsp->fh->fd == -1) {
3417 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3420 if (total_data != POSIX_LOCK_DATA_SIZE) {
3421 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3424 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3425 return ERROR_NT(NT_STATUS_NO_MEMORY);
3428 /* Copy the lock range data. */
3429 lock_data = (char *)talloc_memdup(
3430 data_ctx, pdata, total_data);
3432 talloc_destroy(data_ctx);
3433 return ERROR_NT(NT_STATUS_NO_MEMORY);
3440 *pparams = (char *)SMB_REALLOC(*pparams,2);
3441 if (*pparams == NULL) {
3442 talloc_destroy(data_ctx);
3443 return ERROR_NT(NT_STATUS_NO_MEMORY);
3447 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3448 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3449 if (*ppdata == NULL ) {
3450 talloc_destroy(data_ctx);
3451 return ERROR_NT(NT_STATUS_NO_MEMORY);
3455 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3456 mtime_ts = get_mtimespec(&sbuf);
3457 atime_ts = get_atimespec(&sbuf);
3459 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3462 if (!null_timespec(fsp->pending_modtime)) {
3463 /* the pending modtime overrides the current modtime */
3464 mtime_ts = fsp->pending_modtime;
3467 /* Do we have this path open ? */
3468 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3469 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3470 /* the pending modtime overrides the current modtime */
3471 mtime_ts = fsp1->pending_modtime;
3473 if (fsp1 && fsp1->initial_allocation_size) {
3474 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3478 if (lp_dos_filetime_resolution(SNUM(conn))) {
3479 dos_filetime_timespec(&create_time_ts);
3480 dos_filetime_timespec(&mtime_ts);
3481 dos_filetime_timespec(&atime_ts);
3484 create_time = convert_timespec_to_time_t(create_time_ts);
3485 mtime = convert_timespec_to_time_t(mtime_ts);
3486 atime = convert_timespec_to_time_t(atime_ts);
3488 /* NT expects the name to be in an exact form of the *full*
3489 filename. See the trans2 torture test */
3490 if (strequal(base_name,".")) {
3491 pstrcpy(dos_fname, "\\");
3493 pstr_sprintf(dos_fname, "\\%s", fname);
3494 string_replace(dos_fname, '/', '\\');
3497 switch (info_level) {
3498 case SMB_INFO_STANDARD:
3499 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3501 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3502 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3503 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3504 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3505 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3506 SSVAL(pdata,l1_attrFile,mode);
3509 case SMB_INFO_QUERY_EA_SIZE:
3511 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3512 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3514 srv_put_dos_date2(pdata,0,create_time);
3515 srv_put_dos_date2(pdata,4,atime);
3516 srv_put_dos_date2(pdata,8,mtime); /* write time */
3517 SIVAL(pdata,12,(uint32)file_size);
3518 SIVAL(pdata,16,(uint32)allocation_size);
3519 SSVAL(pdata,20,mode);
3520 SIVAL(pdata,22,ea_size);
3524 case SMB_INFO_IS_NAME_VALID:
3525 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3526 if (tran_call == TRANSACT2_QFILEINFO) {
3527 /* os/2 needs this ? really ?*/
3528 return ERROR_DOS(ERRDOS,ERRbadfunc);
3534 case SMB_INFO_QUERY_EAS_FROM_LIST:
3536 size_t total_ea_len = 0;
3537 struct ea_list *ea_file_list = NULL;
3539 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3541 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3542 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3544 if (!ea_list || (total_ea_len > data_size)) {
3545 talloc_destroy(data_ctx);
3547 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3551 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3552 talloc_destroy(data_ctx);
3556 case SMB_INFO_QUERY_ALL_EAS:
3558 /* We have data_size bytes to put EA's into. */
3559 size_t total_ea_len = 0;
3561 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3563 data_ctx = talloc_init("ea_ctx");
3565 return ERROR_NT(NT_STATUS_NO_MEMORY);
3568 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3569 if (!ea_list || (total_ea_len > data_size)) {
3570 talloc_destroy(data_ctx);
3572 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3576 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3577 talloc_destroy(data_ctx);
3581 case SMB_FILE_BASIC_INFORMATION:
3582 case SMB_QUERY_FILE_BASIC_INFO:
3584 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3585 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3586 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3588 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3592 put_long_date_timespec(pdata,create_time_ts);
3593 put_long_date_timespec(pdata+8,atime_ts);
3594 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3595 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3596 SIVAL(pdata,32,mode);
3598 DEBUG(5,("SMB_QFBI - "));
3599 DEBUG(5,("create: %s ", ctime(&create_time)));
3600 DEBUG(5,("access: %s ", ctime(&atime)));
3601 DEBUG(5,("write: %s ", ctime(&mtime)));
3602 DEBUG(5,("change: %s ", ctime(&mtime)));
3603 DEBUG(5,("mode: %x\n", mode));
3606 case SMB_FILE_STANDARD_INFORMATION:
3607 case SMB_QUERY_FILE_STANDARD_INFO:
3609 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3611 SOFF_T(pdata,0,allocation_size);
3612 SOFF_T(pdata,8,file_size);
3613 SIVAL(pdata,16,nlink);
3614 SCVAL(pdata,20,delete_pending?1:0);
3615 SCVAL(pdata,21,(mode&aDIR)?1:0);
3616 SSVAL(pdata,22,0); /* Padding. */
3619 case SMB_FILE_EA_INFORMATION:
3620 case SMB_QUERY_FILE_EA_INFO:
3622 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3623 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3625 SIVAL(pdata,0,ea_size);
3629 /* Get the 8.3 name - used if NT SMB was negotiated. */
3630 case SMB_QUERY_FILE_ALT_NAME_INFO:
3631 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3635 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3636 pstrcpy(short_name,base_name);
3637 /* Mangle if not already 8.3 */
3638 if(!mangle_is_8_3(short_name, True, conn->params)) {
3639 mangle_map(short_name,True,True,conn->params);
3641 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3642 data_size = 4 + len;
3647 case SMB_QUERY_FILE_NAME_INFO:
3649 this must be *exactly* right for ACLs on mapped drives to work
3651 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3652 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3653 data_size = 4 + len;
3657 case SMB_FILE_ALLOCATION_INFORMATION:
3658 case SMB_QUERY_FILE_ALLOCATION_INFO:
3659 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3661 SOFF_T(pdata,0,allocation_size);
3664 case SMB_FILE_END_OF_FILE_INFORMATION:
3665 case SMB_QUERY_FILE_END_OF_FILEINFO:
3666 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3668 SOFF_T(pdata,0,file_size);
3671 case SMB_QUERY_FILE_ALL_INFO:
3672 case SMB_FILE_ALL_INFORMATION:
3674 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3675 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3676 put_long_date_timespec(pdata,create_time_ts);
3677 put_long_date_timespec(pdata+8,atime_ts);
3678 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3679 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3680 SIVAL(pdata,32,mode);
3681 SIVAL(pdata,36,0); /* padding. */
3683 SOFF_T(pdata,0,allocation_size);
3684 SOFF_T(pdata,8,file_size);
3685 SIVAL(pdata,16,nlink);
3686 SCVAL(pdata,20,delete_pending);
3687 SCVAL(pdata,21,(mode&aDIR)?1:0);
3690 SIVAL(pdata,0,ea_size);
3691 pdata += 4; /* EA info */
3692 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3695 data_size = PTR_DIFF(pdata,(*ppdata));
3698 case SMB_FILE_INTERNAL_INFORMATION:
3699 /* This should be an index number - looks like
3702 I think this causes us to fail the IFSKIT
3703 BasicFileInformationTest. -tpot */
3705 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3706 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3707 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3711 case SMB_FILE_ACCESS_INFORMATION:
3712 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3713 SIVAL(pdata,0,access_mask);
3717 case SMB_FILE_NAME_INFORMATION:
3718 /* Pathname with leading '\'. */
3721 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3722 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3723 SIVAL(pdata,0,byte_len);
3724 data_size = 4 + byte_len;
3728 case SMB_FILE_DISPOSITION_INFORMATION:
3729 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3731 SCVAL(pdata,0,delete_pending);
3734 case SMB_FILE_POSITION_INFORMATION:
3735 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3737 SOFF_T(pdata,0,pos);
3740 case SMB_FILE_MODE_INFORMATION:
3741 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3742 SIVAL(pdata,0,mode);
3746 case SMB_FILE_ALIGNMENT_INFORMATION:
3747 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3748 SIVAL(pdata,0,0); /* No alignment needed. */
3754 * NT4 server just returns "invalid query" to this - if we try to answer
3755 * it then NTws gets a BSOD! (tridge).
3756 * W2K seems to want this. JRA.
3758 case SMB_QUERY_FILE_STREAM_INFO:
3760 case SMB_FILE_STREAM_INFORMATION:
3761 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3765 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3766 SIVAL(pdata,0,0); /* ??? */
3767 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3768 SOFF_T(pdata,8,file_size);
3769 SIVAL(pdata,16,allocation_size);
3770 SIVAL(pdata,20,0); /* ??? */
3771 data_size = 24 + byte_len;
3775 case SMB_QUERY_COMPRESSION_INFO:
3776 case SMB_FILE_COMPRESSION_INFORMATION:
3777 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3778 SOFF_T(pdata,0,file_size);
3779 SIVAL(pdata,8,0); /* ??? */
3780 SIVAL(pdata,12,0); /* ??? */
3784 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3785 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3786 put_long_date_timespec(pdata,create_time_ts);
3787 put_long_date_timespec(pdata+8,atime_ts);
3788 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3789 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3790 SIVAL(pdata,32,allocation_size);
3791 SOFF_T(pdata,40,file_size);
3792 SIVAL(pdata,48,mode);
3793 SIVAL(pdata,52,0); /* ??? */
3797 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3798 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3799 SIVAL(pdata,0,mode);
3805 * CIFS UNIX Extensions.
3808 case SMB_QUERY_FILE_UNIX_BASIC:
3810 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3811 data_size = PTR_DIFF(pdata,(*ppdata));
3815 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3817 for (i=0; i<100; i++)
3818 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3824 case SMB_QUERY_FILE_UNIX_INFO2:
3826 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3827 data_size = PTR_DIFF(pdata,(*ppdata));
3831 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3833 for (i=0; i<100; i++)
3834 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3840 case SMB_QUERY_FILE_UNIX_LINK:
3844 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3846 if(!S_ISLNK(sbuf.st_mode))
3847 return(UNIXERROR(ERRSRV,ERRbadlink));
3849 return(UNIXERROR(ERRDOS,ERRbadlink));
3851 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3853 return(UNIXERROR(ERRDOS,ERRnoaccess));
3855 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3857 data_size = PTR_DIFF(pdata,(*ppdata));
3862 #if defined(HAVE_POSIX_ACLS)
3863 case SMB_QUERY_POSIX_ACL:
3865 SMB_ACL_T file_acl = NULL;
3866 SMB_ACL_T def_acl = NULL;
3867 uint16 num_file_acls = 0;
3868 uint16 num_def_acls = 0;
3870 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3871 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3873 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3876 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3877 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3879 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3882 if (S_ISDIR(sbuf.st_mode)) {
3883 if (fsp && fsp->is_directory) {
3884 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3886 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3888 def_acl = free_empty_sys_acl(conn, def_acl);
3891 num_file_acls = count_acl_entries(conn, file_acl);
3892 num_def_acls = count_acl_entries(conn, def_acl);
3894 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3895 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3897 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3898 SMB_POSIX_ACL_HEADER_SIZE) ));
3900 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3903 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3905 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3908 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3909 SSVAL(pdata,2,num_file_acls);
3910 SSVAL(pdata,4,num_def_acls);
3911 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3913 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3916 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3918 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3920 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3922 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3925 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3927 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3931 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3934 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3936 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3942 case SMB_QUERY_POSIX_LOCK:
3944 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3946 SMB_BIG_UINT offset;
3948 enum brl_type lock_type;
3950 if (total_data != POSIX_LOCK_DATA_SIZE) {
3951 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3954 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3955 case POSIX_LOCK_TYPE_READ:
3956 lock_type = READ_LOCK;
3958 case POSIX_LOCK_TYPE_WRITE:
3959 lock_type = WRITE_LOCK;
3961 case POSIX_LOCK_TYPE_UNLOCK:
3963 /* There's no point in asking for an unlock... */
3964 talloc_destroy(data_ctx);
3965 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3968 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3969 #if defined(HAVE_LONGLONG)
3970 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3971 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3972 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3973 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3974 #else /* HAVE_LONGLONG */
3975 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3976 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3977 #endif /* HAVE_LONGLONG */
3979 status = query_lock(fsp,
3986 if (ERROR_WAS_LOCK_DENIED(status)) {
3987 /* Here we need to report who has it locked... */
3988 data_size = POSIX_LOCK_DATA_SIZE;
3990 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3991 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3992 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3993 #if defined(HAVE_LONGLONG)
3994 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3995 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3996 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3997 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3998 #else /* HAVE_LONGLONG */
3999 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4000 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4001 #endif /* HAVE_LONGLONG */
4003 } else if (NT_STATUS_IS_OK(status)) {
4004 /* For success we just return a copy of what we sent
4005 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4006 data_size = POSIX_LOCK_DATA_SIZE;
4007 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4008 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4010 return ERROR_NT(status);
4016 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4019 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4024 /****************************************************************************
4025 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4027 ****************************************************************************/
4029 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4031 SMB_STRUCT_STAT sbuf1, sbuf2;
4032 pstring last_component_oldname;
4033 pstring last_component_newname;
4034 NTSTATUS status = NT_STATUS_OK;
4039 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4040 if (!NT_STATUS_IS_OK(status)) {
4044 status = check_name(conn, oldname);
4045 if (!NT_STATUS_IS_OK(status)) {
4049 /* source must already exist. */
4050 if (!VALID_STAT(sbuf1)) {
4051 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4054 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4055 if (!NT_STATUS_IS_OK(status)) {
4059 status = check_name(conn, newname);
4060 if (!NT_STATUS_IS_OK(status)) {
4064 /* Disallow if newname already exists. */
4065 if (VALID_STAT(sbuf2)) {
4066 return NT_STATUS_OBJECT_NAME_COLLISION;
4069 /* No links from a directory. */
4070 if (S_ISDIR(sbuf1.st_mode)) {
4071 return NT_STATUS_FILE_IS_A_DIRECTORY;
4074 /* Ensure this is within the share. */
4075 status = reduce_name(conn, oldname);
4076 if (!NT_STATUS_IS_OK(status)) {
4080 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4082 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4083 status = map_nt_error_from_unix(errno);
4084 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4085 nt_errstr(status), newname, oldname));
4091 /****************************************************************************
4092 Deal with setting the time from any of the setfilepathinfo functions.
4093 ****************************************************************************/
4095 static NTSTATUS smb_set_file_time(connection_struct *conn,
4098 const SMB_STRUCT_STAT *psbuf,
4099 struct timespec ts[2])
4102 FILE_NOTIFY_CHANGE_LAST_ACCESS
4103 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4106 if (!VALID_STAT(*psbuf)) {
4107 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4110 /* get some defaults (no modifications) if any info is zero or -1. */
4111 if (null_timespec(ts[0])) {
4112 ts[0] = get_atimespec(psbuf);
4113 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4116 if (null_timespec(ts[1])) {
4117 ts[1] = get_mtimespec(psbuf);
4118 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4121 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4122 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4125 * Try and set the times of this file if
4126 * they are different from the current values.
4130 struct timespec mts = get_mtimespec(psbuf);
4131 struct timespec ats = get_atimespec(psbuf);
4132 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4133 return NT_STATUS_OK;
4139 * This was a setfileinfo on an open file.
4140 * NT does this a lot. We also need to
4141 * set the time here, as it can be read by
4142 * FindFirst/FindNext and with the patch for bug #2045
4143 * in smbd/fileio.c it ensures that this timestamp is
4144 * kept sticky even after a write. We save the request
4145 * away and will set it on file close and after a write. JRA.
4148 if (!null_timespec(ts[1])) {
4149 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4150 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4151 fsp_set_pending_modtime(fsp, ts[1]);
4155 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4157 if(file_ntimes(conn, fname, ts)!=0) {
4158 return map_nt_error_from_unix(errno);
4161 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4163 return NT_STATUS_OK;
4166 /****************************************************************************
4167 Deal with setting the dosmode from any of the setfilepathinfo functions.
4168 ****************************************************************************/
4170 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4172 SMB_STRUCT_STAT *psbuf,
4175 if (!VALID_STAT(*psbuf)) {
4176 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4180 if (S_ISDIR(psbuf->st_mode)) {
4187 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4189 /* check the mode isn't different, before changing it */
4190 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4192 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4193 fname, (unsigned int)dosmode ));
4195 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4196 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4197 fname, strerror(errno)));
4198 return map_nt_error_from_unix(errno);
4201 return NT_STATUS_OK;
4204 /****************************************************************************
4205 Deal with setting the size from any of the setfilepathinfo functions.
4206 ****************************************************************************/
4208 static NTSTATUS smb_set_file_size(connection_struct *conn,
4211 SMB_STRUCT_STAT *psbuf,
4214 NTSTATUS status = NT_STATUS_OK;
4215 files_struct *new_fsp = NULL;
4217 if (!VALID_STAT(*psbuf)) {
4218 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4221 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4223 if (size == get_file_size(*psbuf)) {
4224 return NT_STATUS_OK;
4227 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4228 fname, (double)size ));
4230 if (fsp && fsp->fh->fd != -1) {
4231 /* Handle based call. */
4232 if (vfs_set_filelen(fsp, size) == -1) {
4233 return map_nt_error_from_unix(errno);
4235 return NT_STATUS_OK;
4238 status = open_file_ntcreate(conn, fname, psbuf,
4240 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4243 FILE_ATTRIBUTE_NORMAL,
4244 FORCE_OPLOCK_BREAK_TO_NONE,
4247 if (!NT_STATUS_IS_OK(status)) {
4248 /* NB. We check for open_was_deferred in the caller. */
4252 if (vfs_set_filelen(new_fsp, size) == -1) {
4253 status = map_nt_error_from_unix(errno);
4254 close_file(new_fsp,NORMAL_CLOSE);
4258 close_file(new_fsp,NORMAL_CLOSE);
4259 return NT_STATUS_OK;
4262 /****************************************************************************
4263 Deal with SMB_INFO_SET_EA.
4264 ****************************************************************************/
4266 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4272 struct ea_list *ea_list = NULL;
4273 TALLOC_CTX *ctx = NULL;
4274 NTSTATUS status = NT_STATUS_OK;
4276 if (total_data < 10) {
4278 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4279 length. They seem to have no effect. Bug #3212. JRA */
4281 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4282 /* We're done. We only get EA info in this call. */
4283 return NT_STATUS_OK;
4286 return NT_STATUS_INVALID_PARAMETER;
4289 if (IVAL(pdata,0) > total_data) {
4290 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4291 IVAL(pdata,0), (unsigned int)total_data));
4292 return NT_STATUS_INVALID_PARAMETER;
4295 ctx = talloc_init("SMB_INFO_SET_EA");
4297 return NT_STATUS_NO_MEMORY;
4299 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4301 talloc_destroy(ctx);
4302 return NT_STATUS_INVALID_PARAMETER;
4304 status = set_ea(conn, fsp, fname, ea_list);
4305 talloc_destroy(ctx);
4310 /****************************************************************************
4311 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4312 ****************************************************************************/
4314 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4319 SMB_STRUCT_STAT *psbuf)
4321 NTSTATUS status = NT_STATUS_OK;
4322 BOOL delete_on_close;
4325 if (total_data < 1) {
4326 return NT_STATUS_INVALID_PARAMETER;
4330 return NT_STATUS_INVALID_HANDLE;
4333 delete_on_close = (CVAL(pdata,0) ? True : False);
4334 dosmode = dos_mode(conn, fname, psbuf);
4336 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4337 "delete_on_close = %u\n",
4339 (unsigned int)dosmode,
4340 (unsigned int)delete_on_close ));
4342 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4344 if (!NT_STATUS_IS_OK(status)) {
4348 /* The set is across all open files on this dev/inode pair. */
4349 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4350 return NT_STATUS_ACCESS_DENIED;
4352 return NT_STATUS_OK;
4355 /****************************************************************************
4356 Deal with SMB_FILE_POSITION_INFORMATION.
4357 ****************************************************************************/
4359 static NTSTATUS smb_file_position_information(connection_struct *conn,
4364 SMB_BIG_UINT position_information;
4366 if (total_data < 8) {
4367 return NT_STATUS_INVALID_PARAMETER;
4371 /* Ignore on pathname based set. */
4372 return NT_STATUS_OK;
4375 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4376 #ifdef LARGE_SMB_OFF_T
4377 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4378 #else /* LARGE_SMB_OFF_T */
4379 if (IVAL(pdata,4) != 0) {
4380 /* more than 32 bits? */
4381 return NT_STATUS_INVALID_PARAMETER;
4383 #endif /* LARGE_SMB_OFF_T */
4385 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4386 fsp->fsp_name, (double)position_information ));
4387 fsp->fh->position_information = position_information;
4388 return NT_STATUS_OK;
4391 /****************************************************************************
4392 Deal with SMB_FILE_MODE_INFORMATION.
4393 ****************************************************************************/
4395 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4401 if (total_data < 4) {
4402 return NT_STATUS_INVALID_PARAMETER;
4404 mode = IVAL(pdata,0);
4405 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4406 return NT_STATUS_INVALID_PARAMETER;
4408 return NT_STATUS_OK;
4411 /****************************************************************************
4412 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4413 ****************************************************************************/
4415 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4421 pstring link_target;
4422 const char *newname = fname;
4423 NTSTATUS status = NT_STATUS_OK;
4425 /* Set a symbolic link. */
4426 /* Don't allow this if follow links is false. */
4428 if (total_data == 0) {
4429 return NT_STATUS_INVALID_PARAMETER;
4432 if (!lp_symlinks(SNUM(conn))) {
4433 return NT_STATUS_ACCESS_DENIED;
4436 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4438 /* !widelinks forces the target path to be within the share. */
4439 /* This means we can interpret the target as a pathname. */
4440 if (!lp_widelinks(SNUM(conn))) {
4442 char *last_dirp = NULL;
4444 if (*link_target == '/') {
4445 /* No absolute paths allowed. */
4446 return NT_STATUS_ACCESS_DENIED;
4448 pstrcpy(rel_name, newname);
4449 last_dirp = strrchr_m(rel_name, '/');
4451 last_dirp[1] = '\0';
4453 pstrcpy(rel_name, "./");
4455 pstrcat(rel_name, link_target);
4457 status = check_name(conn, rel_name);
4458 if (!NT_STATUS_IS_OK(status)) {
4463 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4464 newname, link_target ));
4466 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4467 return map_nt_error_from_unix(errno);
4470 return NT_STATUS_OK;
4473 /****************************************************************************
4474 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4475 ****************************************************************************/
4477 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4485 NTSTATUS status = NT_STATUS_OK;
4487 /* Set a hard link. */
4488 if (total_data == 0) {
4489 return NT_STATUS_INVALID_PARAMETER;
4492 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4493 if (!NT_STATUS_IS_OK(status)) {
4497 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4498 if (!NT_STATUS_IS_OK(status)) {
4502 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4505 return hardlink_internals(conn, oldname, fname);
4508 /****************************************************************************
4509 Deal with SMB_FILE_RENAME_INFORMATION.
4510 ****************************************************************************/
4512 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4521 /* uint32 root_fid; */ /* Not used */
4525 BOOL dest_has_wcard = False;
4526 NTSTATUS status = NT_STATUS_OK;
4529 if (total_data < 13) {
4530 return NT_STATUS_INVALID_PARAMETER;
4533 overwrite = (CVAL(pdata,0) ? True : False);
4534 /* root_fid = IVAL(pdata,4); */
4535 len = IVAL(pdata,8);
4537 if (len > (total_data - 12) || (len == 0)) {
4538 return NT_STATUS_INVALID_PARAMETER;
4541 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4542 if (!NT_STATUS_IS_OK(status)) {
4546 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4547 if (!NT_STATUS_IS_OK(status)) {
4551 /* Check the new name has no '/' characters. */
4552 if (strchr_m(newname, '/')) {
4553 return NT_STATUS_NOT_SUPPORTED;
4556 /* Create the base directory. */
4557 pstrcpy(base_name, fname);
4558 p = strrchr_m(base_name, '/');
4562 /* Append the new name. */
4563 pstrcat(base_name, "/");
4564 pstrcat(base_name, newname);
4567 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4568 fsp->fnum, fsp->fsp_name, base_name ));
4569 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4571 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4573 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4579 /****************************************************************************
4580 Deal with SMB_SET_POSIX_ACL.
4581 ****************************************************************************/
4583 #if defined(HAVE_POSIX_ACLS)
4584 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4589 SMB_STRUCT_STAT *psbuf)
4591 uint16 posix_acl_version;
4592 uint16 num_file_acls;
4593 uint16 num_def_acls;
4594 BOOL valid_file_acls = True;
4595 BOOL valid_def_acls = True;
4597 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4598 return NT_STATUS_INVALID_PARAMETER;
4600 posix_acl_version = SVAL(pdata,0);
4601 num_file_acls = SVAL(pdata,2);
4602 num_def_acls = SVAL(pdata,4);
4604 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4605 valid_file_acls = False;
4609 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4610 valid_def_acls = False;
4614 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4615 return NT_STATUS_INVALID_PARAMETER;
4618 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4619 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4620 return NT_STATUS_INVALID_PARAMETER;
4623 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4624 fname ? fname : fsp->fsp_name,
4625 (unsigned int)num_file_acls,
4626 (unsigned int)num_def_acls));
4628 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4629 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4630 return map_nt_error_from_unix(errno);
4633 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4634 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4635 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4636 return map_nt_error_from_unix(errno);
4638 return NT_STATUS_OK;
4642 /****************************************************************************
4643 Deal with SMB_SET_POSIX_LOCK.
4644 ****************************************************************************/
4646 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4654 SMB_BIG_UINT offset;
4656 BOOL blocking_lock = False;
4657 enum brl_type lock_type;
4658 NTSTATUS status = NT_STATUS_OK;
4660 if (fsp == NULL || fsp->fh->fd == -1) {
4661 return NT_STATUS_INVALID_HANDLE;
4664 if (total_data != POSIX_LOCK_DATA_SIZE) {
4665 return NT_STATUS_INVALID_PARAMETER;
4668 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4669 case POSIX_LOCK_TYPE_READ:
4670 lock_type = READ_LOCK;
4672 case POSIX_LOCK_TYPE_WRITE:
4673 /* Return the right POSIX-mappable error code for files opened read-only. */
4674 if (!fsp->can_write) {
4675 return NT_STATUS_INVALID_HANDLE;
4677 lock_type = WRITE_LOCK;
4679 case POSIX_LOCK_TYPE_UNLOCK:
4680 lock_type = UNLOCK_LOCK;
4683 return NT_STATUS_INVALID_PARAMETER;
4686 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4687 blocking_lock = False;
4688 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4689 blocking_lock = True;
4691 return NT_STATUS_INVALID_PARAMETER;
4694 if (!lp_blocking_locks(SNUM(conn))) {
4695 blocking_lock = False;
4698 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4699 #if defined(HAVE_LONGLONG)
4700 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4701 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4702 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4703 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4704 #else /* HAVE_LONGLONG */
4705 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4706 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4707 #endif /* HAVE_LONGLONG */
4709 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4710 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4712 (unsigned int)lock_type,
4713 (unsigned int)lock_pid,
4717 if (lock_type == UNLOCK_LOCK) {
4718 status = do_unlock(fsp,
4724 struct byte_range_lock *br_lck = do_lock(fsp,
4733 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4735 * A blocking lock was requested. Package up
4736 * this smb into a queued request and push it
4737 * onto the blocking lock queue.
4739 if(push_blocking_lock_request(br_lck,
4742 -1, /* infinite timeout. */
4749 TALLOC_FREE(br_lck);
4753 TALLOC_FREE(br_lck);
4759 /****************************************************************************
4760 Deal with SMB_INFO_STANDARD.
4761 ****************************************************************************/
4763 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4768 const SMB_STRUCT_STAT *psbuf)
4770 struct timespec ts[2];
4772 if (total_data < 12) {
4773 return NT_STATUS_INVALID_PARAMETER;
4777 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4779 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4781 DEBUG(10,("smb_set_info_standard: file %s\n",
4782 fname ? fname : fsp->fsp_name ));
4784 return smb_set_file_time(conn,
4791 /****************************************************************************
4792 Deal with SMB_SET_FILE_BASIC_INFO.
4793 ****************************************************************************/
4795 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4800 SMB_STRUCT_STAT *psbuf)
4802 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4803 struct timespec write_time;
4804 struct timespec changed_time;
4806 struct timespec ts[2];
4807 NTSTATUS status = NT_STATUS_OK;
4809 if (total_data < 36) {
4810 return NT_STATUS_INVALID_PARAMETER;
4813 /* Set the attributes */
4814 dosmode = IVAL(pdata,32);
4815 status = smb_set_file_dosmode(conn,
4819 if (!NT_STATUS_IS_OK(status)) {
4823 /* Ignore create time at offset pdata. */
4826 ts[0] = interpret_long_date(pdata+8);
4828 write_time = interpret_long_date(pdata+16);
4829 changed_time = interpret_long_date(pdata+24);
4832 ts[1] = timespec_min(&write_time, &changed_time);
4834 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4838 /* Prefer a defined time to an undefined one. */
4839 if (null_timespec(ts[1])) {
4840 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4843 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4844 fname ? fname : fsp->fsp_name ));
4846 return smb_set_file_time(conn,
4853 /****************************************************************************
4854 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4855 ****************************************************************************/
4857 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4862 SMB_STRUCT_STAT *psbuf)
4864 SMB_BIG_UINT allocation_size = 0;
4865 NTSTATUS status = NT_STATUS_OK;
4866 files_struct *new_fsp = NULL;
4868 if (!VALID_STAT(*psbuf)) {
4869 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4872 if (total_data < 8) {
4873 return NT_STATUS_INVALID_PARAMETER;
4876 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4877 #ifdef LARGE_SMB_OFF_T
4878 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4879 #else /* LARGE_SMB_OFF_T */
4880 if (IVAL(pdata,4) != 0) {
4881 /* more than 32 bits? */
4882 return NT_STATUS_INVALID_PARAMETER;
4884 #endif /* LARGE_SMB_OFF_T */
4886 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4887 fname, (double)allocation_size ));
4889 if (allocation_size) {
4890 allocation_size = smb_roundup(conn, allocation_size);
4893 if(allocation_size == get_file_size(*psbuf)) {
4894 return NT_STATUS_OK;
4897 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4898 fname, (double)allocation_size ));
4900 if (fsp && fsp->fh->fd != -1) {
4901 /* Open file handle. */
4902 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4903 return map_nt_error_from_unix(errno);
4905 return NT_STATUS_OK;
4908 /* Pathname or stat or directory file. */
4910 status = open_file_ntcreate(conn, fname, psbuf,
4912 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4915 FILE_ATTRIBUTE_NORMAL,
4916 FORCE_OPLOCK_BREAK_TO_NONE,
4919 if (!NT_STATUS_IS_OK(status)) {
4920 /* NB. We check for open_was_deferred in the caller. */
4923 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4924 status = map_nt_error_from_unix(errno);
4925 close_file(new_fsp,NORMAL_CLOSE);
4929 close_file(new_fsp,NORMAL_CLOSE);
4930 return NT_STATUS_OK;
4933 /****************************************************************************
4934 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4935 ****************************************************************************/
4937 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4942 SMB_STRUCT_STAT *psbuf)
4946 if (total_data < 8) {
4947 return NT_STATUS_INVALID_PARAMETER;
4950 size = IVAL(pdata,0);
4951 #ifdef LARGE_SMB_OFF_T
4952 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4953 #else /* LARGE_SMB_OFF_T */
4954 if (IVAL(pdata,4) != 0) {
4955 /* more than 32 bits? */
4956 return NT_STATUS_INVALID_PARAMETER;
4958 #endif /* LARGE_SMB_OFF_T */
4959 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4960 "file %s to %.0f\n", fname, (double)size ));
4962 return smb_set_file_size(conn,
4969 /****************************************************************************
4970 Allow a UNIX info mknod.
4971 ****************************************************************************/
4973 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4977 SMB_STRUCT_STAT *psbuf)
4979 uint32 file_type = IVAL(pdata,56);
4980 #if defined(HAVE_MAKEDEV)
4981 uint32 dev_major = IVAL(pdata,60);
4982 uint32 dev_minor = IVAL(pdata,68);
4984 SMB_DEV_T dev = (SMB_DEV_T)0;
4985 uint32 raw_unixmode = IVAL(pdata,84);
4989 if (total_data < 100) {
4990 return NT_STATUS_INVALID_PARAMETER;
4993 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4994 if (!NT_STATUS_IS_OK(status)) {
4998 #if defined(HAVE_MAKEDEV)
4999 dev = makedev(dev_major, dev_minor);
5002 switch (file_type) {
5003 #if defined(S_IFIFO)
5004 case UNIX_TYPE_FIFO:
5005 unixmode |= S_IFIFO;
5008 #if defined(S_IFSOCK)
5009 case UNIX_TYPE_SOCKET:
5010 unixmode |= S_IFSOCK;
5013 #if defined(S_IFCHR)
5014 case UNIX_TYPE_CHARDEV:
5015 unixmode |= S_IFCHR;
5018 #if defined(S_IFBLK)
5019 case UNIX_TYPE_BLKDEV:
5020 unixmode |= S_IFBLK;
5024 return NT_STATUS_INVALID_PARAMETER;
5027 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5028 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5030 /* Ok - do the mknod. */
5031 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5032 return map_nt_error_from_unix(errno);
5035 /* If any of the other "set" calls fail we
5036 * don't want to end up with a half-constructed mknod.
5039 if (lp_inherit_perms(SNUM(conn))) {
5041 conn, parent_dirname(fname),
5045 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5046 status = map_nt_error_from_unix(errno);
5047 SMB_VFS_UNLINK(conn,fname);
5050 return NT_STATUS_OK;
5053 /****************************************************************************
5054 Deal with SMB_SET_FILE_UNIX_BASIC.
5055 ****************************************************************************/
5057 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5062 SMB_STRUCT_STAT *psbuf)
5064 struct timespec ts[2];
5065 uint32 raw_unixmode;
5068 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5069 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5070 NTSTATUS status = NT_STATUS_OK;
5071 BOOL delete_on_fail = False;
5072 enum perm_type ptype;
5074 if (total_data < 100) {
5075 return NT_STATUS_INVALID_PARAMETER;
5078 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5079 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5080 size=IVAL(pdata,0); /* first 8 Bytes are size */
5081 #ifdef LARGE_SMB_OFF_T
5082 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5083 #else /* LARGE_SMB_OFF_T */
5084 if (IVAL(pdata,4) != 0) {
5085 /* more than 32 bits? */
5086 return NT_STATUS_INVALID_PARAMETER;
5088 #endif /* LARGE_SMB_OFF_T */
5091 ts[0] = interpret_long_date(pdata+24); /* access_time */
5092 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5093 set_owner = (uid_t)IVAL(pdata,40);
5094 set_grp = (gid_t)IVAL(pdata,48);
5095 raw_unixmode = IVAL(pdata,84);
5097 if (VALID_STAT(*psbuf)) {
5098 if (S_ISDIR(psbuf->st_mode)) {
5099 ptype = PERM_EXISTING_DIR;
5101 ptype = PERM_EXISTING_FILE;
5104 ptype = PERM_NEW_FILE;
5107 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5108 if (!NT_STATUS_IS_OK(status)) {
5112 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5113 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5114 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5116 if (!VALID_STAT(*psbuf)) {
5118 * The only valid use of this is to create character and block
5119 * devices, and named pipes. This is deprecated (IMHO) and
5120 * a new info level should be used for mknod. JRA.
5123 status = smb_unix_mknod(conn,
5128 if (!NT_STATUS_IS_OK(status)) {
5132 /* Ensure we don't try and change anything else. */
5133 raw_unixmode = SMB_MODE_NO_CHANGE;
5134 size = get_file_size(*psbuf);
5135 ts[0] = get_atimespec(psbuf);
5136 ts[1] = get_mtimespec(psbuf);
5138 * We continue here as we might want to change the
5141 delete_on_fail = True;
5145 /* Horrible backwards compatibility hack as an old server bug
5146 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5150 size = get_file_size(*psbuf);
5155 * Deal with the UNIX specific mode set.
5158 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5159 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5160 (unsigned int)unixmode, fname ));
5161 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5162 return map_nt_error_from_unix(errno);
5167 * Deal with the UNIX specific uid set.
5170 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5171 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5172 (unsigned int)set_owner, fname ));
5173 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5174 status = map_nt_error_from_unix(errno);
5175 if (delete_on_fail) {
5176 SMB_VFS_UNLINK(conn,fname);
5183 * Deal with the UNIX specific gid set.
5186 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5187 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5188 (unsigned int)set_owner, fname ));
5189 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5190 status = map_nt_error_from_unix(errno);
5191 if (delete_on_fail) {
5192 SMB_VFS_UNLINK(conn,fname);
5198 /* Deal with any size changes. */
5200 status = smb_set_file_size(conn,
5205 if (!NT_STATUS_IS_OK(status)) {
5209 /* Deal with any time changes. */
5211 return smb_set_file_time(conn,
5218 /****************************************************************************
5219 Deal with SMB_SET_FILE_UNIX_INFO2.
5220 ****************************************************************************/
5222 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5227 SMB_STRUCT_STAT *psbuf)
5233 if (total_data < 116) {
5234 return NT_STATUS_INVALID_PARAMETER;
5237 /* Start by setting all the fields that are common between UNIX_BASIC
5240 status = smb_set_file_unix_basic(conn, pdata, total_data,
5242 if (!NT_STATUS_IS_OK(status)) {
5246 smb_fflags = IVAL(pdata, 108);
5247 smb_fmask = IVAL(pdata, 112);
5249 /* NB: We should only attempt to alter the file flags if the client
5250 * sends a non-zero mask.
5252 if (smb_fmask != 0) {
5253 int stat_fflags = 0;
5255 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5257 /* Client asked to alter a flag we don't understand. */
5258 return NT_STATUS_INVALID_PARAMETER;
5261 if (fsp && fsp->fh->fd != -1) {
5262 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5263 return NT_STATUS_NOT_SUPPORTED;
5265 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5266 return map_nt_error_from_unix(errno);
5271 /* XXX: need to add support for changing the create_time here. You
5272 * can do this for paths on Darwin with setattrlist(2). The right way
5273 * to hook this up is probably by extending the VFS utimes interface.
5276 return NT_STATUS_OK;
5279 /****************************************************************************
5280 Create a directory with POSIX semantics.
5281 ****************************************************************************/
5283 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5287 SMB_STRUCT_STAT *psbuf,
5288 int *pdata_return_size)
5290 NTSTATUS status = NT_STATUS_OK;
5291 uint32 raw_unixmode = 0;
5292 uint32 mod_unixmode = 0;
5293 mode_t unixmode = (mode_t)0;
5294 files_struct *fsp = NULL;
5295 uint16 info_level_return = 0;
5297 char *pdata = *ppdata;
5299 if (total_data < 18) {
5300 return NT_STATUS_INVALID_PARAMETER;
5303 raw_unixmode = IVAL(pdata,8);
5304 /* Next 4 bytes are not yet defined. */
5306 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5307 if (!NT_STATUS_IS_OK(status)) {
5311 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5313 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5314 fname, (unsigned int)unixmode ));
5316 status = open_directory(conn,
5319 FILE_READ_ATTRIBUTES, /* Just a stat open */
5320 FILE_SHARE_NONE, /* Ignored for stat opens */
5327 if (NT_STATUS_IS_OK(status)) {
5328 close_file(fsp, NORMAL_CLOSE);
5331 info_level_return = SVAL(pdata,16);
5333 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5334 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5335 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5336 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5338 *pdata_return_size = 12;
5341 /* Realloc the data size */
5342 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5343 if (*ppdata == NULL) {
5344 *pdata_return_size = 0;
5345 return NT_STATUS_NO_MEMORY;
5348 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5349 SSVAL(pdata,2,0); /* No fnum. */
5350 SIVAL(pdata,4,info); /* Was directory created. */
5352 switch (info_level_return) {
5353 case SMB_QUERY_FILE_UNIX_BASIC:
5354 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5355 SSVAL(pdata,10,0); /* Padding. */
5356 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5358 case SMB_QUERY_FILE_UNIX_INFO2:
5359 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5360 SSVAL(pdata,10,0); /* Padding. */
5361 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5364 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5365 SSVAL(pdata,10,0); /* Padding. */
5372 /****************************************************************************
5373 Open/Create a file with POSIX semantics.
5374 ****************************************************************************/
5376 static NTSTATUS smb_posix_open(connection_struct *conn,
5380 SMB_STRUCT_STAT *psbuf,
5381 int *pdata_return_size)
5383 BOOL extended_oplock_granted = False;
5384 char *pdata = *ppdata;
5386 uint32 wire_open_mode = 0;
5387 uint32 raw_unixmode = 0;
5388 uint32 mod_unixmode = 0;
5389 uint32 create_disp = 0;
5390 uint32 access_mask = 0;
5391 uint32 create_options = 0;
5392 NTSTATUS status = NT_STATUS_OK;
5393 mode_t unixmode = (mode_t)0;
5394 files_struct *fsp = NULL;
5395 int oplock_request = 0;
5397 uint16 info_level_return = 0;
5399 if (total_data < 18) {
5400 return NT_STATUS_INVALID_PARAMETER;
5403 flags = IVAL(pdata,0);
5404 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5405 if (oplock_request) {
5406 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5409 wire_open_mode = IVAL(pdata,4);
5411 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5412 return smb_posix_mkdir(conn,
5420 switch (wire_open_mode & SMB_ACCMODE) {
5422 access_mask = FILE_READ_DATA;
5425 access_mask = FILE_WRITE_DATA;
5428 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5431 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5432 (unsigned int)wire_open_mode ));
5433 return NT_STATUS_INVALID_PARAMETER;
5436 wire_open_mode &= ~SMB_ACCMODE;
5438 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5439 create_disp = FILE_CREATE;
5440 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5441 create_disp = FILE_OVERWRITE_IF;
5442 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5443 create_disp = FILE_OPEN_IF;
5445 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5446 (unsigned int)wire_open_mode ));
5447 return NT_STATUS_INVALID_PARAMETER;
5450 raw_unixmode = IVAL(pdata,8);
5451 /* Next 4 bytes are not yet defined. */
5453 status = unix_perms_from_wire(conn,
5456 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5459 if (!NT_STATUS_IS_OK(status)) {
5463 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5465 if (wire_open_mode & SMB_O_SYNC) {
5466 create_options |= FILE_WRITE_THROUGH;
5468 if (wire_open_mode & SMB_O_APPEND) {
5469 access_mask |= FILE_APPEND_DATA;
5471 if (wire_open_mode & SMB_O_DIRECT) {
5472 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5475 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5477 (unsigned int)wire_open_mode,
5478 (unsigned int)unixmode ));
5480 status = open_file_ntcreate(conn,
5484 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5486 0, /* no create options yet. */
5492 if (!NT_STATUS_IS_OK(status)) {
5496 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5497 extended_oplock_granted = True;
5500 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5501 extended_oplock_granted = True;
5504 info_level_return = SVAL(pdata,16);
5506 /* Allocate the correct return size. */
5508 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5509 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5510 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5511 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5513 *pdata_return_size = 12;
5516 /* Realloc the data size */
5517 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5518 if (*ppdata == NULL) {
5519 close_file(fsp,ERROR_CLOSE);
5520 *pdata_return_size = 0;
5521 return NT_STATUS_NO_MEMORY;
5524 if (extended_oplock_granted) {
5525 if (flags & REQUEST_BATCH_OPLOCK) {
5526 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5528 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5530 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5531 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5533 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5536 SSVAL(pdata,2,fsp->fnum);
5537 SIVAL(pdata,4,info); /* Was file created etc. */
5539 switch (info_level_return) {
5540 case SMB_QUERY_FILE_UNIX_BASIC:
5541 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5542 SSVAL(pdata,10,0); /* padding. */
5543 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5545 case SMB_QUERY_FILE_UNIX_INFO2:
5546 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5547 SSVAL(pdata,10,0); /* padding. */
5548 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5551 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5552 SSVAL(pdata,10,0); /* padding. */
5555 return NT_STATUS_OK;
5558 /****************************************************************************
5559 Delete a file with POSIX semantics.
5560 ****************************************************************************/
5562 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5566 SMB_STRUCT_STAT *psbuf)
5568 NTSTATUS status = NT_STATUS_OK;
5569 files_struct *fsp = NULL;
5573 if (total_data < 2) {
5574 return NT_STATUS_INVALID_PARAMETER;
5577 flags = SVAL(pdata,0);
5579 if (!VALID_STAT(*psbuf)) {
5580 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5583 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5584 !VALID_STAT_OF_DIR(*psbuf)) {
5585 return NT_STATUS_NOT_A_DIRECTORY;
5588 DEBUG(10,("smb_posix_unlink: %s %s\n",
5589 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5592 if (VALID_STAT_OF_DIR(*psbuf)) {
5593 status = open_directory(conn,
5597 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5599 FILE_DELETE_ON_CLOSE,
5600 FILE_FLAG_POSIX_SEMANTICS|0777,
5606 status = open_file_ntcreate(conn,
5610 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5613 FILE_FLAG_POSIX_SEMANTICS|0777,
5614 0, /* No oplock, but break existing ones. */
5618 * For file opens we must set the delete on close
5622 if (!NT_STATUS_IS_OK(status)) {
5626 status = smb_set_file_disposition_info(conn,
5634 if (!NT_STATUS_IS_OK(status)) {
5637 return close_file(fsp, NORMAL_CLOSE);
5640 /****************************************************************************
5641 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5642 ****************************************************************************/
5644 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5645 unsigned int tran_call,
5646 char **pparams, int total_params, char **ppdata, int total_data,
5647 unsigned int max_data_bytes)
5649 char *params = *pparams;
5650 char *pdata = *ppdata;
5652 SMB_STRUCT_STAT sbuf;
5654 files_struct *fsp = NULL;
5655 NTSTATUS status = NT_STATUS_OK;
5656 int data_return_size = 0;
5659 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5664 if (tran_call == TRANSACT2_SETFILEINFO) {
5665 if (total_params < 4) {
5666 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5669 fsp = file_fsp(params,0);
5670 info_level = SVAL(params,2);
5672 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5674 * This is actually a SETFILEINFO on a directory
5675 * handle (returned from an NT SMB). NT5.0 seems
5676 * to do this call. JRA.
5678 pstrcpy(fname, fsp->fsp_name);
5679 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5680 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5681 return UNIXERROR(ERRDOS,ERRbadpath);
5683 } else if (fsp && fsp->print_file) {
5685 * Doing a DELETE_ON_CLOSE should cancel a print job.
5687 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5688 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5690 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5693 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5696 return (UNIXERROR(ERRDOS,ERRbadpath));
5699 * Original code - this is an open file.
5701 CHECK_FSP(fsp,conn);
5703 pstrcpy(fname, fsp->fsp_name);
5705 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5706 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5707 return(UNIXERROR(ERRDOS,ERRbadfid));
5712 if (total_params < 7) {
5713 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5716 info_level = SVAL(params,0);
5717 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5718 if (!NT_STATUS_IS_OK(status)) {
5719 return ERROR_NT(status);
5722 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5723 if (!NT_STATUS_IS_OK(status)) {
5724 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5725 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5727 return ERROR_NT(status);
5730 status = unix_convert(conn, fname, False, NULL, &sbuf);
5731 if (!NT_STATUS_IS_OK(status)) {
5732 return ERROR_NT(status);
5735 status = check_name(conn, fname);
5736 if (!NT_STATUS_IS_OK(status)) {
5737 return ERROR_NT(status);
5741 * For CIFS UNIX extensions the target name may not exist.
5744 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5745 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5746 return UNIXERROR(ERRDOS,ERRbadpath);
5750 if (!CAN_WRITE(conn)) {
5751 return ERROR_DOS(ERRSRV,ERRaccess);
5754 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5755 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5758 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5759 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5761 /* Realloc the parameter size */
5762 *pparams = (char *)SMB_REALLOC(*pparams,2);
5763 if (*pparams == NULL) {
5764 return ERROR_NT(NT_STATUS_NO_MEMORY);
5770 if (fsp && !null_timespec(fsp->pending_modtime)) {
5771 /* the pending modtime overrides the current modtime */
5772 set_mtimespec(&sbuf, fsp->pending_modtime);
5775 switch (info_level) {
5777 case SMB_INFO_STANDARD:
5779 status = smb_set_info_standard(conn,
5788 case SMB_INFO_SET_EA:
5790 status = smb_info_set_ea(conn,
5798 case SMB_SET_FILE_BASIC_INFO:
5799 case SMB_FILE_BASIC_INFORMATION:
5801 status = smb_set_file_basic_info(conn,
5810 case SMB_FILE_ALLOCATION_INFORMATION:
5811 case SMB_SET_FILE_ALLOCATION_INFO:
5813 status = smb_set_file_allocation_info(conn,
5822 case SMB_FILE_END_OF_FILE_INFORMATION:
5823 case SMB_SET_FILE_END_OF_FILE_INFO:
5825 status = smb_set_file_end_of_file_info(conn,
5834 case SMB_FILE_DISPOSITION_INFORMATION:
5835 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5838 /* JRA - We used to just ignore this on a path ?
5839 * Shouldn't this be invalid level on a pathname
5842 if (tran_call != TRANSACT2_SETFILEINFO) {
5843 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5846 status = smb_set_file_disposition_info(conn,
5855 case SMB_FILE_POSITION_INFORMATION:
5857 status = smb_file_position_information(conn,
5864 /* From tridge Samba4 :
5865 * MODE_INFORMATION in setfileinfo (I have no
5866 * idea what "mode information" on a file is - it takes a value of 0,
5867 * 2, 4 or 6. What could it be?).
5870 case SMB_FILE_MODE_INFORMATION:
5872 status = smb_file_mode_information(conn,
5879 * CIFS UNIX extensions.
5882 case SMB_SET_FILE_UNIX_BASIC:
5884 status = smb_set_file_unix_basic(conn,
5893 case SMB_SET_FILE_UNIX_INFO2:
5895 status = smb_set_file_unix_info2(conn,
5904 case SMB_SET_FILE_UNIX_LINK:
5906 if (tran_call != TRANSACT2_SETPATHINFO) {
5907 /* We must have a pathname for this. */
5908 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5910 status = smb_set_file_unix_link(conn,
5918 case SMB_SET_FILE_UNIX_HLINK:
5920 if (tran_call != TRANSACT2_SETPATHINFO) {
5921 /* We must have a pathname for this. */
5922 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5924 status = smb_set_file_unix_hlink(conn,
5933 case SMB_FILE_RENAME_INFORMATION:
5935 status = smb_file_rename_information(conn,
5945 #if defined(HAVE_POSIX_ACLS)
5946 case SMB_SET_POSIX_ACL:
5948 status = smb_set_posix_acl(conn,
5958 case SMB_SET_POSIX_LOCK:
5960 if (tran_call != TRANSACT2_SETFILEINFO) {
5961 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5963 status = smb_set_posix_lock(conn,
5972 case SMB_POSIX_PATH_OPEN:
5974 if (tran_call != TRANSACT2_SETPATHINFO) {
5975 /* We must have a pathname for this. */
5976 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5979 status = smb_posix_open(conn,
5988 case SMB_POSIX_PATH_UNLINK:
5990 if (tran_call != TRANSACT2_SETPATHINFO) {
5991 /* We must have a pathname for this. */
5992 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5995 status = smb_posix_unlink(conn,
6004 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6008 if (!NT_STATUS_IS_OK(status)) {
6009 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6010 /* We have re-scheduled this call. */
6013 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6014 /* We have re-scheduled this call. */
6017 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6018 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6020 return ERROR_NT(status);
6024 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6029 /****************************************************************************
6030 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6031 ****************************************************************************/
6033 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6034 char **pparams, int total_params, char **ppdata, int total_data,
6035 unsigned int max_data_bytes)
6037 char *params = *pparams;
6038 char *pdata = *ppdata;
6040 SMB_STRUCT_STAT sbuf;
6041 NTSTATUS status = NT_STATUS_OK;
6042 struct ea_list *ea_list = NULL;
6044 if (!CAN_WRITE(conn))
6045 return ERROR_DOS(ERRSRV,ERRaccess);
6047 if (total_params < 5) {
6048 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6051 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6052 if (!NT_STATUS_IS_OK(status)) {
6053 return ERROR_NT(status);
6056 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6058 status = unix_convert(conn, directory, False, NULL, &sbuf);
6059 if (!NT_STATUS_IS_OK(status)) {
6060 return ERROR_NT(status);
6063 status = check_name(conn, directory);
6064 if (!NT_STATUS_IS_OK(status)) {
6065 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6066 return ERROR_NT(status);
6069 /* Any data in this call is an EA list. */
6070 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6071 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6075 * OS/2 workplace shell seems to send SET_EA requests of "null"
6076 * length (4 bytes containing IVAL 4).
6077 * They seem to have no effect. Bug #3212. JRA.
6080 if (total_data != 4) {
6081 if (total_data < 10) {
6082 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6085 if (IVAL(pdata,0) > total_data) {
6086 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6087 IVAL(pdata,0), (unsigned int)total_data));
6088 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6091 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6094 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6096 } else if (IVAL(pdata,0) != 4) {
6097 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6100 status = create_directory(conn, directory);
6102 if (!NT_STATUS_IS_OK(status)) {
6103 return ERROR_NT(status);
6106 /* Try and set any given EA. */
6108 status = set_ea(conn, NULL, directory, ea_list);
6109 if (!NT_STATUS_IS_OK(status)) {
6110 return ERROR_NT(status);
6114 /* Realloc the parameter and data sizes */
6115 *pparams = (char *)SMB_REALLOC(*pparams,2);
6116 if(*pparams == NULL) {
6117 return ERROR_NT(NT_STATUS_NO_MEMORY);
6123 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6128 /****************************************************************************
6129 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6130 We don't actually do this - we just send a null response.
6131 ****************************************************************************/
6133 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6134 char **pparams, int total_params, char **ppdata, int total_data,
6135 unsigned int max_data_bytes)
6137 static uint16 fnf_handle = 257;
6138 char *params = *pparams;
6141 if (total_params < 6) {
6142 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6145 info_level = SVAL(params,4);
6146 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6148 switch (info_level) {
6153 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6156 /* Realloc the parameter and data sizes */
6157 *pparams = (char *)SMB_REALLOC(*pparams,6);
6158 if (*pparams == NULL) {
6159 return ERROR_NT(NT_STATUS_NO_MEMORY);
6163 SSVAL(params,0,fnf_handle);
6164 SSVAL(params,2,0); /* No changes */
6165 SSVAL(params,4,0); /* No EA errors */
6172 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6177 /****************************************************************************
6178 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6179 changes). Currently this does nothing.
6180 ****************************************************************************/
6182 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6183 char **pparams, int total_params, char **ppdata, int total_data,
6184 unsigned int max_data_bytes)
6186 char *params = *pparams;
6188 DEBUG(3,("call_trans2findnotifynext\n"));
6190 /* Realloc the parameter and data sizes */
6191 *pparams = (char *)SMB_REALLOC(*pparams,4);
6192 if (*pparams == NULL) {
6193 return ERROR_NT(NT_STATUS_NO_MEMORY);
6197 SSVAL(params,0,0); /* No changes */
6198 SSVAL(params,2,0); /* No EA errors */
6200 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6205 /****************************************************************************
6206 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6207 ****************************************************************************/
6209 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6210 char **pparams, int total_params, char **ppdata, int total_data,
6211 unsigned int max_data_bytes)
6213 char *params = *pparams;
6216 int max_referral_level;
6218 DEBUG(10,("call_trans2getdfsreferral\n"));
6220 if (total_params < 3) {
6221 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6224 max_referral_level = SVAL(params,0);
6226 if(!lp_host_msdfs())
6227 return ERROR_DOS(ERRDOS,ERRbadfunc);
6229 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6230 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
6231 return UNIXERROR(ERRDOS,ERRbadfile);
6233 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6234 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6239 #define LMCAT_SPL 0x53
6240 #define LMFUNC_GETJOBID 0x60
6242 /****************************************************************************
6243 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6244 ****************************************************************************/
6246 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6247 char **pparams, int total_params, char **ppdata, int total_data,
6248 unsigned int max_data_bytes)
6250 char *pdata = *ppdata;
6251 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6253 /* check for an invalid fid before proceeding */
6256 return(ERROR_DOS(ERRDOS,ERRbadfid));
6258 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6259 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6260 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6261 if (*ppdata == NULL) {
6262 return ERROR_NT(NT_STATUS_NO_MEMORY);
6266 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6267 CAN ACCEPT THIS IN UNICODE. JRA. */
6269 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6270 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6271 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6272 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6275 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6276 return ERROR_DOS(ERRSRV,ERRerror);
6280 /****************************************************************************
6281 Reply to a SMBfindclose (stop trans2 directory search).
6282 ****************************************************************************/
6284 int reply_findclose(connection_struct *conn,
6285 char *inbuf,char *outbuf,int length,int bufsize)
6288 int dptr_num=SVALS(inbuf,smb_vwv0);
6289 START_PROFILE(SMBfindclose);
6291 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6293 dptr_close(&dptr_num);
6295 outsize = set_message(outbuf,0,0,False);
6297 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6299 END_PROFILE(SMBfindclose);
6303 /****************************************************************************
6304 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6305 ****************************************************************************/
6307 int reply_findnclose(connection_struct *conn,
6308 char *inbuf,char *outbuf,int length,int bufsize)
6312 START_PROFILE(SMBfindnclose);
6314 dptr_num = SVAL(inbuf,smb_vwv0);
6316 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6318 /* We never give out valid handles for a
6319 findnotifyfirst - so any dptr_num is ok here.
6322 outsize = set_message(outbuf,0,0,False);
6324 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6326 END_PROFILE(SMBfindnclose);
6330 int handle_trans2(connection_struct *conn,
6331 struct trans_state *state,
6332 char *inbuf, char *outbuf, int size, int bufsize)
6336 if (Protocol >= PROTOCOL_NT1) {
6337 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6340 /* Now we must call the relevant TRANS2 function */
6341 switch(state->call) {
6342 case TRANSACT2_OPEN:
6344 START_PROFILE(Trans2_open);
6345 outsize = call_trans2open(
6346 conn, inbuf, outbuf, bufsize,
6347 &state->param, state->total_param,
6348 &state->data, state->total_data,
6349 state->max_data_return);
6350 END_PROFILE(Trans2_open);
6354 case TRANSACT2_FINDFIRST:
6356 START_PROFILE(Trans2_findfirst);
6357 outsize = call_trans2findfirst(
6358 conn, inbuf, outbuf, bufsize,
6359 &state->param, state->total_param,
6360 &state->data, state->total_data,
6361 state->max_data_return);
6362 END_PROFILE(Trans2_findfirst);
6366 case TRANSACT2_FINDNEXT:
6368 START_PROFILE(Trans2_findnext);
6369 outsize = call_trans2findnext(
6370 conn, inbuf, outbuf, size, bufsize,
6371 &state->param, state->total_param,
6372 &state->data, state->total_data,
6373 state->max_data_return);
6374 END_PROFILE(Trans2_findnext);
6378 case TRANSACT2_QFSINFO:
6380 START_PROFILE(Trans2_qfsinfo);
6381 outsize = call_trans2qfsinfo(
6382 conn, inbuf, outbuf, size, bufsize,
6383 &state->param, state->total_param,
6384 &state->data, state->total_data,
6385 state->max_data_return);
6386 END_PROFILE(Trans2_qfsinfo);
6390 case TRANSACT2_SETFSINFO:
6392 START_PROFILE(Trans2_setfsinfo);
6393 outsize = call_trans2setfsinfo(
6394 conn, inbuf, outbuf, size, bufsize,
6395 &state->param, state->total_param,
6396 &state->data, state->total_data,
6397 state->max_data_return);
6398 END_PROFILE(Trans2_setfsinfo);
6402 case TRANSACT2_QPATHINFO:
6403 case TRANSACT2_QFILEINFO:
6405 START_PROFILE(Trans2_qpathinfo);
6406 outsize = call_trans2qfilepathinfo(
6407 conn, inbuf, outbuf, size, bufsize, state->call,
6408 &state->param, state->total_param,
6409 &state->data, state->total_data,
6410 state->max_data_return);
6411 END_PROFILE(Trans2_qpathinfo);
6415 case TRANSACT2_SETPATHINFO:
6416 case TRANSACT2_SETFILEINFO:
6418 START_PROFILE(Trans2_setpathinfo);
6419 outsize = call_trans2setfilepathinfo(
6420 conn, inbuf, outbuf, size, bufsize, state->call,
6421 &state->param, state->total_param,
6422 &state->data, state->total_data,
6423 state->max_data_return);
6424 END_PROFILE(Trans2_setpathinfo);
6428 case TRANSACT2_FINDNOTIFYFIRST:
6430 START_PROFILE(Trans2_findnotifyfirst);
6431 outsize = call_trans2findnotifyfirst(
6432 conn, inbuf, outbuf, size, bufsize,
6433 &state->param, state->total_param,
6434 &state->data, state->total_data,
6435 state->max_data_return);
6436 END_PROFILE(Trans2_findnotifyfirst);
6440 case TRANSACT2_FINDNOTIFYNEXT:
6442 START_PROFILE(Trans2_findnotifynext);
6443 outsize = call_trans2findnotifynext(
6444 conn, inbuf, outbuf, size, bufsize,
6445 &state->param, state->total_param,
6446 &state->data, state->total_data,
6447 state->max_data_return);
6448 END_PROFILE(Trans2_findnotifynext);
6452 case TRANSACT2_MKDIR:
6454 START_PROFILE(Trans2_mkdir);
6455 outsize = call_trans2mkdir(
6456 conn, inbuf, outbuf, size, bufsize,
6457 &state->param, state->total_param,
6458 &state->data, state->total_data,
6459 state->max_data_return);
6460 END_PROFILE(Trans2_mkdir);
6464 case TRANSACT2_GET_DFS_REFERRAL:
6466 START_PROFILE(Trans2_get_dfs_referral);
6467 outsize = call_trans2getdfsreferral(
6468 conn, inbuf, outbuf, size, bufsize,
6469 &state->param, state->total_param,
6470 &state->data, state->total_data,
6471 state->max_data_return);
6472 END_PROFILE(Trans2_get_dfs_referral);
6476 case TRANSACT2_IOCTL:
6478 START_PROFILE(Trans2_ioctl);
6479 outsize = call_trans2ioctl(
6480 conn, inbuf, outbuf, size, bufsize,
6481 &state->param, state->total_param,
6482 &state->data, state->total_data,
6483 state->max_data_return);
6484 END_PROFILE(Trans2_ioctl);
6489 /* Error in request */
6490 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6491 outsize = ERROR_DOS(ERRSRV,ERRerror);
6497 /****************************************************************************
6498 Reply to a SMBtrans2.
6499 ****************************************************************************/
6501 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6502 int size, int bufsize)
6505 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6506 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6507 unsigned int psoff = SVAL(inbuf, smb_psoff);
6508 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6509 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6510 struct trans_state *state;
6513 START_PROFILE(SMBtrans2);
6515 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6516 if (!NT_STATUS_IS_OK(result)) {
6517 DEBUG(2, ("Got invalid trans2 request: %s\n",
6518 nt_errstr(result)));
6519 END_PROFILE(SMBtrans2);
6520 return ERROR_NT(result);
6523 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6524 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6525 END_PROFILE(SMBtrans2);
6526 return ERROR_DOS(ERRSRV,ERRaccess);
6529 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6530 DEBUG(0, ("talloc failed\n"));
6531 END_PROFILE(SMBtrans2);
6532 return ERROR_NT(NT_STATUS_NO_MEMORY);
6535 state->cmd = SMBtrans2;
6537 state->mid = SVAL(inbuf, smb_mid);
6538 state->vuid = SVAL(inbuf, smb_uid);
6539 state->setup_count = SVAL(inbuf, smb_suwcnt);
6540 state->setup = NULL;
6541 state->total_param = SVAL(inbuf, smb_tpscnt);
6542 state->param = NULL;
6543 state->total_data = SVAL(inbuf, smb_tdscnt);
6545 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6546 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6547 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6548 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6549 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6551 state->call = tran_call;
6553 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6554 is so as a sanity check */
6555 if (state->setup_count != 1) {
6557 * Need to have rc=0 for ioctl to get job id for OS/2.
6558 * Network printing will fail if function is not successful.
6559 * Similar function in reply.c will be used if protocol
6560 * is LANMAN1.0 instead of LM1.2X002.
6561 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6562 * outbuf doesn't have to be set(only job id is used).
6564 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6565 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6566 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6567 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6569 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6570 DEBUG(2,("Transaction is %d\n",tran_call));
6572 END_PROFILE(SMBtrans2);
6573 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6577 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6580 if (state->total_data) {
6581 /* Can't use talloc here, the core routines do realloc on the
6582 * params and data. */
6583 state->data = (char *)SMB_MALLOC(state->total_data);
6584 if (state->data == NULL) {
6585 DEBUG(0,("reply_trans2: data malloc fail for %u "
6586 "bytes !\n", (unsigned int)state->total_data));
6588 END_PROFILE(SMBtrans2);
6589 return(ERROR_DOS(ERRDOS,ERRnomem));
6591 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6593 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6594 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6597 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6600 if (state->total_param) {
6601 /* Can't use talloc here, the core routines do realloc on the
6602 * params and data. */
6603 state->param = (char *)SMB_MALLOC(state->total_param);
6604 if (state->param == NULL) {
6605 DEBUG(0,("reply_trans: param malloc fail for %u "
6606 "bytes !\n", (unsigned int)state->total_param));
6607 SAFE_FREE(state->data);
6609 END_PROFILE(SMBtrans2);
6610 return(ERROR_DOS(ERRDOS,ERRnomem));
6612 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6614 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6615 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6618 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6621 state->received_data = dscnt;
6622 state->received_param = pscnt;
6624 if ((state->received_param == state->total_param) &&
6625 (state->received_data == state->total_data)) {
6627 outsize = handle_trans2(conn, state, inbuf, outbuf,
6629 SAFE_FREE(state->data);
6630 SAFE_FREE(state->param);
6632 END_PROFILE(SMBtrans2);
6636 DLIST_ADD(conn->pending_trans, state);
6638 /* We need to send an interim response then receive the rest
6639 of the parameter/data bytes */
6640 outsize = set_message(outbuf,0,0,False);
6642 END_PROFILE(SMBtrans2);
6647 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6648 SAFE_FREE(state->data);
6649 SAFE_FREE(state->param);
6651 END_PROFILE(SMBtrans2);
6652 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6656 /****************************************************************************
6657 Reply to a SMBtranss2
6658 ****************************************************************************/
6660 int reply_transs2(connection_struct *conn,
6661 char *inbuf,char *outbuf,int size,int bufsize)
6664 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6665 struct trans_state *state;
6667 START_PROFILE(SMBtranss2);
6671 for (state = conn->pending_trans; state != NULL;
6672 state = state->next) {
6673 if (state->mid == SVAL(inbuf,smb_mid)) {
6678 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6679 END_PROFILE(SMBtranss2);
6680 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6683 /* Revise state->total_param and state->total_data in case they have
6684 changed downwards */
6686 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6687 state->total_param = SVAL(inbuf, smb_tpscnt);
6688 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6689 state->total_data = SVAL(inbuf, smb_tdscnt);
6691 pcnt = SVAL(inbuf, smb_spscnt);
6692 poff = SVAL(inbuf, smb_spsoff);
6693 pdisp = SVAL(inbuf, smb_spsdisp);
6695 dcnt = SVAL(inbuf, smb_sdscnt);
6696 doff = SVAL(inbuf, smb_sdsoff);
6697 ddisp = SVAL(inbuf, smb_sdsdisp);
6699 state->received_param += pcnt;
6700 state->received_data += dcnt;
6702 if ((state->received_data > state->total_data) ||
6703 (state->received_param > state->total_param))
6707 if (pdisp+pcnt > state->total_param)
6709 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6711 if (pdisp > state->total_param)
6713 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6714 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6716 if (state->param + pdisp < state->param)
6719 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6724 if (ddisp+dcnt > state->total_data)
6726 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6728 if (ddisp > state->total_data)
6730 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6731 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6733 if (state->data + ddisp < state->data)
6736 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6740 if ((state->received_param < state->total_param) ||
6741 (state->received_data < state->total_data)) {
6742 END_PROFILE(SMBtranss2);
6746 /* construct_reply_common has done us the favor to pre-fill the
6747 * command field with SMBtranss2 which is wrong :-)
6749 SCVAL(outbuf,smb_com,SMBtrans2);
6751 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6753 DLIST_REMOVE(conn->pending_trans, state);
6754 SAFE_FREE(state->data);
6755 SAFE_FREE(state->param);
6759 END_PROFILE(SMBtranss2);
6760 return(ERROR_DOS(ERRSRV,ERRnosupport));
6763 END_PROFILE(SMBtranss2);
6768 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6769 DLIST_REMOVE(conn->pending_trans, state);
6770 SAFE_FREE(state->data);
6771 SAFE_FREE(state->param);
6773 END_PROFILE(SMBtranss2);
6774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);