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, 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, (const char *)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));
1166 pstrcpy(fname,dname);
1168 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1169 got_match = mask_match(fname, mask, conn->case_sensitive);
1171 if(!got_match && check_mangled_names &&
1172 !mangle_is_8_3(fname, False, conn->params)) {
1175 * It turns out that NT matches wildcards against
1176 * both long *and* short names. This may explain some
1177 * of the wildcard wierdness from old DOS clients
1178 * that some people have been seeing.... JRA.
1182 pstrcpy( newname, fname);
1183 mangle_map( newname, True, False, conn->params);
1184 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1185 got_match = mask_match(newname, mask, conn->case_sensitive);
1189 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1190 if (dont_descend && !isdots)
1193 pstrcpy(pathreal,conn->dirpath);
1195 pstrcat(pathreal,"/");
1196 pstrcat(pathreal,dname);
1198 if (INFO_LEVEL_IS_UNIX(info_level)) {
1199 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1200 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1201 pathreal,strerror(errno)));
1204 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1205 pstring link_target;
1207 /* Needed to show the msdfs symlinks as
1210 if(lp_host_msdfs() &&
1211 lp_msdfs_root(SNUM(conn)) &&
1212 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1213 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1216 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1220 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1221 pathreal,strerror(errno)));
1227 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1229 mode = dos_mode(conn,pathreal,&sbuf);
1232 if (!dir_check_ftype(conn,mode,dirtype)) {
1233 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1238 file_size = get_file_size(sbuf);
1239 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1241 mdate_ts = get_mtimespec(&sbuf);
1242 adate_ts = get_atimespec(&sbuf);
1243 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1245 if (lp_dos_filetime_resolution(SNUM(conn))) {
1246 dos_filetime_timespec(&create_date_ts);
1247 dos_filetime_timespec(&mdate_ts);
1248 dos_filetime_timespec(&adate_ts);
1251 create_date = convert_timespec_to_time_t(create_date_ts);
1252 mdate = convert_timespec_to_time_t(mdate_ts);
1253 adate = convert_timespec_to_time_t(adate_ts);
1255 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1259 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1263 mangle_map(fname,False,True,conn->params);
1268 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1270 switch (info_level) {
1271 case SMB_FIND_INFO_STANDARD:
1272 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1273 if(requires_resume_key) {
1277 srv_put_dos_date2(p,0,create_date);
1278 srv_put_dos_date2(p,4,adate);
1279 srv_put_dos_date2(p,8,mdate);
1280 SIVAL(p,12,(uint32)file_size);
1281 SIVAL(p,16,(uint32)allocation_size);
1285 p += align_string(outbuf, p, 0);
1286 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1287 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1289 SCVAL(nameptr, -1, len - 2);
1291 SCVAL(nameptr, -1, 0);
1295 SCVAL(nameptr, -1, len - 1);
1297 SCVAL(nameptr, -1, 0);
1303 case SMB_FIND_EA_SIZE:
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1305 if(requires_resume_key) {
1309 srv_put_dos_date2(p,0,create_date);
1310 srv_put_dos_date2(p,4,adate);
1311 srv_put_dos_date2(p,8,mdate);
1312 SIVAL(p,12,(uint32)file_size);
1313 SIVAL(p,16,(uint32)allocation_size);
1316 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1317 SIVAL(p,22,ea_size); /* Extended attributes */
1321 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1322 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1335 SCVAL(nameptr,0,len);
1337 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1340 case SMB_FIND_EA_LIST:
1342 struct ea_list *file_list = NULL;
1345 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1349 if(requires_resume_key) {
1353 srv_put_dos_date2(p,0,create_date);
1354 srv_put_dos_date2(p,4,adate);
1355 srv_put_dos_date2(p,8,mdate);
1356 SIVAL(p,12,(uint32)file_size);
1357 SIVAL(p,16,(uint32)allocation_size);
1359 p += 22; /* p now points to the EA area. */
1361 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1362 name_list = ea_list_union(name_list, file_list, &ea_len);
1364 /* We need to determine if this entry will fit in the space available. */
1365 /* Max string size is 255 bytes. */
1366 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1367 /* Move the dirptr back to prev_dirpos */
1368 dptr_SeekDir(conn->dirptr, prev_dirpos);
1369 *out_of_space = True;
1370 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1371 return False; /* Not finished - just out of space */
1374 /* Push the ea_data followed by the name. */
1375 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1377 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1378 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1391 SCVAL(nameptr,0,len);
1393 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1397 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1398 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1399 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1401 SIVAL(p,0,reskey); p += 4;
1402 put_long_date_timespec(p,create_date_ts); p += 8;
1403 put_long_date_timespec(p,adate_ts); p += 8;
1404 put_long_date_timespec(p,mdate_ts); p += 8;
1405 put_long_date_timespec(p,mdate_ts); p += 8;
1406 SOFF_T(p,0,file_size); p += 8;
1407 SOFF_T(p,0,allocation_size); p += 8;
1408 SIVAL(p,0,nt_extmode); p += 4;
1409 q = p; p += 4; /* q is placeholder for name length. */
1411 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1412 SIVAL(p,0,ea_size); /* Extended attributes */
1415 /* Clear the short name buffer. This is
1416 * IMPORTANT as not doing so will trigger
1417 * a Win2k client bug. JRA.
1419 if (!was_8_3 && check_mangled_names) {
1420 pstring mangled_name;
1421 pstrcpy(mangled_name, fname);
1422 mangle_map(mangled_name,True,True,
1424 mangled_name[12] = 0;
1425 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1427 memset(p + 2 + len,'\0',24 - len);
1434 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1437 SIVAL(p,0,0); /* Ensure any padding is null. */
1438 len = PTR_DIFF(p, pdata);
1439 len = (len + 3) & ~3;
1444 case SMB_FIND_FILE_DIRECTORY_INFO:
1445 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1447 SIVAL(p,0,reskey); p += 4;
1448 put_long_date_timespec(p,create_date_ts); p += 8;
1449 put_long_date_timespec(p,adate_ts); p += 8;
1450 put_long_date_timespec(p,mdate_ts); p += 8;
1451 put_long_date_timespec(p,mdate_ts); p += 8;
1452 SOFF_T(p,0,file_size); p += 8;
1453 SOFF_T(p,0,allocation_size); p += 8;
1454 SIVAL(p,0,nt_extmode); p += 4;
1455 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1458 SIVAL(p,0,0); /* Ensure any padding is null. */
1459 len = PTR_DIFF(p, pdata);
1460 len = (len + 3) & ~3;
1465 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1466 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1468 SIVAL(p,0,reskey); p += 4;
1469 put_long_date_timespec(p,create_date_ts); p += 8;
1470 put_long_date_timespec(p,adate_ts); p += 8;
1471 put_long_date_timespec(p,mdate_ts); p += 8;
1472 put_long_date_timespec(p,mdate_ts); p += 8;
1473 SOFF_T(p,0,file_size); p += 8;
1474 SOFF_T(p,0,allocation_size); p += 8;
1475 SIVAL(p,0,nt_extmode); p += 4;
1476 q = p; p += 4; /* q is placeholder for name length. */
1478 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1479 SIVAL(p,0,ea_size); /* Extended attributes */
1482 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1486 SIVAL(p,0,0); /* Ensure any padding is null. */
1487 len = PTR_DIFF(p, pdata);
1488 len = (len + 3) & ~3;
1493 case SMB_FIND_FILE_NAMES_INFO:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1496 SIVAL(p,0,reskey); p += 4;
1498 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1499 acl on a dir (tridge) */
1500 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1503 SIVAL(p,0,0); /* Ensure any padding is null. */
1504 len = PTR_DIFF(p, pdata);
1505 len = (len + 3) & ~3;
1510 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1511 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1513 SIVAL(p,0,reskey); p += 4;
1514 put_long_date_timespec(p,create_date_ts); p += 8;
1515 put_long_date_timespec(p,adate_ts); p += 8;
1516 put_long_date_timespec(p,mdate_ts); p += 8;
1517 put_long_date_timespec(p,mdate_ts); p += 8;
1518 SOFF_T(p,0,file_size); p += 8;
1519 SOFF_T(p,0,allocation_size); p += 8;
1520 SIVAL(p,0,nt_extmode); p += 4;
1521 q = p; p += 4; /* q is placeholder for name length. */
1523 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1524 SIVAL(p,0,ea_size); /* Extended attributes */
1527 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1528 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1529 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1530 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1533 SIVAL(p,0,0); /* Ensure any padding is null. */
1534 len = PTR_DIFF(p, pdata);
1535 len = (len + 3) & ~3;
1540 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1541 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1542 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1544 SIVAL(p,0,reskey); p += 4;
1545 put_long_date_timespec(p,create_date_ts); p += 8;
1546 put_long_date_timespec(p,adate_ts); p += 8;
1547 put_long_date_timespec(p,mdate_ts); p += 8;
1548 put_long_date_timespec(p,mdate_ts); p += 8;
1549 SOFF_T(p,0,file_size); p += 8;
1550 SOFF_T(p,0,allocation_size); p += 8;
1551 SIVAL(p,0,nt_extmode); p += 4;
1552 q = p; p += 4; /* q is placeholder for name length */
1554 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1555 SIVAL(p,0,ea_size); /* Extended attributes */
1558 /* Clear the short name buffer. This is
1559 * IMPORTANT as not doing so will trigger
1560 * a Win2k client bug. JRA.
1562 if (!was_8_3 && check_mangled_names) {
1563 pstring mangled_name;
1564 pstrcpy(mangled_name, fname);
1565 mangle_map(mangled_name,True,True,
1567 mangled_name[12] = 0;
1568 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1571 memset(p + 2 + len,'\0',24 - len);
1578 SSVAL(p,0,0); p += 2; /* Reserved ? */
1579 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1580 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1581 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1584 SIVAL(p,0,0); /* Ensure any padding is null. */
1585 len = PTR_DIFF(p, pdata);
1586 len = (len + 3) & ~3;
1591 /* CIFS UNIX Extension. */
1593 case SMB_FIND_FILE_UNIX:
1594 case SMB_FIND_FILE_UNIX_INFO2:
1596 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1598 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1600 if (info_level == SMB_FIND_FILE_UNIX) {
1601 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1602 p = store_file_unix_basic(conn, p,
1604 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1606 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1607 p = store_file_unix_basic_info2(conn, p,
1611 len = srvstr_push(outbuf, p, fname, -1, 0);
1612 SIVAL(nameptr, 0, len);
1616 SIVAL(p,0,0); /* Ensure any padding is null. */
1618 len = PTR_DIFF(p, pdata);
1619 len = (len + 3) & ~3;
1620 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1622 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1631 if (PTR_DIFF(p,pdata) > space_remaining) {
1632 /* Move the dirptr back to prev_dirpos */
1633 dptr_SeekDir(conn->dirptr, prev_dirpos);
1634 *out_of_space = True;
1635 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1636 return False; /* Not finished - just out of space */
1639 /* Setup the last entry pointer, as an offset from base_data */
1640 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1641 /* Advance the data pointer to the next slot */
1647 /****************************************************************************
1648 Reply to a TRANS2_FINDFIRST.
1649 ****************************************************************************/
1651 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1652 char **pparams, int total_params, char **ppdata, int total_data,
1653 unsigned int max_data_bytes)
1655 /* We must be careful here that we don't return more than the
1656 allowed number of data bytes. If this means returning fewer than
1657 maxentries then so be it. We assume that the redirector has
1658 enough room for the fixed number of parameter bytes it has
1660 char *params = *pparams;
1661 char *pdata = *ppdata;
1664 uint16 findfirst_flags;
1665 BOOL close_after_first;
1667 BOOL requires_resume_key;
1672 int last_entry_off=0;
1676 BOOL finished = False;
1677 BOOL dont_descend = False;
1678 BOOL out_of_space = False;
1679 int space_remaining;
1680 BOOL mask_contains_wcard = False;
1681 SMB_STRUCT_STAT sbuf;
1682 TALLOC_CTX *ea_ctx = NULL;
1683 struct ea_list *ea_list = NULL;
1684 NTSTATUS ntstatus = NT_STATUS_OK;
1686 if (total_params < 13) {
1687 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1690 dirtype = SVAL(params,0);
1691 maxentries = SVAL(params,2);
1692 findfirst_flags = SVAL(params,4);
1693 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1694 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1695 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1696 info_level = SVAL(params,6);
1698 *directory = *mask = 0;
1700 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1701 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1702 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1703 info_level, max_data_bytes));
1706 /* W2K3 seems to treat zero as 1. */
1710 switch (info_level) {
1711 case SMB_FIND_INFO_STANDARD:
1712 case SMB_FIND_EA_SIZE:
1713 case SMB_FIND_EA_LIST:
1714 case SMB_FIND_FILE_DIRECTORY_INFO:
1715 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1716 case SMB_FIND_FILE_NAMES_INFO:
1717 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1718 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1719 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1721 case SMB_FIND_FILE_UNIX:
1722 case SMB_FIND_FILE_UNIX_INFO2:
1723 if (!lp_unix_extensions()) {
1724 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1728 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1731 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1732 if (!NT_STATUS_IS_OK(ntstatus)) {
1733 return ERROR_NT(ntstatus);
1736 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1737 if (!NT_STATUS_IS_OK(ntstatus)) {
1738 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1739 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1741 return ERROR_NT(ntstatus);
1744 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1745 if (!NT_STATUS_IS_OK(ntstatus)) {
1746 return ERROR_NT(ntstatus);
1748 ntstatus = check_name(conn, directory);
1749 if (!NT_STATUS_IS_OK(ntstatus)) {
1750 return ERROR_NT(ntstatus);
1753 p = strrchr_m(directory,'/');
1755 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1756 if((directory[0] == '.') && (directory[1] == '\0')) {
1758 mask_contains_wcard = True;
1760 pstrcpy(mask,directory);
1762 pstrcpy(directory,"./");
1768 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1770 if (info_level == SMB_FIND_EA_LIST) {
1773 if (total_data < 4) {
1774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1777 ea_size = IVAL(pdata,0);
1778 if (ea_size != total_data) {
1779 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1780 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1781 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1784 if (!lp_ea_support(SNUM(conn))) {
1785 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1788 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1789 return ERROR_NT(NT_STATUS_NO_MEMORY);
1792 /* Pull out the list of names. */
1793 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1795 talloc_destroy(ea_ctx);
1796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1800 *ppdata = (char *)SMB_REALLOC(
1801 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1802 if(*ppdata == NULL ) {
1803 talloc_destroy(ea_ctx);
1804 return ERROR_NT(NT_STATUS_NO_MEMORY);
1808 /* Realloc the params space */
1809 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1810 if (*pparams == NULL) {
1811 talloc_destroy(ea_ctx);
1812 return ERROR_NT(NT_STATUS_NO_MEMORY);
1816 /* Save the wildcard match and attribs we are using on this directory -
1817 needed as lanman2 assumes these are being saved between calls */
1819 ntstatus = dptr_create(conn,
1823 SVAL(inbuf,smb_pid),
1825 mask_contains_wcard,
1829 if (!NT_STATUS_IS_OK(ntstatus)) {
1830 talloc_destroy(ea_ctx);
1831 return ERROR_NT(ntstatus);
1834 dptr_num = dptr_dnum(conn->dirptr);
1835 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1837 /* We don't need to check for VOL here as this is returned by
1838 a different TRANS2 call. */
1840 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1841 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1842 dont_descend = True;
1845 space_remaining = max_data_bytes;
1846 out_of_space = False;
1848 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1849 BOOL got_exact_match = False;
1851 /* this is a heuristic to avoid seeking the dirptr except when
1852 absolutely necessary. It allows for a filename of about 40 chars */
1853 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1854 out_of_space = True;
1857 finished = !get_lanman2_dir_entry(conn,
1859 mask,dirtype,info_level,
1860 requires_resume_key,dont_descend,
1861 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1862 &last_entry_off, ea_list, ea_ctx);
1865 if (finished && out_of_space)
1868 if (!finished && !out_of_space)
1872 * As an optimisation if we know we aren't looking
1873 * for a wildcard name (ie. the name matches the wildcard exactly)
1874 * then we can finish on any (first) match.
1875 * This speeds up large directory searches. JRA.
1881 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1884 talloc_destroy(ea_ctx);
1886 /* Check if we can close the dirptr */
1887 if(close_after_first || (finished && close_if_end)) {
1888 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1889 dptr_close(&dptr_num);
1893 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1894 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1895 * the protocol level is less than NT1. Tested with smbclient. JRA.
1896 * This should fix the OS/2 client bug #2335.
1899 if(numentries == 0) {
1900 dptr_close(&dptr_num);
1901 if (Protocol < PROTOCOL_NT1) {
1902 return ERROR_DOS(ERRDOS,ERRnofiles);
1904 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1908 /* At this point pdata points to numentries directory entries. */
1910 /* Set up the return parameter block */
1911 SSVAL(params,0,dptr_num);
1912 SSVAL(params,2,numentries);
1913 SSVAL(params,4,finished);
1914 SSVAL(params,6,0); /* Never an EA error */
1915 SSVAL(params,8,last_entry_off);
1917 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1919 if ((! *directory) && dptr_path(dptr_num))
1920 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1922 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1923 smb_fn_name(CVAL(inbuf,smb_com)),
1924 mask, directory, dirtype, numentries ) );
1927 * Force a name mangle here to ensure that the
1928 * mask as an 8.3 name is top of the mangled cache.
1929 * The reasons for this are subtle. Don't remove
1930 * this code unless you know what you are doing
1931 * (see PR#13758). JRA.
1934 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1935 mangle_map(mask, True, True, conn->params);
1940 /****************************************************************************
1941 Reply to a TRANS2_FINDNEXT.
1942 ****************************************************************************/
1944 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1945 char **pparams, int total_params, char **ppdata, int total_data,
1946 unsigned int max_data_bytes)
1948 /* We must be careful here that we don't return more than the
1949 allowed number of data bytes. If this means returning fewer than
1950 maxentries then so be it. We assume that the redirector has
1951 enough room for the fixed number of parameter bytes it has
1953 char *params = *pparams;
1954 char *pdata = *ppdata;
1959 uint16 findnext_flags;
1960 BOOL close_after_request;
1962 BOOL requires_resume_key;
1964 BOOL mask_contains_wcard = False;
1965 pstring resume_name;
1971 int i, last_entry_off=0;
1972 BOOL finished = False;
1973 BOOL dont_descend = False;
1974 BOOL out_of_space = False;
1975 int space_remaining;
1976 TALLOC_CTX *ea_ctx = NULL;
1977 struct ea_list *ea_list = NULL;
1978 NTSTATUS ntstatus = NT_STATUS_OK;
1980 if (total_params < 13) {
1981 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1984 dptr_num = SVAL(params,0);
1985 maxentries = SVAL(params,2);
1986 info_level = SVAL(params,4);
1987 resume_key = IVAL(params,6);
1988 findnext_flags = SVAL(params,10);
1989 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1990 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1991 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1992 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1994 *mask = *directory = *resume_name = 0;
1996 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1997 if (!NT_STATUS_IS_OK(ntstatus)) {
1998 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1999 complain (it thinks we're asking for the directory above the shared
2000 path or an invalid name). Catch this as the resume name is only compared, never used in
2001 a file access. JRA. */
2002 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2003 pstrcpy(resume_name, "..");
2004 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2005 pstrcpy(resume_name, ".");
2007 return ERROR_NT(ntstatus);
2011 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2012 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2013 resume_key = %d resume name = %s continue=%d level = %d\n",
2014 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2015 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2018 /* W2K3 seems to treat zero as 1. */
2022 switch (info_level) {
2023 case SMB_FIND_INFO_STANDARD:
2024 case SMB_FIND_EA_SIZE:
2025 case SMB_FIND_EA_LIST:
2026 case SMB_FIND_FILE_DIRECTORY_INFO:
2027 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2028 case SMB_FIND_FILE_NAMES_INFO:
2029 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2030 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2031 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2033 case SMB_FIND_FILE_UNIX:
2034 case SMB_FIND_FILE_UNIX_INFO2:
2035 if (!lp_unix_extensions()) {
2036 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2040 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2043 if (info_level == SMB_FIND_EA_LIST) {
2046 if (total_data < 4) {
2047 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2050 ea_size = IVAL(pdata,0);
2051 if (ea_size != total_data) {
2052 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2053 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2054 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2057 if (!lp_ea_support(SNUM(conn))) {
2058 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2061 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2062 return ERROR_NT(NT_STATUS_NO_MEMORY);
2065 /* Pull out the list of names. */
2066 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2068 talloc_destroy(ea_ctx);
2069 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2073 *ppdata = (char *)SMB_REALLOC(
2074 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2075 if(*ppdata == NULL) {
2076 talloc_destroy(ea_ctx);
2077 return ERROR_NT(NT_STATUS_NO_MEMORY);
2082 /* Realloc the params space */
2083 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2084 if(*pparams == NULL ) {
2085 talloc_destroy(ea_ctx);
2086 return ERROR_NT(NT_STATUS_NO_MEMORY);
2091 /* Check that the dptr is valid */
2092 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2093 talloc_destroy(ea_ctx);
2094 return ERROR_DOS(ERRDOS,ERRnofiles);
2097 string_set(&conn->dirpath,dptr_path(dptr_num));
2099 /* Get the wildcard mask from the dptr */
2100 if((p = dptr_wcard(dptr_num))== NULL) {
2101 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2102 talloc_destroy(ea_ctx);
2103 return ERROR_DOS(ERRDOS,ERRnofiles);
2107 pstrcpy(directory,conn->dirpath);
2109 /* Get the attr mask from the dptr */
2110 dirtype = dptr_attr(dptr_num);
2112 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2113 dptr_num, mask, dirtype,
2115 dptr_TellDir(conn->dirptr)));
2117 /* We don't need to check for VOL here as this is returned by
2118 a different TRANS2 call. */
2120 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2121 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2122 dont_descend = True;
2125 space_remaining = max_data_bytes;
2126 out_of_space = False;
2129 * Seek to the correct position. We no longer use the resume key but
2130 * depend on the last file name instead.
2133 if(*resume_name && !continue_bit) {
2136 long current_pos = 0;
2138 * Remember, mangle_map is called by
2139 * get_lanman2_dir_entry(), so the resume name
2140 * could be mangled. Ensure we check the unmangled name.
2143 if (mangle_is_mangled(resume_name, conn->params)) {
2144 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2149 * Fix for NT redirector problem triggered by resume key indexes
2150 * changing between directory scans. We now return a resume key of 0
2151 * and instead look for the filename to continue from (also given
2152 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2153 * findfirst/findnext (as is usual) then the directory pointer
2154 * should already be at the correct place.
2157 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2158 } /* end if resume_name && !continue_bit */
2160 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2161 BOOL got_exact_match = False;
2163 /* this is a heuristic to avoid seeking the dirptr except when
2164 absolutely necessary. It allows for a filename of about 40 chars */
2165 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2166 out_of_space = True;
2169 finished = !get_lanman2_dir_entry(conn,
2171 mask,dirtype,info_level,
2172 requires_resume_key,dont_descend,
2173 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2174 &last_entry_off, ea_list, ea_ctx);
2177 if (finished && out_of_space)
2180 if (!finished && !out_of_space)
2184 * As an optimisation if we know we aren't looking
2185 * for a wildcard name (ie. the name matches the wildcard exactly)
2186 * then we can finish on any (first) match.
2187 * This speeds up large directory searches. JRA.
2193 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2196 talloc_destroy(ea_ctx);
2198 /* Check if we can close the dirptr */
2199 if(close_after_request || (finished && close_if_end)) {
2200 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2201 dptr_close(&dptr_num); /* This frees up the saved mask */
2204 /* Set up the return parameter block */
2205 SSVAL(params,0,numentries);
2206 SSVAL(params,2,finished);
2207 SSVAL(params,4,0); /* Never an EA error */
2208 SSVAL(params,6,last_entry_off);
2210 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2212 if ((! *directory) && dptr_path(dptr_num))
2213 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2215 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2216 smb_fn_name(CVAL(inbuf,smb_com)),
2217 mask, directory, dirtype, numentries ) );
2222 /****************************************************************************
2223 Reply to a TRANS2_QFSINFO (query filesystem info).
2224 ****************************************************************************/
2226 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2227 char **pparams, int total_params, char **ppdata, int total_data,
2228 unsigned int max_data_bytes)
2231 char *params = *pparams;
2235 char *vname = volume_label(SNUM(conn));
2236 int snum = SNUM(conn);
2237 char *fstype = lp_fstype(SNUM(conn));
2240 if (total_params < 2) {
2241 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2244 info_level = SVAL(params,0);
2246 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2248 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2249 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2250 return ERROR_DOS(ERRSRV,ERRinvdevice);
2253 *ppdata = (char *)SMB_REALLOC(
2254 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2255 if (*ppdata == NULL ) {
2256 return ERROR_NT(NT_STATUS_NO_MEMORY);
2260 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2262 switch (info_level) {
2263 case SMB_INFO_ALLOCATION:
2265 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2267 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2268 return(UNIXERROR(ERRHRD,ERRgeneral));
2271 block_size = lp_block_size(snum);
2272 if (bsize < block_size) {
2273 SMB_BIG_UINT factor = block_size/bsize;
2278 if (bsize > block_size) {
2279 SMB_BIG_UINT factor = bsize/block_size;
2284 bytes_per_sector = 512;
2285 sectors_per_unit = bsize/bytes_per_sector;
2287 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2288 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2289 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2291 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2292 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2293 SIVAL(pdata,l1_cUnit,dsize);
2294 SIVAL(pdata,l1_cUnitAvail,dfree);
2295 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2299 case SMB_INFO_VOLUME:
2300 /* Return volume name */
2302 * Add volume serial number - hash of a combination of
2303 * the called hostname and the service name.
2305 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2307 * Win2k3 and previous mess this up by sending a name length
2308 * one byte short. I believe only older clients (OS/2 Win9x) use
2309 * this call so try fixing this by adding a terminating null to
2310 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2312 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2313 SCVAL(pdata,l2_vol_cch,len);
2314 data_len = l2_vol_szVolLabel + len;
2315 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2316 (unsigned)st.st_ctime, len, vname));
2319 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2320 case SMB_FS_ATTRIBUTE_INFORMATION:
2323 #if defined(HAVE_SYS_QUOTAS)
2324 quota_flag = FILE_VOLUME_QUOTAS;
2327 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2328 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2329 quota_flag); /* FS ATTRIBUTES */
2331 SIVAL(pdata,4,255); /* Max filename component length */
2332 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2333 and will think we can't do long filenames */
2334 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2336 data_len = 12 + len;
2339 case SMB_QUERY_FS_LABEL_INFO:
2340 case SMB_FS_LABEL_INFORMATION:
2341 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2346 case SMB_QUERY_FS_VOLUME_INFO:
2347 case SMB_FS_VOLUME_INFORMATION:
2350 * Add volume serial number - hash of a combination of
2351 * the called hostname and the service name.
2353 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2354 (str_checksum(get_local_machine_name())<<16));
2356 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2357 SIVAL(pdata,12,len);
2359 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2360 (int)strlen(vname),vname, lp_servicename(snum)));
2363 case SMB_QUERY_FS_SIZE_INFO:
2364 case SMB_FS_SIZE_INFORMATION:
2366 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2368 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2369 return(UNIXERROR(ERRHRD,ERRgeneral));
2371 block_size = lp_block_size(snum);
2372 if (bsize < block_size) {
2373 SMB_BIG_UINT factor = block_size/bsize;
2378 if (bsize > block_size) {
2379 SMB_BIG_UINT factor = bsize/block_size;
2384 bytes_per_sector = 512;
2385 sectors_per_unit = bsize/bytes_per_sector;
2386 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2387 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2388 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2389 SBIG_UINT(pdata,0,dsize);
2390 SBIG_UINT(pdata,8,dfree);
2391 SIVAL(pdata,16,sectors_per_unit);
2392 SIVAL(pdata,20,bytes_per_sector);
2396 case SMB_FS_FULL_SIZE_INFORMATION:
2398 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2400 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2401 return(UNIXERROR(ERRHRD,ERRgeneral));
2403 block_size = lp_block_size(snum);
2404 if (bsize < block_size) {
2405 SMB_BIG_UINT factor = block_size/bsize;
2410 if (bsize > block_size) {
2411 SMB_BIG_UINT factor = bsize/block_size;
2416 bytes_per_sector = 512;
2417 sectors_per_unit = bsize/bytes_per_sector;
2418 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2419 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2420 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2421 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2422 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2423 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2424 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2425 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2429 case SMB_QUERY_FS_DEVICE_INFO:
2430 case SMB_FS_DEVICE_INFORMATION:
2432 SIVAL(pdata,0,0); /* dev type */
2433 SIVAL(pdata,4,0); /* characteristics */
2436 #ifdef HAVE_SYS_QUOTAS
2437 case SMB_FS_QUOTA_INFORMATION:
2439 * what we have to send --metze:
2441 * Unknown1: 24 NULL bytes
2442 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2443 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2444 * Quota Flags: 2 byte :
2445 * Unknown3: 6 NULL bytes
2449 * details for Quota Flags:
2451 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2452 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2453 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2454 * 0x0001 Enable Quotas: enable quota for this fs
2458 /* we need to fake up a fsp here,
2459 * because its not send in this call
2462 SMB_NTQUOTA_STRUCT quotas;
2465 ZERO_STRUCT(quotas);
2471 if (current_user.ut.uid != 0) {
2472 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2473 lp_servicename(SNUM(conn)),conn->user));
2474 return ERROR_DOS(ERRDOS,ERRnoaccess);
2477 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2478 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2479 return ERROR_DOS(ERRSRV,ERRerror);
2484 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2486 /* Unknown1 24 NULL bytes*/
2487 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2488 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2489 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2491 /* Default Soft Quota 8 bytes */
2492 SBIG_UINT(pdata,24,quotas.softlim);
2494 /* Default Hard Quota 8 bytes */
2495 SBIG_UINT(pdata,32,quotas.hardlim);
2497 /* Quota flag 2 bytes */
2498 SSVAL(pdata,40,quotas.qflags);
2500 /* Unknown3 6 NULL bytes */
2506 #endif /* HAVE_SYS_QUOTAS */
2507 case SMB_FS_OBJECTID_INFORMATION:
2512 * Query the version and capabilities of the CIFS UNIX extensions
2516 case SMB_QUERY_CIFS_UNIX_INFO:
2517 if (!lp_unix_extensions()) {
2518 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2521 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2522 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2523 /* We have POSIX ACLs, pathname and locking capability. */
2524 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2525 CIFS_UNIX_POSIX_ACLS_CAP|
2526 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2527 CIFS_UNIX_FCNTL_LOCKS_CAP|
2528 CIFS_UNIX_EXTATTR_CAP|
2529 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2532 case SMB_QUERY_POSIX_FS_INFO:
2535 vfs_statvfs_struct svfs;
2537 if (!lp_unix_extensions()) {
2538 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2541 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2545 SIVAL(pdata,0,svfs.OptimalTransferSize);
2546 SIVAL(pdata,4,svfs.BlockSize);
2547 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2548 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2549 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2550 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2551 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2552 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2553 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2555 } else if (rc == EOPNOTSUPP) {
2556 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2557 #endif /* EOPNOTSUPP */
2559 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2560 return ERROR_DOS(ERRSRV,ERRerror);
2565 case SMB_QUERY_POSIX_WHOAMI:
2571 if (!lp_unix_extensions()) {
2572 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2575 if (max_data_bytes < 40) {
2576 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2579 /* We ARE guest if global_sid_Builtin_Guests is
2580 * in our list of SIDs.
2582 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2583 current_user.nt_user_token)) {
2584 flags |= SMB_WHOAMI_GUEST;
2587 /* We are NOT guest if global_sid_Authenticated_Users
2588 * is in our list of SIDs.
2590 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2591 current_user.nt_user_token)) {
2592 flags &= ~SMB_WHOAMI_GUEST;
2595 /* NOTE: 8 bytes for UID/GID, irrespective of native
2596 * platform size. This matches
2597 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2599 data_len = 4 /* flags */
2606 + 4 /* pad/reserved */
2607 + (current_user.ut.ngroups * 8)
2609 + (current_user.nt_user_token->num_sids *
2613 SIVAL(pdata, 0, flags);
2614 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2615 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2616 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2619 if (data_len >= max_data_bytes) {
2620 /* Potential overflow, skip the GIDs and SIDs. */
2622 SIVAL(pdata, 24, 0); /* num_groups */
2623 SIVAL(pdata, 28, 0); /* num_sids */
2624 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2625 SIVAL(pdata, 36, 0); /* reserved */
2631 SIVAL(pdata, 24, current_user.ut.ngroups);
2633 current_user.nt_user_token->num_sids);
2635 /* We walk the SID list twice, but this call is fairly
2636 * infrequent, and I don't expect that it's performance
2637 * sensitive -- jpeach
2639 for (i = 0, sid_bytes = 0;
2640 i < current_user.nt_user_token->num_sids; ++i) {
2642 sid_size(¤t_user.nt_user_token->user_sids[i]);
2645 /* SID list byte count */
2646 SIVAL(pdata, 32, sid_bytes);
2648 /* 4 bytes pad/reserved - must be zero */
2649 SIVAL(pdata, 36, 0);
2653 for (i = 0; i < current_user.ut.ngroups; ++i) {
2654 SBIG_UINT(pdata, data_len,
2655 (SMB_BIG_UINT)current_user.ut.groups[i]);
2661 i < current_user.nt_user_token->num_sids; ++i) {
2663 sid_size(¤t_user.nt_user_token->user_sids[i]);
2665 sid_linearize(pdata + data_len, sid_len,
2666 ¤t_user.nt_user_token->user_sids[i]);
2667 data_len += sid_len;
2673 case SMB_MAC_QUERY_FS_INFO:
2675 * Thursby MAC extension... ONLY on NTFS filesystems
2676 * once we do streams then we don't need this
2678 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2680 SIVAL(pdata,84,0x100); /* Don't support mac... */
2685 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2689 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2691 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2696 /****************************************************************************
2697 Reply to a TRANS2_SETFSINFO (set filesystem info).
2698 ****************************************************************************/
2700 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2701 char **pparams, int total_params, char **ppdata, int total_data,
2702 unsigned int max_data_bytes)
2704 char *pdata = *ppdata;
2705 char *params = *pparams;
2709 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2712 if (total_params < 4) {
2713 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2715 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2718 info_level = SVAL(params,2);
2720 switch(info_level) {
2721 case SMB_SET_CIFS_UNIX_INFO:
2723 uint16 client_unix_major;
2724 uint16 client_unix_minor;
2725 uint32 client_unix_cap_low;
2726 uint32 client_unix_cap_high;
2728 if (!lp_unix_extensions()) {
2729 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2732 /* There should be 12 bytes of capabilities set. */
2733 if (total_data < 8) {
2734 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2736 client_unix_major = SVAL(pdata,0);
2737 client_unix_minor = SVAL(pdata,2);
2738 client_unix_cap_low = IVAL(pdata,4);
2739 client_unix_cap_high = IVAL(pdata,8);
2740 /* Just print these values for now. */
2741 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2742 cap_low = 0x%x, cap_high = 0x%x\n",
2743 (unsigned int)client_unix_major,
2744 (unsigned int)client_unix_minor,
2745 (unsigned int)client_unix_cap_low,
2746 (unsigned int)client_unix_cap_high ));
2748 /* Here is where we must switch to posix pathname processing... */
2749 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2750 lp_set_posix_pathnames();
2751 mangle_change_to_posix();
2754 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2755 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2756 /* Client that knows how to do posix locks,
2757 * but not posix open/mkdir operations. Set a
2758 * default type for read/write checks. */
2760 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2765 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2768 size_t param_len = 0;
2769 size_t data_len = total_data;
2771 if (!lp_unix_extensions()) {
2772 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2775 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2777 status = srv_request_encryption_setup(conn,
2778 (unsigned char **)ppdata,
2780 (unsigned char **)pparams,
2784 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2785 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2786 } else if (!NT_STATUS_IS_OK(status)) {
2787 return ERROR_NT(status);
2790 send_trans2_replies(outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2792 if (NT_STATUS_IS_OK(status)) {
2793 /* Server-side transport encryption is now *on*. */
2794 status = srv_encryption_start(conn);
2795 if (!NT_STATUS_IS_OK(status)) {
2796 exit_server_cleanly("Failure in setting up encrypted transport");
2801 case SMB_FS_QUOTA_INFORMATION:
2803 files_struct *fsp = NULL;
2804 SMB_NTQUOTA_STRUCT quotas;
2806 ZERO_STRUCT(quotas);
2809 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2810 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2811 lp_servicename(SNUM(conn)),conn->user));
2812 return ERROR_DOS(ERRSRV,ERRaccess);
2815 /* note: normaly there're 48 bytes,
2816 * but we didn't use the last 6 bytes for now
2819 fsp = file_fsp(params,0);
2820 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2821 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2822 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2825 if (total_data < 42) {
2826 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2828 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2831 /* unknown_1 24 NULL bytes in pdata*/
2833 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2834 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2835 #ifdef LARGE_SMB_OFF_T
2836 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2837 #else /* LARGE_SMB_OFF_T */
2838 if ((IVAL(pdata,28) != 0)&&
2839 ((quotas.softlim != 0xFFFFFFFF)||
2840 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2841 /* more than 32 bits? */
2842 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2844 #endif /* LARGE_SMB_OFF_T */
2846 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2847 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2848 #ifdef LARGE_SMB_OFF_T
2849 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2850 #else /* LARGE_SMB_OFF_T */
2851 if ((IVAL(pdata,36) != 0)&&
2852 ((quotas.hardlim != 0xFFFFFFFF)||
2853 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2854 /* more than 32 bits? */
2855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2857 #endif /* LARGE_SMB_OFF_T */
2859 /* quota_flags 2 bytes **/
2860 quotas.qflags = SVAL(pdata,40);
2862 /* unknown_2 6 NULL bytes follow*/
2864 /* now set the quotas */
2865 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2866 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2867 return ERROR_DOS(ERRSRV,ERRerror);
2873 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2875 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2880 * sending this reply works fine,
2881 * but I'm not sure it's the same
2882 * like windows do...
2885 outsize = set_message(outbuf,10,0,True);
2890 #if defined(HAVE_POSIX_ACLS)
2891 /****************************************************************************
2892 Utility function to count the number of entries in a POSIX acl.
2893 ****************************************************************************/
2895 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2897 unsigned int ace_count = 0;
2898 int entry_id = SMB_ACL_FIRST_ENTRY;
2899 SMB_ACL_ENTRY_T entry;
2901 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2903 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2904 entry_id = SMB_ACL_NEXT_ENTRY;
2911 /****************************************************************************
2912 Utility function to marshall a POSIX acl into wire format.
2913 ****************************************************************************/
2915 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2917 int entry_id = SMB_ACL_FIRST_ENTRY;
2918 SMB_ACL_ENTRY_T entry;
2920 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2921 SMB_ACL_TAG_T tagtype;
2922 SMB_ACL_PERMSET_T permset;
2923 unsigned char perms = 0;
2924 unsigned int own_grp;
2927 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2928 entry_id = SMB_ACL_NEXT_ENTRY;
2931 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2932 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2936 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2937 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2941 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2942 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2943 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2945 SCVAL(pdata,1,perms);
2948 case SMB_ACL_USER_OBJ:
2949 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2950 own_grp = (unsigned int)pst->st_uid;
2951 SIVAL(pdata,2,own_grp);
2956 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2958 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2960 own_grp = (unsigned int)*puid;
2961 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2962 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2963 SIVAL(pdata,2,own_grp);
2967 case SMB_ACL_GROUP_OBJ:
2968 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2969 own_grp = (unsigned int)pst->st_gid;
2970 SIVAL(pdata,2,own_grp);
2975 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2977 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2979 own_grp = (unsigned int)*pgid;
2980 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2981 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2982 SIVAL(pdata,2,own_grp);
2987 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2988 SIVAL(pdata,2,0xFFFFFFFF);
2989 SIVAL(pdata,6,0xFFFFFFFF);
2992 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2993 SIVAL(pdata,2,0xFFFFFFFF);
2994 SIVAL(pdata,6,0xFFFFFFFF);
2997 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3000 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3007 /****************************************************************************
3008 Store the FILE_UNIX_BASIC info.
3009 ****************************************************************************/
3011 static char *store_file_unix_basic(connection_struct *conn,
3014 const SMB_STRUCT_STAT *psbuf)
3016 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3017 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3019 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3022 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3025 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3026 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3027 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3030 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3034 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3038 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3041 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3045 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3049 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3052 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3056 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3063 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3064 * the chflags(2) (or equivalent) flags.
3066 * XXX: this really should be behind the VFS interface. To do this, we would
3067 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3068 * Each VFS module could then implement it's own mapping as appropriate for the
3069 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3071 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3075 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3079 { UF_IMMUTABLE, EXT_IMMUTABLE },
3083 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3087 { UF_HIDDEN, EXT_HIDDEN },
3090 /* Do not remove. We need to guarantee that this array has at least one
3091 * entry to build on HP-UX.
3097 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3098 uint32 *smb_fflags, uint32 *smb_fmask)
3100 #ifdef HAVE_STAT_ST_FLAGS
3103 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3104 *smb_fmask |= info2_flags_map[i].smb_fflag;
3105 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3106 *smb_fflags |= info2_flags_map[i].smb_fflag;
3109 #endif /* HAVE_STAT_ST_FLAGS */
3112 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3113 const uint32 smb_fflags,
3114 const uint32 smb_fmask,
3117 #ifdef HAVE_STAT_ST_FLAGS
3118 uint32 max_fmask = 0;
3121 *stat_fflags = psbuf->st_flags;
3123 /* For each flags requested in smb_fmask, check the state of the
3124 * corresponding flag in smb_fflags and set or clear the matching
3128 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3129 max_fmask |= info2_flags_map[i].smb_fflag;
3130 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3131 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3132 *stat_fflags |= info2_flags_map[i].stat_fflag;
3134 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3139 /* If smb_fmask is asking to set any bits that are not supported by
3140 * our flag mappings, we should fail.
3142 if ((smb_fmask & max_fmask) != smb_fmask) {
3149 #endif /* HAVE_STAT_ST_FLAGS */
3153 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3154 * of file flags and birth (create) time.
3156 static char *store_file_unix_basic_info2(connection_struct *conn,
3159 const SMB_STRUCT_STAT *psbuf)
3161 uint32 file_flags = 0;
3162 uint32 flags_mask = 0;
3164 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3166 /* Create (birth) time 64 bit */
3167 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3170 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3171 SIVAL(pdata, 0, file_flags); /* flags */
3172 SIVAL(pdata, 4, flags_mask); /* mask */
3178 /****************************************************************************
3179 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3180 file name or file id).
3181 ****************************************************************************/
3183 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3184 unsigned int tran_call,
3185 char **pparams, int total_params, char **ppdata, int total_data,
3186 unsigned int max_data_bytes)
3188 char *params = *pparams;
3189 char *pdata = *ppdata;
3193 SMB_OFF_T file_size=0;
3194 SMB_BIG_UINT allocation_size=0;
3195 unsigned int data_size = 0;
3196 unsigned int param_size = 2;
3197 SMB_STRUCT_STAT sbuf;
3198 pstring fname, dos_fname;
3203 BOOL delete_pending = False;
3205 time_t create_time, mtime, atime;
3206 struct timespec create_time_ts, mtime_ts, atime_ts;
3207 files_struct *fsp = NULL;
3208 TALLOC_CTX *data_ctx = NULL;
3209 struct ea_list *ea_list = NULL;
3210 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3211 char *lock_data = NULL;
3214 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3218 if (tran_call == TRANSACT2_QFILEINFO) {
3219 if (total_params < 4) {
3220 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3223 fsp = file_fsp(params,0);
3224 info_level = SVAL(params,2);
3226 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3228 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3229 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3232 if(fsp && (fsp->fake_file_handle)) {
3234 * This is actually for the QUOTA_FAKE_FILE --metze
3237 pstrcpy(fname, fsp->fsp_name);
3238 /* We know this name is ok, it's already passed the checks. */
3240 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3242 * This is actually a QFILEINFO on a directory
3243 * handle (returned from an NT SMB). NT5.0 seems
3244 * to do this call. JRA.
3246 /* We know this name is ok, it's already passed the checks. */
3247 pstrcpy(fname, fsp->fsp_name);
3249 if (INFO_LEVEL_IS_UNIX(info_level)) {
3250 /* Always do lstat for UNIX calls. */
3251 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3252 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3253 return UNIXERROR(ERRDOS,ERRbadpath);
3255 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3256 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3257 return UNIXERROR(ERRDOS,ERRbadpath);
3260 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3263 * Original code - this is an open file.
3265 CHECK_FSP(fsp,conn);
3267 pstrcpy(fname, fsp->fsp_name);
3268 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3269 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3270 return(UNIXERROR(ERRDOS,ERRbadfid));
3272 pos = fsp->fh->position_information;
3273 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3274 access_mask = fsp->access_mask;
3277 NTSTATUS status = NT_STATUS_OK;
3280 if (total_params < 7) {
3281 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3284 info_level = SVAL(params,0);
3286 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3288 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3289 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3292 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3293 if (!NT_STATUS_IS_OK(status)) {
3294 return ERROR_NT(status);
3297 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3298 if (!NT_STATUS_IS_OK(status)) {
3299 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3300 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3302 return ERROR_NT(status);
3305 status = unix_convert(conn, fname, False, NULL, &sbuf);
3306 if (!NT_STATUS_IS_OK(status)) {
3307 return ERROR_NT(status);
3309 status = check_name(conn, fname);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3312 return ERROR_NT(status);
3315 if (INFO_LEVEL_IS_UNIX(info_level)) {
3316 /* Always do lstat for UNIX calls. */
3317 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3318 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3319 return UNIXERROR(ERRDOS,ERRbadpath);
3321 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3322 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3323 return UNIXERROR(ERRDOS,ERRbadpath);
3326 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3327 if (delete_pending) {
3328 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3332 nlink = sbuf.st_nlink;
3334 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3335 /* NTFS does not seem to count ".." */
3339 if ((nlink > 0) && delete_pending) {
3343 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3344 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3347 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3348 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3350 p = strrchr_m(fname,'/');
3356 mode = dos_mode(conn,fname,&sbuf);
3358 mode = FILE_ATTRIBUTE_NORMAL;
3360 fullpathname = fname;
3362 file_size = get_file_size(sbuf);
3364 /* Pull out any data sent here before we realloc. */
3365 switch (info_level) {
3366 case SMB_INFO_QUERY_EAS_FROM_LIST:
3368 /* Pull any EA list from the data portion. */
3371 if (total_data < 4) {
3372 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3374 ea_size = IVAL(pdata,0);
3376 if (total_data > 0 && ea_size != total_data) {
3377 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3378 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3379 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3382 if (!lp_ea_support(SNUM(conn))) {
3383 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3386 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3387 return ERROR_NT(NT_STATUS_NO_MEMORY);
3390 /* Pull out the list of names. */
3391 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3393 talloc_destroy(data_ctx);
3394 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3399 case SMB_QUERY_POSIX_LOCK:
3401 if (fsp == NULL || fsp->fh->fd == -1) {
3402 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3405 if (total_data != POSIX_LOCK_DATA_SIZE) {
3406 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3409 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3410 return ERROR_NT(NT_STATUS_NO_MEMORY);
3413 /* Copy the lock range data. */
3414 lock_data = (char *)talloc_memdup(
3415 data_ctx, pdata, total_data);
3417 talloc_destroy(data_ctx);
3418 return ERROR_NT(NT_STATUS_NO_MEMORY);
3425 *pparams = (char *)SMB_REALLOC(*pparams,2);
3426 if (*pparams == NULL) {
3427 talloc_destroy(data_ctx);
3428 return ERROR_NT(NT_STATUS_NO_MEMORY);
3432 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3433 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3434 if (*ppdata == NULL ) {
3435 talloc_destroy(data_ctx);
3436 return ERROR_NT(NT_STATUS_NO_MEMORY);
3440 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3441 mtime_ts = get_mtimespec(&sbuf);
3442 atime_ts = get_atimespec(&sbuf);
3444 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3447 if (!null_timespec(fsp->pending_modtime)) {
3448 /* the pending modtime overrides the current modtime */
3449 mtime_ts = fsp->pending_modtime;
3452 /* Do we have this path open ? */
3453 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3454 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3455 /* the pending modtime overrides the current modtime */
3456 mtime_ts = fsp1->pending_modtime;
3458 if (fsp1 && fsp1->initial_allocation_size) {
3459 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3463 if (lp_dos_filetime_resolution(SNUM(conn))) {
3464 dos_filetime_timespec(&create_time_ts);
3465 dos_filetime_timespec(&mtime_ts);
3466 dos_filetime_timespec(&atime_ts);
3469 create_time = convert_timespec_to_time_t(create_time_ts);
3470 mtime = convert_timespec_to_time_t(mtime_ts);
3471 atime = convert_timespec_to_time_t(atime_ts);
3473 /* NT expects the name to be in an exact form of the *full*
3474 filename. See the trans2 torture test */
3475 if (strequal(base_name,".")) {
3476 pstrcpy(dos_fname, "\\");
3478 pstr_sprintf(dos_fname, "\\%s", fname);
3479 string_replace(dos_fname, '/', '\\');
3482 switch (info_level) {
3483 case SMB_INFO_STANDARD:
3484 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3486 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3487 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3488 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3489 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3490 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3491 SSVAL(pdata,l1_attrFile,mode);
3494 case SMB_INFO_QUERY_EA_SIZE:
3496 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3497 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3499 srv_put_dos_date2(pdata,0,create_time);
3500 srv_put_dos_date2(pdata,4,atime);
3501 srv_put_dos_date2(pdata,8,mtime); /* write time */
3502 SIVAL(pdata,12,(uint32)file_size);
3503 SIVAL(pdata,16,(uint32)allocation_size);
3504 SSVAL(pdata,20,mode);
3505 SIVAL(pdata,22,ea_size);
3509 case SMB_INFO_IS_NAME_VALID:
3510 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3511 if (tran_call == TRANSACT2_QFILEINFO) {
3512 /* os/2 needs this ? really ?*/
3513 return ERROR_DOS(ERRDOS,ERRbadfunc);
3519 case SMB_INFO_QUERY_EAS_FROM_LIST:
3521 size_t total_ea_len = 0;
3522 struct ea_list *ea_file_list = NULL;
3524 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3526 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3527 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3529 if (!ea_list || (total_ea_len > data_size)) {
3530 talloc_destroy(data_ctx);
3532 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3536 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3537 talloc_destroy(data_ctx);
3541 case SMB_INFO_QUERY_ALL_EAS:
3543 /* We have data_size bytes to put EA's into. */
3544 size_t total_ea_len = 0;
3546 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3548 data_ctx = talloc_init("ea_ctx");
3550 return ERROR_NT(NT_STATUS_NO_MEMORY);
3553 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3554 if (!ea_list || (total_ea_len > data_size)) {
3555 talloc_destroy(data_ctx);
3557 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3561 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3562 talloc_destroy(data_ctx);
3566 case SMB_FILE_BASIC_INFORMATION:
3567 case SMB_QUERY_FILE_BASIC_INFO:
3569 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3570 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3571 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3573 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3577 put_long_date_timespec(pdata,create_time_ts);
3578 put_long_date_timespec(pdata+8,atime_ts);
3579 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3580 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3581 SIVAL(pdata,32,mode);
3583 DEBUG(5,("SMB_QFBI - "));
3584 DEBUG(5,("create: %s ", ctime(&create_time)));
3585 DEBUG(5,("access: %s ", ctime(&atime)));
3586 DEBUG(5,("write: %s ", ctime(&mtime)));
3587 DEBUG(5,("change: %s ", ctime(&mtime)));
3588 DEBUG(5,("mode: %x\n", mode));
3591 case SMB_FILE_STANDARD_INFORMATION:
3592 case SMB_QUERY_FILE_STANDARD_INFO:
3594 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3596 SOFF_T(pdata,0,allocation_size);
3597 SOFF_T(pdata,8,file_size);
3598 SIVAL(pdata,16,nlink);
3599 SCVAL(pdata,20,delete_pending?1:0);
3600 SCVAL(pdata,21,(mode&aDIR)?1:0);
3601 SSVAL(pdata,22,0); /* Padding. */
3604 case SMB_FILE_EA_INFORMATION:
3605 case SMB_QUERY_FILE_EA_INFO:
3607 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3608 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3610 SIVAL(pdata,0,ea_size);
3614 /* Get the 8.3 name - used if NT SMB was negotiated. */
3615 case SMB_QUERY_FILE_ALT_NAME_INFO:
3616 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3620 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3621 pstrcpy(short_name,base_name);
3622 /* Mangle if not already 8.3 */
3623 if(!mangle_is_8_3(short_name, True, conn->params)) {
3624 mangle_map(short_name,True,True,conn->params);
3626 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3627 data_size = 4 + len;
3632 case SMB_QUERY_FILE_NAME_INFO:
3634 this must be *exactly* right for ACLs on mapped drives to work
3636 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3637 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3638 data_size = 4 + len;
3642 case SMB_FILE_ALLOCATION_INFORMATION:
3643 case SMB_QUERY_FILE_ALLOCATION_INFO:
3644 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3646 SOFF_T(pdata,0,allocation_size);
3649 case SMB_FILE_END_OF_FILE_INFORMATION:
3650 case SMB_QUERY_FILE_END_OF_FILEINFO:
3651 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3653 SOFF_T(pdata,0,file_size);
3656 case SMB_QUERY_FILE_ALL_INFO:
3657 case SMB_FILE_ALL_INFORMATION:
3659 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3660 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3661 put_long_date_timespec(pdata,create_time_ts);
3662 put_long_date_timespec(pdata+8,atime_ts);
3663 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3664 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3665 SIVAL(pdata,32,mode);
3666 SIVAL(pdata,36,0); /* padding. */
3668 SOFF_T(pdata,0,allocation_size);
3669 SOFF_T(pdata,8,file_size);
3670 SIVAL(pdata,16,nlink);
3671 SCVAL(pdata,20,delete_pending);
3672 SCVAL(pdata,21,(mode&aDIR)?1:0);
3675 SIVAL(pdata,0,ea_size);
3676 pdata += 4; /* EA info */
3677 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3680 data_size = PTR_DIFF(pdata,(*ppdata));
3683 case SMB_FILE_INTERNAL_INFORMATION:
3684 /* This should be an index number - looks like
3687 I think this causes us to fail the IFSKIT
3688 BasicFileInformationTest. -tpot */
3690 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3691 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3692 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3696 case SMB_FILE_ACCESS_INFORMATION:
3697 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3698 SIVAL(pdata,0,access_mask);
3702 case SMB_FILE_NAME_INFORMATION:
3703 /* Pathname with leading '\'. */
3706 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3707 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3708 SIVAL(pdata,0,byte_len);
3709 data_size = 4 + byte_len;
3713 case SMB_FILE_DISPOSITION_INFORMATION:
3714 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3716 SCVAL(pdata,0,delete_pending);
3719 case SMB_FILE_POSITION_INFORMATION:
3720 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3722 SOFF_T(pdata,0,pos);
3725 case SMB_FILE_MODE_INFORMATION:
3726 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3727 SIVAL(pdata,0,mode);
3731 case SMB_FILE_ALIGNMENT_INFORMATION:
3732 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3733 SIVAL(pdata,0,0); /* No alignment needed. */
3739 * NT4 server just returns "invalid query" to this - if we try to answer
3740 * it then NTws gets a BSOD! (tridge).
3741 * W2K seems to want this. JRA.
3743 case SMB_QUERY_FILE_STREAM_INFO:
3745 case SMB_FILE_STREAM_INFORMATION:
3746 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3750 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3751 SIVAL(pdata,0,0); /* ??? */
3752 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3753 SOFF_T(pdata,8,file_size);
3754 SIVAL(pdata,16,allocation_size);
3755 SIVAL(pdata,20,0); /* ??? */
3756 data_size = 24 + byte_len;
3760 case SMB_QUERY_COMPRESSION_INFO:
3761 case SMB_FILE_COMPRESSION_INFORMATION:
3762 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3763 SOFF_T(pdata,0,file_size);
3764 SIVAL(pdata,8,0); /* ??? */
3765 SIVAL(pdata,12,0); /* ??? */
3769 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3770 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3771 put_long_date_timespec(pdata,create_time_ts);
3772 put_long_date_timespec(pdata+8,atime_ts);
3773 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3774 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3775 SIVAL(pdata,32,allocation_size);
3776 SOFF_T(pdata,40,file_size);
3777 SIVAL(pdata,48,mode);
3778 SIVAL(pdata,52,0); /* ??? */
3782 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3783 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3784 SIVAL(pdata,0,mode);
3790 * CIFS UNIX Extensions.
3793 case SMB_QUERY_FILE_UNIX_BASIC:
3795 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3796 data_size = PTR_DIFF(pdata,(*ppdata));
3800 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3802 for (i=0; i<100; i++)
3803 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3809 case SMB_QUERY_FILE_UNIX_INFO2:
3811 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3812 data_size = PTR_DIFF(pdata,(*ppdata));
3816 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3818 for (i=0; i<100; i++)
3819 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3825 case SMB_QUERY_FILE_UNIX_LINK:
3829 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3831 if(!S_ISLNK(sbuf.st_mode))
3832 return(UNIXERROR(ERRSRV,ERRbadlink));
3834 return(UNIXERROR(ERRDOS,ERRbadlink));
3836 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3838 return(UNIXERROR(ERRDOS,ERRnoaccess));
3840 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3842 data_size = PTR_DIFF(pdata,(*ppdata));
3847 #if defined(HAVE_POSIX_ACLS)
3848 case SMB_QUERY_POSIX_ACL:
3850 SMB_ACL_T file_acl = NULL;
3851 SMB_ACL_T def_acl = NULL;
3852 uint16 num_file_acls = 0;
3853 uint16 num_def_acls = 0;
3855 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3856 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3858 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3861 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3862 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3864 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3867 if (S_ISDIR(sbuf.st_mode)) {
3868 if (fsp && fsp->is_directory) {
3869 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3871 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3873 def_acl = free_empty_sys_acl(conn, def_acl);
3876 num_file_acls = count_acl_entries(conn, file_acl);
3877 num_def_acls = count_acl_entries(conn, def_acl);
3879 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3880 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3882 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3883 SMB_POSIX_ACL_HEADER_SIZE) ));
3885 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3888 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3890 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3893 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3894 SSVAL(pdata,2,num_file_acls);
3895 SSVAL(pdata,4,num_def_acls);
3896 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3898 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3901 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3903 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3905 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3907 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3910 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3912 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3916 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3919 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3921 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3927 case SMB_QUERY_POSIX_LOCK:
3929 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3931 SMB_BIG_UINT offset;
3933 enum brl_type lock_type;
3935 if (total_data != POSIX_LOCK_DATA_SIZE) {
3936 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3939 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3940 case POSIX_LOCK_TYPE_READ:
3941 lock_type = READ_LOCK;
3943 case POSIX_LOCK_TYPE_WRITE:
3944 lock_type = WRITE_LOCK;
3946 case POSIX_LOCK_TYPE_UNLOCK:
3948 /* There's no point in asking for an unlock... */
3949 talloc_destroy(data_ctx);
3950 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3953 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3954 #if defined(HAVE_LONGLONG)
3955 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3956 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3957 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3958 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3959 #else /* HAVE_LONGLONG */
3960 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3961 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3962 #endif /* HAVE_LONGLONG */
3964 status = query_lock(fsp,
3971 if (ERROR_WAS_LOCK_DENIED(status)) {
3972 /* Here we need to report who has it locked... */
3973 data_size = POSIX_LOCK_DATA_SIZE;
3975 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3976 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3977 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3978 #if defined(HAVE_LONGLONG)
3979 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3980 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3981 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3982 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3983 #else /* HAVE_LONGLONG */
3984 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3985 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3986 #endif /* HAVE_LONGLONG */
3988 } else if (NT_STATUS_IS_OK(status)) {
3989 /* For success we just return a copy of what we sent
3990 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3991 data_size = POSIX_LOCK_DATA_SIZE;
3992 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3993 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3995 return ERROR_NT(status);
4001 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4004 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4009 /****************************************************************************
4010 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4012 ****************************************************************************/
4014 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4016 SMB_STRUCT_STAT sbuf1, sbuf2;
4017 pstring last_component_oldname;
4018 pstring last_component_newname;
4019 NTSTATUS status = NT_STATUS_OK;
4024 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4025 if (!NT_STATUS_IS_OK(status)) {
4029 status = check_name(conn, oldname);
4030 if (!NT_STATUS_IS_OK(status)) {
4034 /* source must already exist. */
4035 if (!VALID_STAT(sbuf1)) {
4036 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4039 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4040 if (!NT_STATUS_IS_OK(status)) {
4044 status = check_name(conn, newname);
4045 if (!NT_STATUS_IS_OK(status)) {
4049 /* Disallow if newname already exists. */
4050 if (VALID_STAT(sbuf2)) {
4051 return NT_STATUS_OBJECT_NAME_COLLISION;
4054 /* No links from a directory. */
4055 if (S_ISDIR(sbuf1.st_mode)) {
4056 return NT_STATUS_FILE_IS_A_DIRECTORY;
4059 /* Ensure this is within the share. */
4060 status = reduce_name(conn, oldname);
4061 if (!NT_STATUS_IS_OK(status)) {
4065 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4067 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4068 status = map_nt_error_from_unix(errno);
4069 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4070 nt_errstr(status), newname, oldname));
4076 /****************************************************************************
4077 Deal with setting the time from any of the setfilepathinfo functions.
4078 ****************************************************************************/
4080 static NTSTATUS smb_set_file_time(connection_struct *conn,
4083 const SMB_STRUCT_STAT *psbuf,
4084 struct timespec ts[2])
4087 FILE_NOTIFY_CHANGE_LAST_ACCESS
4088 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4091 if (!VALID_STAT(*psbuf)) {
4092 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4095 /* get some defaults (no modifications) if any info is zero or -1. */
4096 if (null_timespec(ts[0])) {
4097 ts[0] = get_atimespec(psbuf);
4098 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4101 if (null_timespec(ts[1])) {
4102 ts[1] = get_mtimespec(psbuf);
4103 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4106 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4107 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4110 * Try and set the times of this file if
4111 * they are different from the current values.
4115 struct timespec mts = get_mtimespec(psbuf);
4116 struct timespec ats = get_atimespec(psbuf);
4117 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4118 return NT_STATUS_OK;
4124 * This was a setfileinfo on an open file.
4125 * NT does this a lot. We also need to
4126 * set the time here, as it can be read by
4127 * FindFirst/FindNext and with the patch for bug #2045
4128 * in smbd/fileio.c it ensures that this timestamp is
4129 * kept sticky even after a write. We save the request
4130 * away and will set it on file close and after a write. JRA.
4133 if (!null_timespec(ts[1])) {
4134 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4135 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4136 fsp_set_pending_modtime(fsp, ts[1]);
4140 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4142 if(file_ntimes(conn, fname, ts)!=0) {
4143 return map_nt_error_from_unix(errno);
4146 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4148 return NT_STATUS_OK;
4151 /****************************************************************************
4152 Deal with setting the dosmode from any of the setfilepathinfo functions.
4153 ****************************************************************************/
4155 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4157 SMB_STRUCT_STAT *psbuf,
4160 if (!VALID_STAT(*psbuf)) {
4161 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4165 if (S_ISDIR(psbuf->st_mode)) {
4172 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4174 /* check the mode isn't different, before changing it */
4175 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4177 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4178 fname, (unsigned int)dosmode ));
4180 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4181 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4182 fname, strerror(errno)));
4183 return map_nt_error_from_unix(errno);
4186 return NT_STATUS_OK;
4189 /****************************************************************************
4190 Deal with setting the size from any of the setfilepathinfo functions.
4191 ****************************************************************************/
4193 static NTSTATUS smb_set_file_size(connection_struct *conn,
4196 SMB_STRUCT_STAT *psbuf,
4199 NTSTATUS status = NT_STATUS_OK;
4200 files_struct *new_fsp = NULL;
4202 if (!VALID_STAT(*psbuf)) {
4203 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4206 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4208 if (size == get_file_size(*psbuf)) {
4209 return NT_STATUS_OK;
4212 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4213 fname, (double)size ));
4215 if (fsp && fsp->fh->fd != -1) {
4216 /* Handle based call. */
4217 if (vfs_set_filelen(fsp, size) == -1) {
4218 return map_nt_error_from_unix(errno);
4220 return NT_STATUS_OK;
4223 status = open_file_ntcreate(conn, fname, psbuf,
4225 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4228 FILE_ATTRIBUTE_NORMAL,
4229 FORCE_OPLOCK_BREAK_TO_NONE,
4232 if (!NT_STATUS_IS_OK(status)) {
4233 /* NB. We check for open_was_deferred in the caller. */
4237 if (vfs_set_filelen(new_fsp, size) == -1) {
4238 status = map_nt_error_from_unix(errno);
4239 close_file(new_fsp,NORMAL_CLOSE);
4243 close_file(new_fsp,NORMAL_CLOSE);
4244 return NT_STATUS_OK;
4247 /****************************************************************************
4248 Deal with SMB_INFO_SET_EA.
4249 ****************************************************************************/
4251 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4257 struct ea_list *ea_list = NULL;
4258 TALLOC_CTX *ctx = NULL;
4259 NTSTATUS status = NT_STATUS_OK;
4261 if (total_data < 10) {
4263 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4264 length. They seem to have no effect. Bug #3212. JRA */
4266 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4267 /* We're done. We only get EA info in this call. */
4268 return NT_STATUS_OK;
4271 return NT_STATUS_INVALID_PARAMETER;
4274 if (IVAL(pdata,0) > total_data) {
4275 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4276 IVAL(pdata,0), (unsigned int)total_data));
4277 return NT_STATUS_INVALID_PARAMETER;
4280 ctx = talloc_init("SMB_INFO_SET_EA");
4282 return NT_STATUS_NO_MEMORY;
4284 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4286 talloc_destroy(ctx);
4287 return NT_STATUS_INVALID_PARAMETER;
4289 status = set_ea(conn, fsp, fname, ea_list);
4290 talloc_destroy(ctx);
4295 /****************************************************************************
4296 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4297 ****************************************************************************/
4299 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4304 SMB_STRUCT_STAT *psbuf)
4306 NTSTATUS status = NT_STATUS_OK;
4307 BOOL delete_on_close;
4310 if (total_data < 1) {
4311 return NT_STATUS_INVALID_PARAMETER;
4315 return NT_STATUS_INVALID_HANDLE;
4318 delete_on_close = (CVAL(pdata,0) ? True : False);
4319 dosmode = dos_mode(conn, fname, psbuf);
4321 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4322 "delete_on_close = %u\n",
4324 (unsigned int)dosmode,
4325 (unsigned int)delete_on_close ));
4327 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4329 if (!NT_STATUS_IS_OK(status)) {
4333 /* The set is across all open files on this dev/inode pair. */
4334 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4335 return NT_STATUS_ACCESS_DENIED;
4337 return NT_STATUS_OK;
4340 /****************************************************************************
4341 Deal with SMB_FILE_POSITION_INFORMATION.
4342 ****************************************************************************/
4344 static NTSTATUS smb_file_position_information(connection_struct *conn,
4349 SMB_BIG_UINT position_information;
4351 if (total_data < 8) {
4352 return NT_STATUS_INVALID_PARAMETER;
4356 /* Ignore on pathname based set. */
4357 return NT_STATUS_OK;
4360 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4361 #ifdef LARGE_SMB_OFF_T
4362 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4363 #else /* LARGE_SMB_OFF_T */
4364 if (IVAL(pdata,4) != 0) {
4365 /* more than 32 bits? */
4366 return NT_STATUS_INVALID_PARAMETER;
4368 #endif /* LARGE_SMB_OFF_T */
4370 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4371 fsp->fsp_name, (double)position_information ));
4372 fsp->fh->position_information = position_information;
4373 return NT_STATUS_OK;
4376 /****************************************************************************
4377 Deal with SMB_FILE_MODE_INFORMATION.
4378 ****************************************************************************/
4380 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4386 if (total_data < 4) {
4387 return NT_STATUS_INVALID_PARAMETER;
4389 mode = IVAL(pdata,0);
4390 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4391 return NT_STATUS_INVALID_PARAMETER;
4393 return NT_STATUS_OK;
4396 /****************************************************************************
4397 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4398 ****************************************************************************/
4400 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4406 pstring link_target;
4407 const char *newname = fname;
4408 NTSTATUS status = NT_STATUS_OK;
4410 /* Set a symbolic link. */
4411 /* Don't allow this if follow links is false. */
4413 if (total_data == 0) {
4414 return NT_STATUS_INVALID_PARAMETER;
4417 if (!lp_symlinks(SNUM(conn))) {
4418 return NT_STATUS_ACCESS_DENIED;
4421 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4423 /* !widelinks forces the target path to be within the share. */
4424 /* This means we can interpret the target as a pathname. */
4425 if (!lp_widelinks(SNUM(conn))) {
4427 char *last_dirp = NULL;
4429 if (*link_target == '/') {
4430 /* No absolute paths allowed. */
4431 return NT_STATUS_ACCESS_DENIED;
4433 pstrcpy(rel_name, newname);
4434 last_dirp = strrchr_m(rel_name, '/');
4436 last_dirp[1] = '\0';
4438 pstrcpy(rel_name, "./");
4440 pstrcat(rel_name, link_target);
4442 status = check_name(conn, rel_name);
4443 if (!NT_STATUS_IS_OK(status)) {
4448 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4449 newname, link_target ));
4451 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4452 return map_nt_error_from_unix(errno);
4455 return NT_STATUS_OK;
4458 /****************************************************************************
4459 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4460 ****************************************************************************/
4462 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4470 NTSTATUS status = NT_STATUS_OK;
4472 /* Set a hard link. */
4473 if (total_data == 0) {
4474 return NT_STATUS_INVALID_PARAMETER;
4477 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4478 if (!NT_STATUS_IS_OK(status)) {
4482 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4483 if (!NT_STATUS_IS_OK(status)) {
4487 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4490 return hardlink_internals(conn, oldname, fname);
4493 /****************************************************************************
4494 Deal with SMB_FILE_RENAME_INFORMATION.
4495 ****************************************************************************/
4497 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4506 /* uint32 root_fid; */ /* Not used */
4510 BOOL dest_has_wcard = False;
4511 NTSTATUS status = NT_STATUS_OK;
4514 if (total_data < 13) {
4515 return NT_STATUS_INVALID_PARAMETER;
4518 overwrite = (CVAL(pdata,0) ? True : False);
4519 /* root_fid = IVAL(pdata,4); */
4520 len = IVAL(pdata,8);
4522 if (len > (total_data - 12) || (len == 0)) {
4523 return NT_STATUS_INVALID_PARAMETER;
4526 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4527 if (!NT_STATUS_IS_OK(status)) {
4531 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4532 if (!NT_STATUS_IS_OK(status)) {
4536 /* Check the new name has no '/' characters. */
4537 if (strchr_m(newname, '/')) {
4538 return NT_STATUS_NOT_SUPPORTED;
4541 /* Create the base directory. */
4542 pstrcpy(base_name, fname);
4543 p = strrchr_m(base_name, '/');
4547 /* Append the new name. */
4548 pstrcat(base_name, "/");
4549 pstrcat(base_name, newname);
4552 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4553 fsp->fnum, fsp->fsp_name, base_name ));
4554 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4556 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4558 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4564 /****************************************************************************
4565 Deal with SMB_SET_POSIX_ACL.
4566 ****************************************************************************/
4568 #if defined(HAVE_POSIX_ACLS)
4569 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4574 SMB_STRUCT_STAT *psbuf)
4576 uint16 posix_acl_version;
4577 uint16 num_file_acls;
4578 uint16 num_def_acls;
4579 BOOL valid_file_acls = True;
4580 BOOL valid_def_acls = True;
4582 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4583 return NT_STATUS_INVALID_PARAMETER;
4585 posix_acl_version = SVAL(pdata,0);
4586 num_file_acls = SVAL(pdata,2);
4587 num_def_acls = SVAL(pdata,4);
4589 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4590 valid_file_acls = False;
4594 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4595 valid_def_acls = False;
4599 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4600 return NT_STATUS_INVALID_PARAMETER;
4603 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4604 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4605 return NT_STATUS_INVALID_PARAMETER;
4608 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4609 fname ? fname : fsp->fsp_name,
4610 (unsigned int)num_file_acls,
4611 (unsigned int)num_def_acls));
4613 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4614 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4615 return map_nt_error_from_unix(errno);
4618 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4619 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4620 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4621 return map_nt_error_from_unix(errno);
4623 return NT_STATUS_OK;
4627 /****************************************************************************
4628 Deal with SMB_SET_POSIX_LOCK.
4629 ****************************************************************************/
4631 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4639 SMB_BIG_UINT offset;
4641 BOOL blocking_lock = False;
4642 enum brl_type lock_type;
4643 NTSTATUS status = NT_STATUS_OK;
4645 if (fsp == NULL || fsp->fh->fd == -1) {
4646 return NT_STATUS_INVALID_HANDLE;
4649 if (total_data != POSIX_LOCK_DATA_SIZE) {
4650 return NT_STATUS_INVALID_PARAMETER;
4653 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4654 case POSIX_LOCK_TYPE_READ:
4655 lock_type = READ_LOCK;
4657 case POSIX_LOCK_TYPE_WRITE:
4658 /* Return the right POSIX-mappable error code for files opened read-only. */
4659 if (!fsp->can_write) {
4660 return NT_STATUS_INVALID_HANDLE;
4662 lock_type = WRITE_LOCK;
4664 case POSIX_LOCK_TYPE_UNLOCK:
4665 lock_type = UNLOCK_LOCK;
4668 return NT_STATUS_INVALID_PARAMETER;
4671 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4672 blocking_lock = False;
4673 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4674 blocking_lock = True;
4676 return NT_STATUS_INVALID_PARAMETER;
4679 if (!lp_blocking_locks(SNUM(conn))) {
4680 blocking_lock = False;
4683 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4684 #if defined(HAVE_LONGLONG)
4685 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4686 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4687 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4688 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4689 #else /* HAVE_LONGLONG */
4690 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4691 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4692 #endif /* HAVE_LONGLONG */
4694 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4695 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4697 (unsigned int)lock_type,
4698 (unsigned int)lock_pid,
4702 if (lock_type == UNLOCK_LOCK) {
4703 status = do_unlock(fsp,
4709 struct byte_range_lock *br_lck = do_lock(fsp,
4718 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4720 * A blocking lock was requested. Package up
4721 * this smb into a queued request and push it
4722 * onto the blocking lock queue.
4724 if(push_blocking_lock_request(br_lck,
4727 -1, /* infinite timeout. */
4734 TALLOC_FREE(br_lck);
4738 TALLOC_FREE(br_lck);
4744 /****************************************************************************
4745 Deal with SMB_INFO_STANDARD.
4746 ****************************************************************************/
4748 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4753 const SMB_STRUCT_STAT *psbuf)
4755 struct timespec ts[2];
4757 if (total_data < 12) {
4758 return NT_STATUS_INVALID_PARAMETER;
4762 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4764 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4766 DEBUG(10,("smb_set_info_standard: file %s\n",
4767 fname ? fname : fsp->fsp_name ));
4769 return smb_set_file_time(conn,
4776 /****************************************************************************
4777 Deal with SMB_SET_FILE_BASIC_INFO.
4778 ****************************************************************************/
4780 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4785 SMB_STRUCT_STAT *psbuf)
4787 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4788 struct timespec write_time;
4789 struct timespec changed_time;
4791 struct timespec ts[2];
4792 NTSTATUS status = NT_STATUS_OK;
4794 if (total_data < 36) {
4795 return NT_STATUS_INVALID_PARAMETER;
4798 /* Set the attributes */
4799 dosmode = IVAL(pdata,32);
4800 status = smb_set_file_dosmode(conn,
4804 if (!NT_STATUS_IS_OK(status)) {
4808 /* Ignore create time at offset pdata. */
4811 ts[0] = interpret_long_date(pdata+8);
4813 write_time = interpret_long_date(pdata+16);
4814 changed_time = interpret_long_date(pdata+24);
4817 ts[1] = timespec_min(&write_time, &changed_time);
4819 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4823 /* Prefer a defined time to an undefined one. */
4824 if (null_timespec(ts[1])) {
4825 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4828 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4829 fname ? fname : fsp->fsp_name ));
4831 return smb_set_file_time(conn,
4838 /****************************************************************************
4839 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4840 ****************************************************************************/
4842 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4847 SMB_STRUCT_STAT *psbuf)
4849 SMB_BIG_UINT allocation_size = 0;
4850 NTSTATUS status = NT_STATUS_OK;
4851 files_struct *new_fsp = NULL;
4853 if (!VALID_STAT(*psbuf)) {
4854 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4857 if (total_data < 8) {
4858 return NT_STATUS_INVALID_PARAMETER;
4861 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4862 #ifdef LARGE_SMB_OFF_T
4863 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4864 #else /* LARGE_SMB_OFF_T */
4865 if (IVAL(pdata,4) != 0) {
4866 /* more than 32 bits? */
4867 return NT_STATUS_INVALID_PARAMETER;
4869 #endif /* LARGE_SMB_OFF_T */
4871 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4872 fname, (double)allocation_size ));
4874 if (allocation_size) {
4875 allocation_size = smb_roundup(conn, allocation_size);
4878 if(allocation_size == get_file_size(*psbuf)) {
4879 return NT_STATUS_OK;
4882 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4883 fname, (double)allocation_size ));
4885 if (fsp && fsp->fh->fd != -1) {
4886 /* Open file handle. */
4887 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4888 return map_nt_error_from_unix(errno);
4890 return NT_STATUS_OK;
4893 /* Pathname or stat or directory file. */
4895 status = open_file_ntcreate(conn, fname, psbuf,
4897 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4900 FILE_ATTRIBUTE_NORMAL,
4901 FORCE_OPLOCK_BREAK_TO_NONE,
4904 if (!NT_STATUS_IS_OK(status)) {
4905 /* NB. We check for open_was_deferred in the caller. */
4908 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4909 status = map_nt_error_from_unix(errno);
4910 close_file(new_fsp,NORMAL_CLOSE);
4914 close_file(new_fsp,NORMAL_CLOSE);
4915 return NT_STATUS_OK;
4918 /****************************************************************************
4919 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4920 ****************************************************************************/
4922 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4927 SMB_STRUCT_STAT *psbuf)
4931 if (total_data < 8) {
4932 return NT_STATUS_INVALID_PARAMETER;
4935 size = IVAL(pdata,0);
4936 #ifdef LARGE_SMB_OFF_T
4937 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4938 #else /* LARGE_SMB_OFF_T */
4939 if (IVAL(pdata,4) != 0) {
4940 /* more than 32 bits? */
4941 return NT_STATUS_INVALID_PARAMETER;
4943 #endif /* LARGE_SMB_OFF_T */
4944 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4945 "file %s to %.0f\n", fname, (double)size ));
4947 return smb_set_file_size(conn,
4954 /****************************************************************************
4955 Allow a UNIX info mknod.
4956 ****************************************************************************/
4958 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4962 SMB_STRUCT_STAT *psbuf)
4964 uint32 file_type = IVAL(pdata,56);
4965 #if defined(HAVE_MAKEDEV)
4966 uint32 dev_major = IVAL(pdata,60);
4967 uint32 dev_minor = IVAL(pdata,68);
4969 SMB_DEV_T dev = (SMB_DEV_T)0;
4970 uint32 raw_unixmode = IVAL(pdata,84);
4974 if (total_data < 100) {
4975 return NT_STATUS_INVALID_PARAMETER;
4978 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4979 if (!NT_STATUS_IS_OK(status)) {
4983 #if defined(HAVE_MAKEDEV)
4984 dev = makedev(dev_major, dev_minor);
4987 switch (file_type) {
4988 #if defined(S_IFIFO)
4989 case UNIX_TYPE_FIFO:
4990 unixmode |= S_IFIFO;
4993 #if defined(S_IFSOCK)
4994 case UNIX_TYPE_SOCKET:
4995 unixmode |= S_IFSOCK;
4998 #if defined(S_IFCHR)
4999 case UNIX_TYPE_CHARDEV:
5000 unixmode |= S_IFCHR;
5003 #if defined(S_IFBLK)
5004 case UNIX_TYPE_BLKDEV:
5005 unixmode |= S_IFBLK;
5009 return NT_STATUS_INVALID_PARAMETER;
5012 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5013 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5015 /* Ok - do the mknod. */
5016 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5017 return map_nt_error_from_unix(errno);
5020 /* If any of the other "set" calls fail we
5021 * don't want to end up with a half-constructed mknod.
5024 if (lp_inherit_perms(SNUM(conn))) {
5026 conn, parent_dirname(fname),
5030 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5031 status = map_nt_error_from_unix(errno);
5032 SMB_VFS_UNLINK(conn,fname);
5035 return NT_STATUS_OK;
5038 /****************************************************************************
5039 Deal with SMB_SET_FILE_UNIX_BASIC.
5040 ****************************************************************************/
5042 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5047 SMB_STRUCT_STAT *psbuf)
5049 struct timespec ts[2];
5050 uint32 raw_unixmode;
5053 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5054 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5055 NTSTATUS status = NT_STATUS_OK;
5056 BOOL delete_on_fail = False;
5057 enum perm_type ptype;
5059 if (total_data < 100) {
5060 return NT_STATUS_INVALID_PARAMETER;
5063 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5064 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5065 size=IVAL(pdata,0); /* first 8 Bytes are size */
5066 #ifdef LARGE_SMB_OFF_T
5067 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5068 #else /* LARGE_SMB_OFF_T */
5069 if (IVAL(pdata,4) != 0) {
5070 /* more than 32 bits? */
5071 return NT_STATUS_INVALID_PARAMETER;
5073 #endif /* LARGE_SMB_OFF_T */
5076 ts[0] = interpret_long_date(pdata+24); /* access_time */
5077 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5078 set_owner = (uid_t)IVAL(pdata,40);
5079 set_grp = (gid_t)IVAL(pdata,48);
5080 raw_unixmode = IVAL(pdata,84);
5082 if (VALID_STAT(*psbuf)) {
5083 if (S_ISDIR(psbuf->st_mode)) {
5084 ptype = PERM_EXISTING_DIR;
5086 ptype = PERM_EXISTING_FILE;
5089 ptype = PERM_NEW_FILE;
5092 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5093 if (!NT_STATUS_IS_OK(status)) {
5097 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5098 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5099 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5101 if (!VALID_STAT(*psbuf)) {
5103 * The only valid use of this is to create character and block
5104 * devices, and named pipes. This is deprecated (IMHO) and
5105 * a new info level should be used for mknod. JRA.
5108 status = smb_unix_mknod(conn,
5113 if (!NT_STATUS_IS_OK(status)) {
5117 /* Ensure we don't try and change anything else. */
5118 raw_unixmode = SMB_MODE_NO_CHANGE;
5119 size = get_file_size(*psbuf);
5120 ts[0] = get_atimespec(psbuf);
5121 ts[1] = get_mtimespec(psbuf);
5123 * We continue here as we might want to change the
5126 delete_on_fail = True;
5130 /* Horrible backwards compatibility hack as an old server bug
5131 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5135 size = get_file_size(*psbuf);
5140 * Deal with the UNIX specific mode set.
5143 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5144 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5145 (unsigned int)unixmode, fname ));
5146 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5147 return map_nt_error_from_unix(errno);
5152 * Deal with the UNIX specific uid set.
5155 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5156 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5157 (unsigned int)set_owner, fname ));
5158 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5159 status = map_nt_error_from_unix(errno);
5160 if (delete_on_fail) {
5161 SMB_VFS_UNLINK(conn,fname);
5168 * Deal with the UNIX specific gid set.
5171 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5172 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5173 (unsigned int)set_owner, fname ));
5174 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5175 status = map_nt_error_from_unix(errno);
5176 if (delete_on_fail) {
5177 SMB_VFS_UNLINK(conn,fname);
5183 /* Deal with any size changes. */
5185 status = smb_set_file_size(conn,
5190 if (!NT_STATUS_IS_OK(status)) {
5194 /* Deal with any time changes. */
5196 return smb_set_file_time(conn,
5203 /****************************************************************************
5204 Deal with SMB_SET_FILE_UNIX_INFO2.
5205 ****************************************************************************/
5207 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5212 SMB_STRUCT_STAT *psbuf)
5218 if (total_data < 116) {
5219 return NT_STATUS_INVALID_PARAMETER;
5222 /* Start by setting all the fields that are common between UNIX_BASIC
5225 status = smb_set_file_unix_basic(conn, pdata, total_data,
5227 if (!NT_STATUS_IS_OK(status)) {
5231 smb_fflags = IVAL(pdata, 108);
5232 smb_fmask = IVAL(pdata, 112);
5234 /* NB: We should only attempt to alter the file flags if the client
5235 * sends a non-zero mask.
5237 if (smb_fmask != 0) {
5238 int stat_fflags = 0;
5240 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5242 /* Client asked to alter a flag we don't understand. */
5243 return NT_STATUS_INVALID_PARAMETER;
5246 if (fsp && fsp->fh->fd != -1) {
5247 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5248 return NT_STATUS_NOT_SUPPORTED;
5250 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5251 return map_nt_error_from_unix(errno);
5256 /* XXX: need to add support for changing the create_time here. You
5257 * can do this for paths on Darwin with setattrlist(2). The right way
5258 * to hook this up is probably by extending the VFS utimes interface.
5261 return NT_STATUS_OK;
5264 /****************************************************************************
5265 Create a directory with POSIX semantics.
5266 ****************************************************************************/
5268 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5272 SMB_STRUCT_STAT *psbuf,
5273 int *pdata_return_size)
5275 NTSTATUS status = NT_STATUS_OK;
5276 uint32 raw_unixmode = 0;
5277 uint32 mod_unixmode = 0;
5278 mode_t unixmode = (mode_t)0;
5279 files_struct *fsp = NULL;
5280 uint16 info_level_return = 0;
5282 char *pdata = *ppdata;
5284 if (total_data < 18) {
5285 return NT_STATUS_INVALID_PARAMETER;
5288 raw_unixmode = IVAL(pdata,8);
5289 /* Next 4 bytes are not yet defined. */
5291 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5292 if (!NT_STATUS_IS_OK(status)) {
5296 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5298 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5299 fname, (unsigned int)unixmode ));
5301 status = open_directory(conn,
5304 FILE_READ_ATTRIBUTES, /* Just a stat open */
5305 FILE_SHARE_NONE, /* Ignored for stat opens */
5312 if (NT_STATUS_IS_OK(status)) {
5313 close_file(fsp, NORMAL_CLOSE);
5316 info_level_return = SVAL(pdata,16);
5318 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5319 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5320 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5321 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5323 *pdata_return_size = 12;
5326 /* Realloc the data size */
5327 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5328 if (*ppdata == NULL) {
5329 *pdata_return_size = 0;
5330 return NT_STATUS_NO_MEMORY;
5333 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5334 SSVAL(pdata,2,0); /* No fnum. */
5335 SIVAL(pdata,4,info); /* Was directory created. */
5337 switch (info_level_return) {
5338 case SMB_QUERY_FILE_UNIX_BASIC:
5339 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5340 SSVAL(pdata,10,0); /* Padding. */
5341 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5343 case SMB_QUERY_FILE_UNIX_INFO2:
5344 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5345 SSVAL(pdata,10,0); /* Padding. */
5346 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5349 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5350 SSVAL(pdata,10,0); /* Padding. */
5357 /****************************************************************************
5358 Open/Create a file with POSIX semantics.
5359 ****************************************************************************/
5361 static NTSTATUS smb_posix_open(connection_struct *conn,
5365 SMB_STRUCT_STAT *psbuf,
5366 int *pdata_return_size)
5368 BOOL extended_oplock_granted = False;
5369 char *pdata = *ppdata;
5371 uint32 wire_open_mode = 0;
5372 uint32 raw_unixmode = 0;
5373 uint32 mod_unixmode = 0;
5374 uint32 create_disp = 0;
5375 uint32 access_mask = 0;
5376 uint32 create_options = 0;
5377 NTSTATUS status = NT_STATUS_OK;
5378 mode_t unixmode = (mode_t)0;
5379 files_struct *fsp = NULL;
5380 int oplock_request = 0;
5382 uint16 info_level_return = 0;
5384 if (total_data < 18) {
5385 return NT_STATUS_INVALID_PARAMETER;
5388 flags = IVAL(pdata,0);
5389 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5390 if (oplock_request) {
5391 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5394 wire_open_mode = IVAL(pdata,4);
5396 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5397 return smb_posix_mkdir(conn,
5405 switch (wire_open_mode & SMB_ACCMODE) {
5407 access_mask = FILE_READ_DATA;
5410 access_mask = FILE_WRITE_DATA;
5413 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5416 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5417 (unsigned int)wire_open_mode ));
5418 return NT_STATUS_INVALID_PARAMETER;
5421 wire_open_mode &= ~SMB_ACCMODE;
5423 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5424 create_disp = FILE_CREATE;
5425 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5426 create_disp = FILE_OVERWRITE_IF;
5427 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5428 create_disp = FILE_OPEN_IF;
5430 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5431 (unsigned int)wire_open_mode ));
5432 return NT_STATUS_INVALID_PARAMETER;
5435 raw_unixmode = IVAL(pdata,8);
5436 /* Next 4 bytes are not yet defined. */
5438 status = unix_perms_from_wire(conn,
5441 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5444 if (!NT_STATUS_IS_OK(status)) {
5448 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5450 if (wire_open_mode & SMB_O_SYNC) {
5451 create_options |= FILE_WRITE_THROUGH;
5453 if (wire_open_mode & SMB_O_APPEND) {
5454 access_mask |= FILE_APPEND_DATA;
5456 if (wire_open_mode & SMB_O_DIRECT) {
5457 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5460 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5462 (unsigned int)wire_open_mode,
5463 (unsigned int)unixmode ));
5465 status = open_file_ntcreate(conn,
5469 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5471 0, /* no create options yet. */
5477 if (!NT_STATUS_IS_OK(status)) {
5481 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5482 extended_oplock_granted = True;
5485 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5486 extended_oplock_granted = True;
5489 info_level_return = SVAL(pdata,16);
5491 /* Allocate the correct return size. */
5493 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5494 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5495 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5496 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5498 *pdata_return_size = 12;
5501 /* Realloc the data size */
5502 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5503 if (*ppdata == NULL) {
5504 close_file(fsp,ERROR_CLOSE);
5505 *pdata_return_size = 0;
5506 return NT_STATUS_NO_MEMORY;
5509 if (extended_oplock_granted) {
5510 if (flags & REQUEST_BATCH_OPLOCK) {
5511 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5513 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5515 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5516 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5518 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5521 SSVAL(pdata,2,fsp->fnum);
5522 SIVAL(pdata,4,info); /* Was file created etc. */
5524 switch (info_level_return) {
5525 case SMB_QUERY_FILE_UNIX_BASIC:
5526 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5527 SSVAL(pdata,10,0); /* padding. */
5528 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5530 case SMB_QUERY_FILE_UNIX_INFO2:
5531 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5532 SSVAL(pdata,10,0); /* padding. */
5533 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5536 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5537 SSVAL(pdata,10,0); /* padding. */
5540 return NT_STATUS_OK;
5543 /****************************************************************************
5544 Delete a file with POSIX semantics.
5545 ****************************************************************************/
5547 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5551 SMB_STRUCT_STAT *psbuf)
5553 NTSTATUS status = NT_STATUS_OK;
5554 files_struct *fsp = NULL;
5558 if (total_data < 2) {
5559 return NT_STATUS_INVALID_PARAMETER;
5562 flags = SVAL(pdata,0);
5564 if (!VALID_STAT(*psbuf)) {
5565 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5568 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5569 !VALID_STAT_OF_DIR(*psbuf)) {
5570 return NT_STATUS_NOT_A_DIRECTORY;
5573 DEBUG(10,("smb_posix_unlink: %s %s\n",
5574 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5577 if (VALID_STAT_OF_DIR(*psbuf)) {
5578 status = open_directory(conn,
5582 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5584 FILE_DELETE_ON_CLOSE,
5585 FILE_FLAG_POSIX_SEMANTICS|0777,
5591 status = open_file_ntcreate(conn,
5595 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5598 FILE_FLAG_POSIX_SEMANTICS|0777,
5599 0, /* No oplock, but break existing ones. */
5603 * For file opens we must set the delete on close
5607 if (!NT_STATUS_IS_OK(status)) {
5611 status = smb_set_file_disposition_info(conn,
5619 if (!NT_STATUS_IS_OK(status)) {
5622 return close_file(fsp, NORMAL_CLOSE);
5625 /****************************************************************************
5626 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5627 ****************************************************************************/
5629 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5630 unsigned int tran_call,
5631 char **pparams, int total_params, char **ppdata, int total_data,
5632 unsigned int max_data_bytes)
5634 char *params = *pparams;
5635 char *pdata = *ppdata;
5637 SMB_STRUCT_STAT sbuf;
5639 files_struct *fsp = NULL;
5640 NTSTATUS status = NT_STATUS_OK;
5641 int data_return_size = 0;
5644 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5649 if (tran_call == TRANSACT2_SETFILEINFO) {
5650 if (total_params < 4) {
5651 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5654 fsp = file_fsp(params,0);
5655 info_level = SVAL(params,2);
5657 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5659 * This is actually a SETFILEINFO on a directory
5660 * handle (returned from an NT SMB). NT5.0 seems
5661 * to do this call. JRA.
5663 pstrcpy(fname, fsp->fsp_name);
5664 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5665 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5666 return UNIXERROR(ERRDOS,ERRbadpath);
5668 } else if (fsp && fsp->print_file) {
5670 * Doing a DELETE_ON_CLOSE should cancel a print job.
5672 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5673 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5675 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5678 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5681 return (UNIXERROR(ERRDOS,ERRbadpath));
5684 * Original code - this is an open file.
5686 CHECK_FSP(fsp,conn);
5688 pstrcpy(fname, fsp->fsp_name);
5690 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5691 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5692 return(UNIXERROR(ERRDOS,ERRbadfid));
5697 if (total_params < 7) {
5698 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5701 info_level = SVAL(params,0);
5702 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5703 if (!NT_STATUS_IS_OK(status)) {
5704 return ERROR_NT(status);
5707 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5708 if (!NT_STATUS_IS_OK(status)) {
5709 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5710 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5712 return ERROR_NT(status);
5715 status = unix_convert(conn, fname, False, NULL, &sbuf);
5716 if (!NT_STATUS_IS_OK(status)) {
5717 return ERROR_NT(status);
5720 status = check_name(conn, fname);
5721 if (!NT_STATUS_IS_OK(status)) {
5722 return ERROR_NT(status);
5726 * For CIFS UNIX extensions the target name may not exist.
5729 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5730 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5731 return UNIXERROR(ERRDOS,ERRbadpath);
5735 if (!CAN_WRITE(conn)) {
5736 return ERROR_DOS(ERRSRV,ERRaccess);
5739 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5740 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5743 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5744 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5746 /* Realloc the parameter size */
5747 *pparams = (char *)SMB_REALLOC(*pparams,2);
5748 if (*pparams == NULL) {
5749 return ERROR_NT(NT_STATUS_NO_MEMORY);
5755 if (fsp && !null_timespec(fsp->pending_modtime)) {
5756 /* the pending modtime overrides the current modtime */
5757 set_mtimespec(&sbuf, fsp->pending_modtime);
5760 switch (info_level) {
5762 case SMB_INFO_STANDARD:
5764 status = smb_set_info_standard(conn,
5773 case SMB_INFO_SET_EA:
5775 status = smb_info_set_ea(conn,
5783 case SMB_SET_FILE_BASIC_INFO:
5784 case SMB_FILE_BASIC_INFORMATION:
5786 status = smb_set_file_basic_info(conn,
5795 case SMB_FILE_ALLOCATION_INFORMATION:
5796 case SMB_SET_FILE_ALLOCATION_INFO:
5798 status = smb_set_file_allocation_info(conn,
5807 case SMB_FILE_END_OF_FILE_INFORMATION:
5808 case SMB_SET_FILE_END_OF_FILE_INFO:
5810 status = smb_set_file_end_of_file_info(conn,
5819 case SMB_FILE_DISPOSITION_INFORMATION:
5820 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5823 /* JRA - We used to just ignore this on a path ?
5824 * Shouldn't this be invalid level on a pathname
5827 if (tran_call != TRANSACT2_SETFILEINFO) {
5828 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5831 status = smb_set_file_disposition_info(conn,
5840 case SMB_FILE_POSITION_INFORMATION:
5842 status = smb_file_position_information(conn,
5849 /* From tridge Samba4 :
5850 * MODE_INFORMATION in setfileinfo (I have no
5851 * idea what "mode information" on a file is - it takes a value of 0,
5852 * 2, 4 or 6. What could it be?).
5855 case SMB_FILE_MODE_INFORMATION:
5857 status = smb_file_mode_information(conn,
5864 * CIFS UNIX extensions.
5867 case SMB_SET_FILE_UNIX_BASIC:
5869 status = smb_set_file_unix_basic(conn,
5878 case SMB_SET_FILE_UNIX_INFO2:
5880 status = smb_set_file_unix_info2(conn,
5889 case SMB_SET_FILE_UNIX_LINK:
5891 if (tran_call != TRANSACT2_SETPATHINFO) {
5892 /* We must have a pathname for this. */
5893 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5895 status = smb_set_file_unix_link(conn,
5903 case SMB_SET_FILE_UNIX_HLINK:
5905 if (tran_call != TRANSACT2_SETPATHINFO) {
5906 /* We must have a pathname for this. */
5907 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5909 status = smb_set_file_unix_hlink(conn,
5918 case SMB_FILE_RENAME_INFORMATION:
5920 status = smb_file_rename_information(conn,
5930 #if defined(HAVE_POSIX_ACLS)
5931 case SMB_SET_POSIX_ACL:
5933 status = smb_set_posix_acl(conn,
5943 case SMB_SET_POSIX_LOCK:
5945 if (tran_call != TRANSACT2_SETFILEINFO) {
5946 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5948 status = smb_set_posix_lock(conn,
5957 case SMB_POSIX_PATH_OPEN:
5959 if (tran_call != TRANSACT2_SETPATHINFO) {
5960 /* We must have a pathname for this. */
5961 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5964 status = smb_posix_open(conn,
5973 case SMB_POSIX_PATH_UNLINK:
5975 if (tran_call != TRANSACT2_SETPATHINFO) {
5976 /* We must have a pathname for this. */
5977 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5980 status = smb_posix_unlink(conn,
5989 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5993 if (!NT_STATUS_IS_OK(status)) {
5994 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5995 /* We have re-scheduled this call. */
5998 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5999 /* We have re-scheduled this call. */
6002 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6003 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6005 return ERROR_NT(status);
6009 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6014 /****************************************************************************
6015 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6016 ****************************************************************************/
6018 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6019 char **pparams, int total_params, char **ppdata, int total_data,
6020 unsigned int max_data_bytes)
6022 char *params = *pparams;
6023 char *pdata = *ppdata;
6025 SMB_STRUCT_STAT sbuf;
6026 NTSTATUS status = NT_STATUS_OK;
6027 struct ea_list *ea_list = NULL;
6029 if (!CAN_WRITE(conn))
6030 return ERROR_DOS(ERRSRV,ERRaccess);
6032 if (total_params < 5) {
6033 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6036 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6037 if (!NT_STATUS_IS_OK(status)) {
6038 return ERROR_NT(status);
6041 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6043 status = unix_convert(conn, directory, False, NULL, &sbuf);
6044 if (!NT_STATUS_IS_OK(status)) {
6045 return ERROR_NT(status);
6048 status = check_name(conn, directory);
6049 if (!NT_STATUS_IS_OK(status)) {
6050 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6051 return ERROR_NT(status);
6054 /* Any data in this call is an EA list. */
6055 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6056 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6060 * OS/2 workplace shell seems to send SET_EA requests of "null"
6061 * length (4 bytes containing IVAL 4).
6062 * They seem to have no effect. Bug #3212. JRA.
6065 if (total_data != 4) {
6066 if (total_data < 10) {
6067 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6070 if (IVAL(pdata,0) > total_data) {
6071 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6072 IVAL(pdata,0), (unsigned int)total_data));
6073 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6076 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6079 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6081 } else if (IVAL(pdata,0) != 4) {
6082 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6085 status = create_directory(conn, directory);
6087 if (!NT_STATUS_IS_OK(status)) {
6088 return ERROR_NT(status);
6091 /* Try and set any given EA. */
6093 status = set_ea(conn, NULL, directory, ea_list);
6094 if (!NT_STATUS_IS_OK(status)) {
6095 return ERROR_NT(status);
6099 /* Realloc the parameter and data sizes */
6100 *pparams = (char *)SMB_REALLOC(*pparams,2);
6101 if(*pparams == NULL) {
6102 return ERROR_NT(NT_STATUS_NO_MEMORY);
6108 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6113 /****************************************************************************
6114 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6115 We don't actually do this - we just send a null response.
6116 ****************************************************************************/
6118 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6119 char **pparams, int total_params, char **ppdata, int total_data,
6120 unsigned int max_data_bytes)
6122 static uint16 fnf_handle = 257;
6123 char *params = *pparams;
6126 if (total_params < 6) {
6127 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6130 info_level = SVAL(params,4);
6131 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6133 switch (info_level) {
6138 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6141 /* Realloc the parameter and data sizes */
6142 *pparams = (char *)SMB_REALLOC(*pparams,6);
6143 if (*pparams == NULL) {
6144 return ERROR_NT(NT_STATUS_NO_MEMORY);
6148 SSVAL(params,0,fnf_handle);
6149 SSVAL(params,2,0); /* No changes */
6150 SSVAL(params,4,0); /* No EA errors */
6157 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6162 /****************************************************************************
6163 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6164 changes). Currently this does nothing.
6165 ****************************************************************************/
6167 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6168 char **pparams, int total_params, char **ppdata, int total_data,
6169 unsigned int max_data_bytes)
6171 char *params = *pparams;
6173 DEBUG(3,("call_trans2findnotifynext\n"));
6175 /* Realloc the parameter and data sizes */
6176 *pparams = (char *)SMB_REALLOC(*pparams,4);
6177 if (*pparams == NULL) {
6178 return ERROR_NT(NT_STATUS_NO_MEMORY);
6182 SSVAL(params,0,0); /* No changes */
6183 SSVAL(params,2,0); /* No EA errors */
6185 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6190 /****************************************************************************
6191 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6192 ****************************************************************************/
6194 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6195 char **pparams, int total_params, char **ppdata, int total_data,
6196 unsigned int max_data_bytes)
6198 char *params = *pparams;
6201 int max_referral_level;
6203 DEBUG(10,("call_trans2getdfsreferral\n"));
6205 if (total_params < 3) {
6206 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6209 max_referral_level = SVAL(params,0);
6211 if(!lp_host_msdfs())
6212 return ERROR_DOS(ERRDOS,ERRbadfunc);
6214 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6215 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
6216 return UNIXERROR(ERRDOS,ERRbadfile);
6218 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6219 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6224 #define LMCAT_SPL 0x53
6225 #define LMFUNC_GETJOBID 0x60
6227 /****************************************************************************
6228 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6229 ****************************************************************************/
6231 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6232 char **pparams, int total_params, char **ppdata, int total_data,
6233 unsigned int max_data_bytes)
6235 char *pdata = *ppdata;
6236 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6238 /* check for an invalid fid before proceeding */
6241 return(ERROR_DOS(ERRDOS,ERRbadfid));
6243 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6244 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6245 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6246 if (*ppdata == NULL) {
6247 return ERROR_NT(NT_STATUS_NO_MEMORY);
6251 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6252 CAN ACCEPT THIS IN UNICODE. JRA. */
6254 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6255 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6256 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6257 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6260 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6261 return ERROR_DOS(ERRSRV,ERRerror);
6265 /****************************************************************************
6266 Reply to a SMBfindclose (stop trans2 directory search).
6267 ****************************************************************************/
6269 int reply_findclose(connection_struct *conn,
6270 char *inbuf,char *outbuf,int length,int bufsize)
6273 int dptr_num=SVALS(inbuf,smb_vwv0);
6274 START_PROFILE(SMBfindclose);
6276 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6278 dptr_close(&dptr_num);
6280 outsize = set_message(outbuf,0,0,False);
6282 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6284 END_PROFILE(SMBfindclose);
6288 /****************************************************************************
6289 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6290 ****************************************************************************/
6292 int reply_findnclose(connection_struct *conn,
6293 char *inbuf,char *outbuf,int length,int bufsize)
6297 START_PROFILE(SMBfindnclose);
6299 dptr_num = SVAL(inbuf,smb_vwv0);
6301 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6303 /* We never give out valid handles for a
6304 findnotifyfirst - so any dptr_num is ok here.
6307 outsize = set_message(outbuf,0,0,False);
6309 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6311 END_PROFILE(SMBfindnclose);
6315 int handle_trans2(connection_struct *conn,
6316 struct trans_state *state,
6317 char *inbuf, char *outbuf, int size, int bufsize)
6321 if (Protocol >= PROTOCOL_NT1) {
6322 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6325 /* Now we must call the relevant TRANS2 function */
6326 switch(state->call) {
6327 case TRANSACT2_OPEN:
6329 START_PROFILE(Trans2_open);
6330 outsize = call_trans2open(
6331 conn, inbuf, outbuf, bufsize,
6332 &state->param, state->total_param,
6333 &state->data, state->total_data,
6334 state->max_data_return);
6335 END_PROFILE(Trans2_open);
6339 case TRANSACT2_FINDFIRST:
6341 START_PROFILE(Trans2_findfirst);
6342 outsize = call_trans2findfirst(
6343 conn, inbuf, outbuf, bufsize,
6344 &state->param, state->total_param,
6345 &state->data, state->total_data,
6346 state->max_data_return);
6347 END_PROFILE(Trans2_findfirst);
6351 case TRANSACT2_FINDNEXT:
6353 START_PROFILE(Trans2_findnext);
6354 outsize = call_trans2findnext(
6355 conn, inbuf, outbuf, size, bufsize,
6356 &state->param, state->total_param,
6357 &state->data, state->total_data,
6358 state->max_data_return);
6359 END_PROFILE(Trans2_findnext);
6363 case TRANSACT2_QFSINFO:
6365 START_PROFILE(Trans2_qfsinfo);
6366 outsize = call_trans2qfsinfo(
6367 conn, inbuf, outbuf, size, bufsize,
6368 &state->param, state->total_param,
6369 &state->data, state->total_data,
6370 state->max_data_return);
6371 END_PROFILE(Trans2_qfsinfo);
6375 case TRANSACT2_SETFSINFO:
6377 START_PROFILE(Trans2_setfsinfo);
6378 outsize = call_trans2setfsinfo(
6379 conn, inbuf, outbuf, size, bufsize,
6380 &state->param, state->total_param,
6381 &state->data, state->total_data,
6382 state->max_data_return);
6383 END_PROFILE(Trans2_setfsinfo);
6387 case TRANSACT2_QPATHINFO:
6388 case TRANSACT2_QFILEINFO:
6390 START_PROFILE(Trans2_qpathinfo);
6391 outsize = call_trans2qfilepathinfo(
6392 conn, inbuf, outbuf, size, bufsize, state->call,
6393 &state->param, state->total_param,
6394 &state->data, state->total_data,
6395 state->max_data_return);
6396 END_PROFILE(Trans2_qpathinfo);
6400 case TRANSACT2_SETPATHINFO:
6401 case TRANSACT2_SETFILEINFO:
6403 START_PROFILE(Trans2_setpathinfo);
6404 outsize = call_trans2setfilepathinfo(
6405 conn, inbuf, outbuf, size, bufsize, state->call,
6406 &state->param, state->total_param,
6407 &state->data, state->total_data,
6408 state->max_data_return);
6409 END_PROFILE(Trans2_setpathinfo);
6413 case TRANSACT2_FINDNOTIFYFIRST:
6415 START_PROFILE(Trans2_findnotifyfirst);
6416 outsize = call_trans2findnotifyfirst(
6417 conn, inbuf, outbuf, size, bufsize,
6418 &state->param, state->total_param,
6419 &state->data, state->total_data,
6420 state->max_data_return);
6421 END_PROFILE(Trans2_findnotifyfirst);
6425 case TRANSACT2_FINDNOTIFYNEXT:
6427 START_PROFILE(Trans2_findnotifynext);
6428 outsize = call_trans2findnotifynext(
6429 conn, inbuf, outbuf, size, bufsize,
6430 &state->param, state->total_param,
6431 &state->data, state->total_data,
6432 state->max_data_return);
6433 END_PROFILE(Trans2_findnotifynext);
6437 case TRANSACT2_MKDIR:
6439 START_PROFILE(Trans2_mkdir);
6440 outsize = call_trans2mkdir(
6441 conn, inbuf, outbuf, size, bufsize,
6442 &state->param, state->total_param,
6443 &state->data, state->total_data,
6444 state->max_data_return);
6445 END_PROFILE(Trans2_mkdir);
6449 case TRANSACT2_GET_DFS_REFERRAL:
6451 START_PROFILE(Trans2_get_dfs_referral);
6452 outsize = call_trans2getdfsreferral(
6453 conn, inbuf, outbuf, size, bufsize,
6454 &state->param, state->total_param,
6455 &state->data, state->total_data,
6456 state->max_data_return);
6457 END_PROFILE(Trans2_get_dfs_referral);
6461 case TRANSACT2_IOCTL:
6463 START_PROFILE(Trans2_ioctl);
6464 outsize = call_trans2ioctl(
6465 conn, inbuf, outbuf, size, bufsize,
6466 &state->param, state->total_param,
6467 &state->data, state->total_data,
6468 state->max_data_return);
6469 END_PROFILE(Trans2_ioctl);
6474 /* Error in request */
6475 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6476 outsize = ERROR_DOS(ERRSRV,ERRerror);
6482 /****************************************************************************
6483 Reply to a SMBtrans2.
6484 ****************************************************************************/
6486 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6487 int size, int bufsize)
6490 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6491 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6492 unsigned int psoff = SVAL(inbuf, smb_psoff);
6493 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6494 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6495 struct trans_state *state;
6498 START_PROFILE(SMBtrans2);
6500 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6501 if (!NT_STATUS_IS_OK(result)) {
6502 DEBUG(2, ("Got invalid trans2 request: %s\n",
6503 nt_errstr(result)));
6504 END_PROFILE(SMBtrans2);
6505 return ERROR_NT(result);
6508 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6509 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6510 END_PROFILE(SMBtrans2);
6511 return ERROR_DOS(ERRSRV,ERRaccess);
6514 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6515 DEBUG(0, ("talloc failed\n"));
6516 END_PROFILE(SMBtrans2);
6517 return ERROR_NT(NT_STATUS_NO_MEMORY);
6520 state->cmd = SMBtrans2;
6522 state->mid = SVAL(inbuf, smb_mid);
6523 state->vuid = SVAL(inbuf, smb_uid);
6524 state->setup_count = SVAL(inbuf, smb_suwcnt);
6525 state->setup = NULL;
6526 state->total_param = SVAL(inbuf, smb_tpscnt);
6527 state->param = NULL;
6528 state->total_data = SVAL(inbuf, smb_tdscnt);
6530 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6531 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6532 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6533 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6534 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6536 state->call = tran_call;
6538 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6539 is so as a sanity check */
6540 if (state->setup_count != 1) {
6542 * Need to have rc=0 for ioctl to get job id for OS/2.
6543 * Network printing will fail if function is not successful.
6544 * Similar function in reply.c will be used if protocol
6545 * is LANMAN1.0 instead of LM1.2X002.
6546 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6547 * outbuf doesn't have to be set(only job id is used).
6549 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6550 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6551 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6552 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6554 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6555 DEBUG(2,("Transaction is %d\n",tran_call));
6557 END_PROFILE(SMBtrans2);
6558 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6562 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6565 if (state->total_data) {
6566 /* Can't use talloc here, the core routines do realloc on the
6567 * params and data. */
6568 state->data = (char *)SMB_MALLOC(state->total_data);
6569 if (state->data == NULL) {
6570 DEBUG(0,("reply_trans2: data malloc fail for %u "
6571 "bytes !\n", (unsigned int)state->total_data));
6573 END_PROFILE(SMBtrans2);
6574 return(ERROR_DOS(ERRDOS,ERRnomem));
6576 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6578 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6579 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6582 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6585 if (state->total_param) {
6586 /* Can't use talloc here, the core routines do realloc on the
6587 * params and data. */
6588 state->param = (char *)SMB_MALLOC(state->total_param);
6589 if (state->param == NULL) {
6590 DEBUG(0,("reply_trans: param malloc fail for %u "
6591 "bytes !\n", (unsigned int)state->total_param));
6592 SAFE_FREE(state->data);
6594 END_PROFILE(SMBtrans2);
6595 return(ERROR_DOS(ERRDOS,ERRnomem));
6597 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6599 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6600 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6603 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6606 state->received_data = dscnt;
6607 state->received_param = pscnt;
6609 if ((state->received_param == state->total_param) &&
6610 (state->received_data == state->total_data)) {
6612 outsize = handle_trans2(conn, state, inbuf, outbuf,
6614 SAFE_FREE(state->data);
6615 SAFE_FREE(state->param);
6617 END_PROFILE(SMBtrans2);
6621 DLIST_ADD(conn->pending_trans, state);
6623 /* We need to send an interim response then receive the rest
6624 of the parameter/data bytes */
6625 outsize = set_message(outbuf,0,0,False);
6627 END_PROFILE(SMBtrans2);
6632 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6633 SAFE_FREE(state->data);
6634 SAFE_FREE(state->param);
6636 END_PROFILE(SMBtrans2);
6637 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6641 /****************************************************************************
6642 Reply to a SMBtranss2
6643 ****************************************************************************/
6645 int reply_transs2(connection_struct *conn,
6646 char *inbuf,char *outbuf,int size,int bufsize)
6649 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6650 struct trans_state *state;
6652 START_PROFILE(SMBtranss2);
6656 for (state = conn->pending_trans; state != NULL;
6657 state = state->next) {
6658 if (state->mid == SVAL(inbuf,smb_mid)) {
6663 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6664 END_PROFILE(SMBtranss2);
6665 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6668 /* Revise state->total_param and state->total_data in case they have
6669 changed downwards */
6671 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6672 state->total_param = SVAL(inbuf, smb_tpscnt);
6673 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6674 state->total_data = SVAL(inbuf, smb_tdscnt);
6676 pcnt = SVAL(inbuf, smb_spscnt);
6677 poff = SVAL(inbuf, smb_spsoff);
6678 pdisp = SVAL(inbuf, smb_spsdisp);
6680 dcnt = SVAL(inbuf, smb_sdscnt);
6681 doff = SVAL(inbuf, smb_sdsoff);
6682 ddisp = SVAL(inbuf, smb_sdsdisp);
6684 state->received_param += pcnt;
6685 state->received_data += dcnt;
6687 if ((state->received_data > state->total_data) ||
6688 (state->received_param > state->total_param))
6692 if (pdisp+pcnt > state->total_param)
6694 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6696 if (pdisp > state->total_param)
6698 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6699 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6701 if (state->param + pdisp < state->param)
6704 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6709 if (ddisp+dcnt > state->total_data)
6711 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6713 if (ddisp > state->total_data)
6715 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6716 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6718 if (state->data + ddisp < state->data)
6721 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6725 if ((state->received_param < state->total_param) ||
6726 (state->received_data < state->total_data)) {
6727 END_PROFILE(SMBtranss2);
6731 /* construct_reply_common has done us the favor to pre-fill the
6732 * command field with SMBtranss2 which is wrong :-)
6734 SCVAL(outbuf,smb_com,SMBtrans2);
6736 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6738 DLIST_REMOVE(conn->pending_trans, state);
6739 SAFE_FREE(state->data);
6740 SAFE_FREE(state->param);
6744 END_PROFILE(SMBtranss2);
6745 return(ERROR_DOS(ERRSRV,ERRnosupport));
6748 END_PROFILE(SMBtranss2);
6753 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6754 DLIST_REMOVE(conn->pending_trans, state);
6755 SAFE_FREE(state->data);
6756 SAFE_FREE(state->param);
6758 END_PROFILE(SMBtranss2);
6759 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);