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) {
1206 /* Needed to show the msdfs symlinks as
1209 if(lp_host_msdfs() &&
1210 lp_msdfs_root(SNUM(conn)) &&
1211 ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1213 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1214 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1218 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1219 pathreal,strerror(errno)));
1225 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1227 mode = dos_mode(conn,pathreal,&sbuf);
1230 if (!dir_check_ftype(conn,mode,dirtype)) {
1231 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1236 file_size = get_file_size(sbuf);
1237 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1239 mdate_ts = get_mtimespec(&sbuf);
1240 adate_ts = get_atimespec(&sbuf);
1241 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1243 if (lp_dos_filetime_resolution(SNUM(conn))) {
1244 dos_filetime_timespec(&create_date_ts);
1245 dos_filetime_timespec(&mdate_ts);
1246 dos_filetime_timespec(&adate_ts);
1249 create_date = convert_timespec_to_time_t(create_date_ts);
1250 mdate = convert_timespec_to_time_t(mdate_ts);
1251 adate = convert_timespec_to_time_t(adate_ts);
1253 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1257 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1261 mangle_map(fname,False,True,conn->params);
1266 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1268 switch (info_level) {
1269 case SMB_FIND_INFO_STANDARD:
1270 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1271 if(requires_resume_key) {
1275 srv_put_dos_date2(p,0,create_date);
1276 srv_put_dos_date2(p,4,adate);
1277 srv_put_dos_date2(p,8,mdate);
1278 SIVAL(p,12,(uint32)file_size);
1279 SIVAL(p,16,(uint32)allocation_size);
1283 p += align_string(outbuf, p, 0);
1284 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1285 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1287 SCVAL(nameptr, -1, len - 2);
1289 SCVAL(nameptr, -1, 0);
1293 SCVAL(nameptr, -1, len - 1);
1295 SCVAL(nameptr, -1, 0);
1301 case SMB_FIND_EA_SIZE:
1302 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1303 if(requires_resume_key) {
1307 srv_put_dos_date2(p,0,create_date);
1308 srv_put_dos_date2(p,4,adate);
1309 srv_put_dos_date2(p,8,mdate);
1310 SIVAL(p,12,(uint32)file_size);
1311 SIVAL(p,16,(uint32)allocation_size);
1314 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1315 SIVAL(p,22,ea_size); /* Extended attributes */
1319 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1320 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1333 SCVAL(nameptr,0,len);
1335 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1338 case SMB_FIND_EA_LIST:
1340 struct ea_list *file_list = NULL;
1343 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1347 if(requires_resume_key) {
1351 srv_put_dos_date2(p,0,create_date);
1352 srv_put_dos_date2(p,4,adate);
1353 srv_put_dos_date2(p,8,mdate);
1354 SIVAL(p,12,(uint32)file_size);
1355 SIVAL(p,16,(uint32)allocation_size);
1357 p += 22; /* p now points to the EA area. */
1359 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1360 name_list = ea_list_union(name_list, file_list, &ea_len);
1362 /* We need to determine if this entry will fit in the space available. */
1363 /* Max string size is 255 bytes. */
1364 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1365 /* Move the dirptr back to prev_dirpos */
1366 dptr_SeekDir(conn->dirptr, prev_dirpos);
1367 *out_of_space = True;
1368 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1369 return False; /* Not finished - just out of space */
1372 /* Push the ea_data followed by the name. */
1373 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1375 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1376 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1389 SCVAL(nameptr,0,len);
1391 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1395 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1396 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1397 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1399 SIVAL(p,0,reskey); p += 4;
1400 put_long_date_timespec(p,create_date_ts); p += 8;
1401 put_long_date_timespec(p,adate_ts); p += 8;
1402 put_long_date_timespec(p,mdate_ts); p += 8;
1403 put_long_date_timespec(p,mdate_ts); p += 8;
1404 SOFF_T(p,0,file_size); p += 8;
1405 SOFF_T(p,0,allocation_size); p += 8;
1406 SIVAL(p,0,nt_extmode); p += 4;
1407 q = p; p += 4; /* q is placeholder for name length. */
1409 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1410 SIVAL(p,0,ea_size); /* Extended attributes */
1413 /* Clear the short name buffer. This is
1414 * IMPORTANT as not doing so will trigger
1415 * a Win2k client bug. JRA.
1417 if (!was_8_3 && check_mangled_names) {
1418 pstring mangled_name;
1419 pstrcpy(mangled_name, fname);
1420 mangle_map(mangled_name,True,True,
1422 mangled_name[12] = 0;
1423 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1425 memset(p + 2 + len,'\0',24 - len);
1432 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1435 SIVAL(p,0,0); /* Ensure any padding is null. */
1436 len = PTR_DIFF(p, pdata);
1437 len = (len + 3) & ~3;
1442 case SMB_FIND_FILE_DIRECTORY_INFO:
1443 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1445 SIVAL(p,0,reskey); p += 4;
1446 put_long_date_timespec(p,create_date_ts); p += 8;
1447 put_long_date_timespec(p,adate_ts); p += 8;
1448 put_long_date_timespec(p,mdate_ts); p += 8;
1449 put_long_date_timespec(p,mdate_ts); p += 8;
1450 SOFF_T(p,0,file_size); p += 8;
1451 SOFF_T(p,0,allocation_size); p += 8;
1452 SIVAL(p,0,nt_extmode); p += 4;
1453 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1456 SIVAL(p,0,0); /* Ensure any padding is null. */
1457 len = PTR_DIFF(p, pdata);
1458 len = (len + 3) & ~3;
1463 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1464 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1466 SIVAL(p,0,reskey); p += 4;
1467 put_long_date_timespec(p,create_date_ts); p += 8;
1468 put_long_date_timespec(p,adate_ts); p += 8;
1469 put_long_date_timespec(p,mdate_ts); p += 8;
1470 put_long_date_timespec(p,mdate_ts); p += 8;
1471 SOFF_T(p,0,file_size); p += 8;
1472 SOFF_T(p,0,allocation_size); p += 8;
1473 SIVAL(p,0,nt_extmode); p += 4;
1474 q = p; p += 4; /* q is placeholder for name length. */
1476 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1477 SIVAL(p,0,ea_size); /* Extended attributes */
1480 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1484 SIVAL(p,0,0); /* Ensure any padding is null. */
1485 len = PTR_DIFF(p, pdata);
1486 len = (len + 3) & ~3;
1491 case SMB_FIND_FILE_NAMES_INFO:
1492 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1494 SIVAL(p,0,reskey); p += 4;
1496 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1497 acl on a dir (tridge) */
1498 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1501 SIVAL(p,0,0); /* Ensure any padding is null. */
1502 len = PTR_DIFF(p, pdata);
1503 len = (len + 3) & ~3;
1508 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1509 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1511 SIVAL(p,0,reskey); p += 4;
1512 put_long_date_timespec(p,create_date_ts); p += 8;
1513 put_long_date_timespec(p,adate_ts); p += 8;
1514 put_long_date_timespec(p,mdate_ts); p += 8;
1515 put_long_date_timespec(p,mdate_ts); p += 8;
1516 SOFF_T(p,0,file_size); p += 8;
1517 SOFF_T(p,0,allocation_size); p += 8;
1518 SIVAL(p,0,nt_extmode); p += 4;
1519 q = p; p += 4; /* q is placeholder for name length. */
1521 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1522 SIVAL(p,0,ea_size); /* Extended attributes */
1525 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1526 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1527 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1528 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1531 SIVAL(p,0,0); /* Ensure any padding is null. */
1532 len = PTR_DIFF(p, pdata);
1533 len = (len + 3) & ~3;
1538 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1539 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1540 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1542 SIVAL(p,0,reskey); p += 4;
1543 put_long_date_timespec(p,create_date_ts); p += 8;
1544 put_long_date_timespec(p,adate_ts); p += 8;
1545 put_long_date_timespec(p,mdate_ts); p += 8;
1546 put_long_date_timespec(p,mdate_ts); p += 8;
1547 SOFF_T(p,0,file_size); p += 8;
1548 SOFF_T(p,0,allocation_size); p += 8;
1549 SIVAL(p,0,nt_extmode); p += 4;
1550 q = p; p += 4; /* q is placeholder for name length */
1552 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1553 SIVAL(p,0,ea_size); /* Extended attributes */
1556 /* Clear the short name buffer. This is
1557 * IMPORTANT as not doing so will trigger
1558 * a Win2k client bug. JRA.
1560 if (!was_8_3 && check_mangled_names) {
1561 pstring mangled_name;
1562 pstrcpy(mangled_name, fname);
1563 mangle_map(mangled_name,True,True,
1565 mangled_name[12] = 0;
1566 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1569 memset(p + 2 + len,'\0',24 - len);
1576 SSVAL(p,0,0); p += 2; /* Reserved ? */
1577 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1578 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1579 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1582 SIVAL(p,0,0); /* Ensure any padding is null. */
1583 len = PTR_DIFF(p, pdata);
1584 len = (len + 3) & ~3;
1589 /* CIFS UNIX Extension. */
1591 case SMB_FIND_FILE_UNIX:
1592 case SMB_FIND_FILE_UNIX_INFO2:
1594 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1596 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1598 if (info_level == SMB_FIND_FILE_UNIX) {
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1600 p = store_file_unix_basic(conn, p,
1603 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1604 p = store_file_unix_basic_info2(conn, p,
1608 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1610 SIVAL(p,0,0); /* Ensure any padding is null. */
1612 len = PTR_DIFF(p, pdata);
1613 len = (len + 3) & ~3;
1614 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1616 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1625 if (PTR_DIFF(p,pdata) > space_remaining) {
1626 /* Move the dirptr back to prev_dirpos */
1627 dptr_SeekDir(conn->dirptr, prev_dirpos);
1628 *out_of_space = True;
1629 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1630 return False; /* Not finished - just out of space */
1633 /* Setup the last entry pointer, as an offset from base_data */
1634 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1635 /* Advance the data pointer to the next slot */
1641 /****************************************************************************
1642 Reply to a TRANS2_FINDFIRST.
1643 ****************************************************************************/
1645 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1646 char **pparams, int total_params, char **ppdata, int total_data,
1647 unsigned int max_data_bytes)
1649 /* We must be careful here that we don't return more than the
1650 allowed number of data bytes. If this means returning fewer than
1651 maxentries then so be it. We assume that the redirector has
1652 enough room for the fixed number of parameter bytes it has
1654 char *params = *pparams;
1655 char *pdata = *ppdata;
1658 uint16 findfirst_flags;
1659 BOOL close_after_first;
1661 BOOL requires_resume_key;
1666 int last_entry_off=0;
1670 BOOL finished = False;
1671 BOOL dont_descend = False;
1672 BOOL out_of_space = False;
1673 int space_remaining;
1674 BOOL mask_contains_wcard = False;
1675 SMB_STRUCT_STAT sbuf;
1676 TALLOC_CTX *ea_ctx = NULL;
1677 struct ea_list *ea_list = NULL;
1678 NTSTATUS ntstatus = NT_STATUS_OK;
1680 if (total_params < 13) {
1681 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1684 dirtype = SVAL(params,0);
1685 maxentries = SVAL(params,2);
1686 findfirst_flags = SVAL(params,4);
1687 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1688 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1689 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1690 info_level = SVAL(params,6);
1692 *directory = *mask = 0;
1694 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1695 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1696 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1697 info_level, max_data_bytes));
1700 /* W2K3 seems to treat zero as 1. */
1704 switch (info_level) {
1705 case SMB_FIND_INFO_STANDARD:
1706 case SMB_FIND_EA_SIZE:
1707 case SMB_FIND_EA_LIST:
1708 case SMB_FIND_FILE_DIRECTORY_INFO:
1709 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1710 case SMB_FIND_FILE_NAMES_INFO:
1711 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1712 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1713 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1715 case SMB_FIND_FILE_UNIX:
1716 case SMB_FIND_FILE_UNIX_INFO2:
1717 if (!lp_unix_extensions()) {
1718 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1722 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1725 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1726 if (!NT_STATUS_IS_OK(ntstatus)) {
1727 return ERROR_NT(ntstatus);
1730 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) {
1731 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1734 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1735 if (!NT_STATUS_IS_OK(ntstatus)) {
1736 return ERROR_NT(ntstatus);
1738 ntstatus = check_name(conn, directory);
1739 if (!NT_STATUS_IS_OK(ntstatus)) {
1740 return ERROR_NT(ntstatus);
1743 p = strrchr_m(directory,'/');
1745 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1746 if((directory[0] == '.') && (directory[1] == '\0')) {
1748 mask_contains_wcard = True;
1750 pstrcpy(mask,directory);
1752 pstrcpy(directory,"./");
1758 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1760 if (info_level == SMB_FIND_EA_LIST) {
1763 if (total_data < 4) {
1764 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1767 ea_size = IVAL(pdata,0);
1768 if (ea_size != total_data) {
1769 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1770 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1771 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1774 if (!lp_ea_support(SNUM(conn))) {
1775 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1778 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1779 return ERROR_NT(NT_STATUS_NO_MEMORY);
1782 /* Pull out the list of names. */
1783 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1785 talloc_destroy(ea_ctx);
1786 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1790 *ppdata = (char *)SMB_REALLOC(
1791 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1792 if(*ppdata == NULL ) {
1793 talloc_destroy(ea_ctx);
1794 return ERROR_NT(NT_STATUS_NO_MEMORY);
1798 /* Realloc the params space */
1799 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1800 if (*pparams == NULL) {
1801 talloc_destroy(ea_ctx);
1802 return ERROR_NT(NT_STATUS_NO_MEMORY);
1806 /* Save the wildcard match and attribs we are using on this directory -
1807 needed as lanman2 assumes these are being saved between calls */
1809 ntstatus = dptr_create(conn,
1813 SVAL(inbuf,smb_pid),
1815 mask_contains_wcard,
1819 if (!NT_STATUS_IS_OK(ntstatus)) {
1820 talloc_destroy(ea_ctx);
1821 return ERROR_NT(ntstatus);
1824 dptr_num = dptr_dnum(conn->dirptr);
1825 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1827 /* We don't need to check for VOL here as this is returned by
1828 a different TRANS2 call. */
1830 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1831 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1832 dont_descend = True;
1835 space_remaining = max_data_bytes;
1836 out_of_space = False;
1838 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1839 BOOL got_exact_match = False;
1841 /* this is a heuristic to avoid seeking the dirptr except when
1842 absolutely necessary. It allows for a filename of about 40 chars */
1843 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1844 out_of_space = True;
1847 finished = !get_lanman2_dir_entry(conn,
1849 mask,dirtype,info_level,
1850 requires_resume_key,dont_descend,
1851 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1852 &last_entry_off, ea_list, ea_ctx);
1855 if (finished && out_of_space)
1858 if (!finished && !out_of_space)
1862 * As an optimisation if we know we aren't looking
1863 * for a wildcard name (ie. the name matches the wildcard exactly)
1864 * then we can finish on any (first) match.
1865 * This speeds up large directory searches. JRA.
1871 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1874 talloc_destroy(ea_ctx);
1876 /* Check if we can close the dirptr */
1877 if(close_after_first || (finished && close_if_end)) {
1878 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1879 dptr_close(&dptr_num);
1883 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1884 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1885 * the protocol level is less than NT1. Tested with smbclient. JRA.
1886 * This should fix the OS/2 client bug #2335.
1889 if(numentries == 0) {
1890 dptr_close(&dptr_num);
1891 if (Protocol < PROTOCOL_NT1) {
1892 return ERROR_DOS(ERRDOS,ERRnofiles);
1894 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1898 /* At this point pdata points to numentries directory entries. */
1900 /* Set up the return parameter block */
1901 SSVAL(params,0,dptr_num);
1902 SSVAL(params,2,numentries);
1903 SSVAL(params,4,finished);
1904 SSVAL(params,6,0); /* Never an EA error */
1905 SSVAL(params,8,last_entry_off);
1907 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1909 if ((! *directory) && dptr_path(dptr_num))
1910 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1912 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1913 smb_fn_name(CVAL(inbuf,smb_com)),
1914 mask, directory, dirtype, numentries ) );
1917 * Force a name mangle here to ensure that the
1918 * mask as an 8.3 name is top of the mangled cache.
1919 * The reasons for this are subtle. Don't remove
1920 * this code unless you know what you are doing
1921 * (see PR#13758). JRA.
1924 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1925 mangle_map(mask, True, True, conn->params);
1930 /****************************************************************************
1931 Reply to a TRANS2_FINDNEXT.
1932 ****************************************************************************/
1934 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1935 char **pparams, int total_params, char **ppdata, int total_data,
1936 unsigned int max_data_bytes)
1938 /* We must be careful here that we don't return more than the
1939 allowed number of data bytes. If this means returning fewer than
1940 maxentries then so be it. We assume that the redirector has
1941 enough room for the fixed number of parameter bytes it has
1943 char *params = *pparams;
1944 char *pdata = *ppdata;
1949 uint16 findnext_flags;
1950 BOOL close_after_request;
1952 BOOL requires_resume_key;
1954 BOOL mask_contains_wcard = False;
1955 pstring resume_name;
1961 int i, last_entry_off=0;
1962 BOOL finished = False;
1963 BOOL dont_descend = False;
1964 BOOL out_of_space = False;
1965 int space_remaining;
1966 TALLOC_CTX *ea_ctx = NULL;
1967 struct ea_list *ea_list = NULL;
1968 NTSTATUS ntstatus = NT_STATUS_OK;
1970 if (total_params < 13) {
1971 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1974 dptr_num = SVAL(params,0);
1975 maxentries = SVAL(params,2);
1976 info_level = SVAL(params,4);
1977 resume_key = IVAL(params,6);
1978 findnext_flags = SVAL(params,10);
1979 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1980 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1981 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1982 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1984 *mask = *directory = *resume_name = 0;
1986 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1987 if (!NT_STATUS_IS_OK(ntstatus)) {
1988 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1989 complain (it thinks we're asking for the directory above the shared
1990 path or an invalid name). Catch this as the resume name is only compared, never used in
1991 a file access. JRA. */
1992 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1993 pstrcpy(resume_name, "..");
1994 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1995 pstrcpy(resume_name, ".");
1997 return ERROR_NT(ntstatus);
2001 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2002 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2003 resume_key = %d resume name = %s continue=%d level = %d\n",
2004 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2005 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2008 /* W2K3 seems to treat zero as 1. */
2012 switch (info_level) {
2013 case SMB_FIND_INFO_STANDARD:
2014 case SMB_FIND_EA_SIZE:
2015 case SMB_FIND_EA_LIST:
2016 case SMB_FIND_FILE_DIRECTORY_INFO:
2017 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2018 case SMB_FIND_FILE_NAMES_INFO:
2019 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2020 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2021 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2023 case SMB_FIND_FILE_UNIX:
2024 case SMB_FIND_FILE_UNIX_INFO2:
2025 if (!lp_unix_extensions()) {
2026 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2030 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2033 if (info_level == SMB_FIND_EA_LIST) {
2036 if (total_data < 4) {
2037 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2040 ea_size = IVAL(pdata,0);
2041 if (ea_size != total_data) {
2042 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2043 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2044 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2047 if (!lp_ea_support(SNUM(conn))) {
2048 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2051 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2052 return ERROR_NT(NT_STATUS_NO_MEMORY);
2055 /* Pull out the list of names. */
2056 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2058 talloc_destroy(ea_ctx);
2059 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2063 *ppdata = (char *)SMB_REALLOC(
2064 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2065 if(*ppdata == NULL) {
2066 talloc_destroy(ea_ctx);
2067 return ERROR_NT(NT_STATUS_NO_MEMORY);
2072 /* Realloc the params space */
2073 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2074 if(*pparams == NULL ) {
2075 talloc_destroy(ea_ctx);
2076 return ERROR_NT(NT_STATUS_NO_MEMORY);
2081 /* Check that the dptr is valid */
2082 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2083 talloc_destroy(ea_ctx);
2084 return ERROR_DOS(ERRDOS,ERRnofiles);
2087 string_set(&conn->dirpath,dptr_path(dptr_num));
2089 /* Get the wildcard mask from the dptr */
2090 if((p = dptr_wcard(dptr_num))== NULL) {
2091 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2092 talloc_destroy(ea_ctx);
2093 return ERROR_DOS(ERRDOS,ERRnofiles);
2097 pstrcpy(directory,conn->dirpath);
2099 /* Get the attr mask from the dptr */
2100 dirtype = dptr_attr(dptr_num);
2102 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2103 dptr_num, mask, dirtype,
2105 dptr_TellDir(conn->dirptr)));
2107 /* We don't need to check for VOL here as this is returned by
2108 a different TRANS2 call. */
2110 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2111 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2112 dont_descend = True;
2115 space_remaining = max_data_bytes;
2116 out_of_space = False;
2119 * Seek to the correct position. We no longer use the resume key but
2120 * depend on the last file name instead.
2123 if(*resume_name && !continue_bit) {
2126 long current_pos = 0;
2128 * Remember, mangle_map is called by
2129 * get_lanman2_dir_entry(), so the resume name
2130 * could be mangled. Ensure we check the unmangled name.
2133 if (mangle_is_mangled(resume_name, conn->params)) {
2134 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2139 * Fix for NT redirector problem triggered by resume key indexes
2140 * changing between directory scans. We now return a resume key of 0
2141 * and instead look for the filename to continue from (also given
2142 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2143 * findfirst/findnext (as is usual) then the directory pointer
2144 * should already be at the correct place.
2147 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2148 } /* end if resume_name && !continue_bit */
2150 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2151 BOOL got_exact_match = False;
2153 /* this is a heuristic to avoid seeking the dirptr except when
2154 absolutely necessary. It allows for a filename of about 40 chars */
2155 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2156 out_of_space = True;
2159 finished = !get_lanman2_dir_entry(conn,
2161 mask,dirtype,info_level,
2162 requires_resume_key,dont_descend,
2163 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2164 &last_entry_off, ea_list, ea_ctx);
2167 if (finished && out_of_space)
2170 if (!finished && !out_of_space)
2174 * As an optimisation if we know we aren't looking
2175 * for a wildcard name (ie. the name matches the wildcard exactly)
2176 * then we can finish on any (first) match.
2177 * This speeds up large directory searches. JRA.
2183 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2186 talloc_destroy(ea_ctx);
2188 /* Check if we can close the dirptr */
2189 if(close_after_request || (finished && close_if_end)) {
2190 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2191 dptr_close(&dptr_num); /* This frees up the saved mask */
2194 /* Set up the return parameter block */
2195 SSVAL(params,0,numentries);
2196 SSVAL(params,2,finished);
2197 SSVAL(params,4,0); /* Never an EA error */
2198 SSVAL(params,6,last_entry_off);
2200 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2202 if ((! *directory) && dptr_path(dptr_num))
2203 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2205 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2206 smb_fn_name(CVAL(inbuf,smb_com)),
2207 mask, directory, dirtype, numentries ) );
2212 /****************************************************************************
2213 Reply to a TRANS2_QFSINFO (query filesystem info).
2214 ****************************************************************************/
2216 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2217 char **pparams, int total_params, char **ppdata, int total_data,
2218 unsigned int max_data_bytes)
2221 char *params = *pparams;
2225 char *vname = volume_label(SNUM(conn));
2226 int snum = SNUM(conn);
2227 char *fstype = lp_fstype(SNUM(conn));
2230 if (total_params < 2) {
2231 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2234 info_level = SVAL(params,0);
2236 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2238 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2239 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2240 return ERROR_DOS(ERRSRV,ERRinvdevice);
2243 *ppdata = (char *)SMB_REALLOC(
2244 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2245 if (*ppdata == NULL ) {
2246 return ERROR_NT(NT_STATUS_NO_MEMORY);
2250 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2252 switch (info_level) {
2253 case SMB_INFO_ALLOCATION:
2255 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2257 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2258 return(UNIXERROR(ERRHRD,ERRgeneral));
2261 block_size = lp_block_size(snum);
2262 if (bsize < block_size) {
2263 SMB_BIG_UINT factor = block_size/bsize;
2268 if (bsize > block_size) {
2269 SMB_BIG_UINT factor = bsize/block_size;
2274 bytes_per_sector = 512;
2275 sectors_per_unit = bsize/bytes_per_sector;
2277 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2278 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2279 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2281 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2282 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2283 SIVAL(pdata,l1_cUnit,dsize);
2284 SIVAL(pdata,l1_cUnitAvail,dfree);
2285 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2289 case SMB_INFO_VOLUME:
2290 /* Return volume name */
2292 * Add volume serial number - hash of a combination of
2293 * the called hostname and the service name.
2295 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2297 * Win2k3 and previous mess this up by sending a name length
2298 * one byte short. I believe only older clients (OS/2 Win9x) use
2299 * this call so try fixing this by adding a terminating null to
2300 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2302 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2303 SCVAL(pdata,l2_vol_cch,len);
2304 data_len = l2_vol_szVolLabel + len;
2305 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2306 (unsigned)st.st_ctime, len, vname));
2309 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2310 case SMB_FS_ATTRIBUTE_INFORMATION:
2313 #if defined(HAVE_SYS_QUOTAS)
2314 quota_flag = FILE_VOLUME_QUOTAS;
2317 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2318 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2319 quota_flag); /* FS ATTRIBUTES */
2321 SIVAL(pdata,4,255); /* Max filename component length */
2322 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2323 and will think we can't do long filenames */
2324 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2326 data_len = 12 + len;
2329 case SMB_QUERY_FS_LABEL_INFO:
2330 case SMB_FS_LABEL_INFORMATION:
2331 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2336 case SMB_QUERY_FS_VOLUME_INFO:
2337 case SMB_FS_VOLUME_INFORMATION:
2340 * Add volume serial number - hash of a combination of
2341 * the called hostname and the service name.
2343 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2344 (str_checksum(get_local_machine_name())<<16));
2346 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2347 SIVAL(pdata,12,len);
2349 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2350 (int)strlen(vname),vname, lp_servicename(snum)));
2353 case SMB_QUERY_FS_SIZE_INFO:
2354 case SMB_FS_SIZE_INFORMATION:
2356 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2358 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2359 return(UNIXERROR(ERRHRD,ERRgeneral));
2361 block_size = lp_block_size(snum);
2362 if (bsize < block_size) {
2363 SMB_BIG_UINT factor = block_size/bsize;
2368 if (bsize > block_size) {
2369 SMB_BIG_UINT factor = bsize/block_size;
2374 bytes_per_sector = 512;
2375 sectors_per_unit = bsize/bytes_per_sector;
2376 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2377 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2378 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2379 SBIG_UINT(pdata,0,dsize);
2380 SBIG_UINT(pdata,8,dfree);
2381 SIVAL(pdata,16,sectors_per_unit);
2382 SIVAL(pdata,20,bytes_per_sector);
2386 case SMB_FS_FULL_SIZE_INFORMATION:
2388 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2390 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2391 return(UNIXERROR(ERRHRD,ERRgeneral));
2393 block_size = lp_block_size(snum);
2394 if (bsize < block_size) {
2395 SMB_BIG_UINT factor = block_size/bsize;
2400 if (bsize > block_size) {
2401 SMB_BIG_UINT factor = bsize/block_size;
2406 bytes_per_sector = 512;
2407 sectors_per_unit = bsize/bytes_per_sector;
2408 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2409 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2410 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2411 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2412 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2413 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2414 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2415 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2419 case SMB_QUERY_FS_DEVICE_INFO:
2420 case SMB_FS_DEVICE_INFORMATION:
2422 SIVAL(pdata,0,0); /* dev type */
2423 SIVAL(pdata,4,0); /* characteristics */
2426 #ifdef HAVE_SYS_QUOTAS
2427 case SMB_FS_QUOTA_INFORMATION:
2429 * what we have to send --metze:
2431 * Unknown1: 24 NULL bytes
2432 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2433 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2434 * Quota Flags: 2 byte :
2435 * Unknown3: 6 NULL bytes
2439 * details for Quota Flags:
2441 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2442 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2443 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2444 * 0x0001 Enable Quotas: enable quota for this fs
2448 /* we need to fake up a fsp here,
2449 * because its not send in this call
2452 SMB_NTQUOTA_STRUCT quotas;
2455 ZERO_STRUCT(quotas);
2461 if (current_user.ut.uid != 0) {
2462 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2463 lp_servicename(SNUM(conn)),conn->user));
2464 return ERROR_DOS(ERRDOS,ERRnoaccess);
2467 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2468 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2469 return ERROR_DOS(ERRSRV,ERRerror);
2474 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2476 /* Unknown1 24 NULL bytes*/
2477 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2478 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2479 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2481 /* Default Soft Quota 8 bytes */
2482 SBIG_UINT(pdata,24,quotas.softlim);
2484 /* Default Hard Quota 8 bytes */
2485 SBIG_UINT(pdata,32,quotas.hardlim);
2487 /* Quota flag 2 bytes */
2488 SSVAL(pdata,40,quotas.qflags);
2490 /* Unknown3 6 NULL bytes */
2496 #endif /* HAVE_SYS_QUOTAS */
2497 case SMB_FS_OBJECTID_INFORMATION:
2502 * Query the version and capabilities of the CIFS UNIX extensions
2506 case SMB_QUERY_CIFS_UNIX_INFO:
2507 if (!lp_unix_extensions()) {
2508 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2511 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2512 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2513 /* We have POSIX ACLs, pathname and locking capability. */
2514 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2515 CIFS_UNIX_POSIX_ACLS_CAP|
2516 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2517 CIFS_UNIX_FCNTL_LOCKS_CAP|
2518 CIFS_UNIX_EXTATTR_CAP|
2519 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2522 case SMB_QUERY_POSIX_FS_INFO:
2525 vfs_statvfs_struct svfs;
2527 if (!lp_unix_extensions()) {
2528 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2531 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2535 SIVAL(pdata,0,svfs.OptimalTransferSize);
2536 SIVAL(pdata,4,svfs.BlockSize);
2537 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2538 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2539 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2540 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2541 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2542 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2543 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2545 } else if (rc == EOPNOTSUPP) {
2546 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2547 #endif /* EOPNOTSUPP */
2549 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2550 return ERROR_DOS(ERRSRV,ERRerror);
2555 case SMB_QUERY_POSIX_WHOAMI:
2561 if (!lp_unix_extensions()) {
2562 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2565 if (max_data_bytes < 40) {
2566 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2569 /* We ARE guest if global_sid_Builtin_Guests is
2570 * in our list of SIDs.
2572 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2573 current_user.nt_user_token)) {
2574 flags |= SMB_WHOAMI_GUEST;
2577 /* We are NOT guest if global_sid_Authenticated_Users
2578 * is in our list of SIDs.
2580 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2581 current_user.nt_user_token)) {
2582 flags &= ~SMB_WHOAMI_GUEST;
2585 /* NOTE: 8 bytes for UID/GID, irrespective of native
2586 * platform size. This matches
2587 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2589 data_len = 4 /* flags */
2596 + 4 /* pad/reserved */
2597 + (current_user.ut.ngroups * 8)
2599 + (current_user.nt_user_token->num_sids *
2603 SIVAL(pdata, 0, flags);
2604 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2605 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2606 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2609 if (data_len >= max_data_bytes) {
2610 /* Potential overflow, skip the GIDs and SIDs. */
2612 SIVAL(pdata, 24, 0); /* num_groups */
2613 SIVAL(pdata, 28, 0); /* num_sids */
2614 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2615 SIVAL(pdata, 36, 0); /* reserved */
2621 SIVAL(pdata, 24, current_user.ut.ngroups);
2623 current_user.nt_user_token->num_sids);
2625 /* We walk the SID list twice, but this call is fairly
2626 * infrequent, and I don't expect that it's performance
2627 * sensitive -- jpeach
2629 for (i = 0, sid_bytes = 0;
2630 i < current_user.nt_user_token->num_sids; ++i) {
2632 sid_size(¤t_user.nt_user_token->user_sids[i]);
2635 /* SID list byte count */
2636 SIVAL(pdata, 32, sid_bytes);
2638 /* 4 bytes pad/reserved - must be zero */
2639 SIVAL(pdata, 36, 0);
2643 for (i = 0; i < current_user.ut.ngroups; ++i) {
2644 SBIG_UINT(pdata, data_len,
2645 (SMB_BIG_UINT)current_user.ut.groups[i]);
2651 i < current_user.nt_user_token->num_sids; ++i) {
2653 sid_size(¤t_user.nt_user_token->user_sids[i]);
2655 sid_linearize(pdata + data_len, sid_len,
2656 ¤t_user.nt_user_token->user_sids[i]);
2657 data_len += sid_len;
2663 case SMB_MAC_QUERY_FS_INFO:
2665 * Thursby MAC extension... ONLY on NTFS filesystems
2666 * once we do streams then we don't need this
2668 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2670 SIVAL(pdata,84,0x100); /* Don't support mac... */
2675 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2679 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2681 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2686 /****************************************************************************
2687 Reply to a TRANS2_SETFSINFO (set filesystem info).
2688 ****************************************************************************/
2690 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2691 char **pparams, int total_params, char **ppdata, int total_data,
2692 unsigned int max_data_bytes)
2694 char *pdata = *ppdata;
2695 char *params = *pparams;
2699 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2702 if (total_params < 4) {
2703 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2705 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2708 info_level = SVAL(params,2);
2710 switch(info_level) {
2711 case SMB_SET_CIFS_UNIX_INFO:
2713 uint16 client_unix_major;
2714 uint16 client_unix_minor;
2715 uint32 client_unix_cap_low;
2716 uint32 client_unix_cap_high;
2718 if (!lp_unix_extensions()) {
2719 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2722 /* There should be 12 bytes of capabilities set. */
2723 if (total_data < 8) {
2724 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2726 client_unix_major = SVAL(pdata,0);
2727 client_unix_minor = SVAL(pdata,2);
2728 client_unix_cap_low = IVAL(pdata,4);
2729 client_unix_cap_high = IVAL(pdata,8);
2730 /* Just print these values for now. */
2731 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2732 cap_low = 0x%x, cap_high = 0x%x\n",
2733 (unsigned int)client_unix_major,
2734 (unsigned int)client_unix_minor,
2735 (unsigned int)client_unix_cap_low,
2736 (unsigned int)client_unix_cap_high ));
2738 /* Here is where we must switch to posix pathname processing... */
2739 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2740 lp_set_posix_pathnames();
2741 mangle_change_to_posix();
2744 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2745 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2746 /* Client that knows how to do posix locks,
2747 * but not posix open/mkdir operations. Set a
2748 * default type for read/write checks. */
2750 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2755 case SMB_FS_QUOTA_INFORMATION:
2757 files_struct *fsp = NULL;
2758 SMB_NTQUOTA_STRUCT quotas;
2760 ZERO_STRUCT(quotas);
2763 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2764 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2765 lp_servicename(SNUM(conn)),conn->user));
2766 return ERROR_DOS(ERRSRV,ERRaccess);
2769 /* note: normaly there're 48 bytes,
2770 * but we didn't use the last 6 bytes for now
2773 fsp = file_fsp(params,0);
2774 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2775 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2776 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2779 if (total_data < 42) {
2780 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2782 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2785 /* unknown_1 24 NULL bytes in pdata*/
2787 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2788 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2789 #ifdef LARGE_SMB_OFF_T
2790 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2791 #else /* LARGE_SMB_OFF_T */
2792 if ((IVAL(pdata,28) != 0)&&
2793 ((quotas.softlim != 0xFFFFFFFF)||
2794 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2795 /* more than 32 bits? */
2796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2798 #endif /* LARGE_SMB_OFF_T */
2800 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2801 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2802 #ifdef LARGE_SMB_OFF_T
2803 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2804 #else /* LARGE_SMB_OFF_T */
2805 if ((IVAL(pdata,36) != 0)&&
2806 ((quotas.hardlim != 0xFFFFFFFF)||
2807 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2808 /* more than 32 bits? */
2809 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2811 #endif /* LARGE_SMB_OFF_T */
2813 /* quota_flags 2 bytes **/
2814 quotas.qflags = SVAL(pdata,40);
2816 /* unknown_2 6 NULL bytes follow*/
2818 /* now set the quotas */
2819 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2820 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2821 return ERROR_DOS(ERRSRV,ERRerror);
2827 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2829 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2834 * sending this reply works fine,
2835 * but I'm not sure it's the same
2836 * like windows do...
2839 outsize = set_message(outbuf,10,0,True);
2844 #if defined(HAVE_POSIX_ACLS)
2845 /****************************************************************************
2846 Utility function to count the number of entries in a POSIX acl.
2847 ****************************************************************************/
2849 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2851 unsigned int ace_count = 0;
2852 int entry_id = SMB_ACL_FIRST_ENTRY;
2853 SMB_ACL_ENTRY_T entry;
2855 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2857 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2858 entry_id = SMB_ACL_NEXT_ENTRY;
2865 /****************************************************************************
2866 Utility function to marshall a POSIX acl into wire format.
2867 ****************************************************************************/
2869 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2871 int entry_id = SMB_ACL_FIRST_ENTRY;
2872 SMB_ACL_ENTRY_T entry;
2874 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2875 SMB_ACL_TAG_T tagtype;
2876 SMB_ACL_PERMSET_T permset;
2877 unsigned char perms = 0;
2878 unsigned int own_grp;
2881 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2882 entry_id = SMB_ACL_NEXT_ENTRY;
2885 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2886 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2890 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2891 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2895 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2896 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2897 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2899 SCVAL(pdata,1,perms);
2902 case SMB_ACL_USER_OBJ:
2903 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2904 own_grp = (unsigned int)pst->st_uid;
2905 SIVAL(pdata,2,own_grp);
2910 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2912 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2914 own_grp = (unsigned int)*puid;
2915 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2916 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2917 SIVAL(pdata,2,own_grp);
2921 case SMB_ACL_GROUP_OBJ:
2922 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2923 own_grp = (unsigned int)pst->st_gid;
2924 SIVAL(pdata,2,own_grp);
2929 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2931 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2933 own_grp = (unsigned int)*pgid;
2934 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2935 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2936 SIVAL(pdata,2,own_grp);
2941 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2942 SIVAL(pdata,2,0xFFFFFFFF);
2943 SIVAL(pdata,6,0xFFFFFFFF);
2946 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2947 SIVAL(pdata,2,0xFFFFFFFF);
2948 SIVAL(pdata,6,0xFFFFFFFF);
2951 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2954 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2961 /****************************************************************************
2962 Store the FILE_UNIX_BASIC info.
2963 ****************************************************************************/
2965 static char *store_file_unix_basic(connection_struct *conn,
2968 const SMB_STRUCT_STAT *psbuf)
2970 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2971 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
2973 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
2976 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2979 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
2980 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
2981 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
2984 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
2988 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
2992 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
2995 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
2999 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3003 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3006 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3010 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3017 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3018 * the chflags(2) (or equivalent) flags.
3020 * XXX: this really should be behind the VFS interface. To do this, we would
3021 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3022 * Each VFS module could then implement it's own mapping as appropriate for the
3023 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3025 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3029 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3033 { UF_IMMUTABLE, EXT_IMMUTABLE },
3037 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3041 { UF_HIDDEN, EXT_HIDDEN }
3046 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3047 uint32 *smb_fflags, uint32 *smb_fmask)
3049 #ifdef HAVE_STAT_ST_FLAGS
3052 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3053 *smb_fmask |= info2_flags_map[i].smb_fflag;
3054 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3055 *smb_fflags |= info2_flags_map[i].smb_fflag;
3058 #endif /* HAVE_STAT_ST_FLAGS */
3061 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3062 const uint32 smb_fflags,
3063 const uint32 smb_fmask,
3066 #ifdef HAVE_STAT_ST_FLAGS
3070 *stat_fflags = psbuf->st_flags;
3072 /* For each flags requested in smb_fmask, check the state of the
3073 * corresponding flag in smb_fflags and set or clear the matching
3077 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3078 max_fmask |= info2_flags_map[i].smb_fflag;
3079 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3080 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3081 *stat_fflags |= info2_flags_map[i].stat_fflag;
3083 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3088 /* If smb_fmask is asking to set any bits that are not supported by
3089 * our flag mappings, we should fail.
3091 if ((smb_fmask & max_fmask) != smb_fmask) {
3098 #endif /* HAVE_STAT_ST_FLAGS */
3102 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3103 * of file flags and birth (create) time.
3105 static char *store_file_unix_basic_info2(connection_struct *conn,
3108 const SMB_STRUCT_STAT *psbuf)
3110 uint32 file_flags = 0;
3111 uint32 flags_mask = 0;
3113 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3115 /* Create (birth) time 64 bit */
3116 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3119 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3120 SIVAL(pdata, 0, file_flags); /* flags */
3121 SIVAL(pdata, 4, flags_mask); /* mask */
3127 /****************************************************************************
3128 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3129 file name or file id).
3130 ****************************************************************************/
3132 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3133 unsigned int tran_call,
3134 char **pparams, int total_params, char **ppdata, int total_data,
3135 unsigned int max_data_bytes)
3137 char *params = *pparams;
3138 char *pdata = *ppdata;
3142 SMB_OFF_T file_size=0;
3143 SMB_BIG_UINT allocation_size=0;
3144 unsigned int data_size = 0;
3145 unsigned int param_size = 2;
3146 SMB_STRUCT_STAT sbuf;
3147 pstring fname, dos_fname;
3152 BOOL delete_pending = False;
3154 time_t create_time, mtime, atime;
3155 struct timespec create_time_ts, mtime_ts, atime_ts;
3156 files_struct *fsp = NULL;
3157 TALLOC_CTX *data_ctx = NULL;
3158 struct ea_list *ea_list = NULL;
3159 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3160 char *lock_data = NULL;
3163 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3167 if (tran_call == TRANSACT2_QFILEINFO) {
3168 if (total_params < 4) {
3169 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3172 fsp = file_fsp(params,0);
3173 info_level = SVAL(params,2);
3175 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3177 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3178 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3181 if(fsp && (fsp->fake_file_handle)) {
3183 * This is actually for the QUOTA_FAKE_FILE --metze
3186 pstrcpy(fname, fsp->fsp_name);
3187 /* We know this name is ok, it's already passed the checks. */
3189 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3191 * This is actually a QFILEINFO on a directory
3192 * handle (returned from an NT SMB). NT5.0 seems
3193 * to do this call. JRA.
3195 /* We know this name is ok, it's already passed the checks. */
3196 pstrcpy(fname, fsp->fsp_name);
3198 if (INFO_LEVEL_IS_UNIX(info_level)) {
3199 /* Always do lstat for UNIX calls. */
3200 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3201 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3202 return UNIXERROR(ERRDOS,ERRbadpath);
3204 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3205 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3206 return UNIXERROR(ERRDOS,ERRbadpath);
3209 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3212 * Original code - this is an open file.
3214 CHECK_FSP(fsp,conn);
3216 pstrcpy(fname, fsp->fsp_name);
3217 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3218 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3219 return(UNIXERROR(ERRDOS,ERRbadfid));
3221 pos = fsp->fh->position_information;
3222 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3223 access_mask = fsp->access_mask;
3226 NTSTATUS status = NT_STATUS_OK;
3229 if (total_params < 7) {
3230 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3233 info_level = SVAL(params,0);
3235 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3237 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3238 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3241 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3242 if (!NT_STATUS_IS_OK(status)) {
3243 return ERROR_NT(status);
3246 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
3247 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3250 status = unix_convert(conn, fname, False, NULL, &sbuf);
3251 if (!NT_STATUS_IS_OK(status)) {
3252 return ERROR_NT(status);
3254 status = check_name(conn, fname);
3255 if (!NT_STATUS_IS_OK(status)) {
3256 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3257 return ERROR_NT(status);
3260 if (INFO_LEVEL_IS_UNIX(info_level)) {
3261 /* Always do lstat for UNIX calls. */
3262 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3263 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3264 return UNIXERROR(ERRDOS,ERRbadpath);
3266 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3267 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3268 return UNIXERROR(ERRDOS,ERRbadpath);
3271 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3272 if (delete_pending) {
3273 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3277 nlink = sbuf.st_nlink;
3279 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3280 /* NTFS does not seem to count ".." */
3284 if ((nlink > 0) && delete_pending) {
3288 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3289 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3292 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3293 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3295 p = strrchr_m(fname,'/');
3301 mode = dos_mode(conn,fname,&sbuf);
3303 mode = FILE_ATTRIBUTE_NORMAL;
3305 fullpathname = fname;
3307 file_size = get_file_size(sbuf);
3309 /* Pull out any data sent here before we realloc. */
3310 switch (info_level) {
3311 case SMB_INFO_QUERY_EAS_FROM_LIST:
3313 /* Pull any EA list from the data portion. */
3316 if (total_data < 4) {
3317 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3319 ea_size = IVAL(pdata,0);
3321 if (total_data > 0 && ea_size != total_data) {
3322 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3323 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3324 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3327 if (!lp_ea_support(SNUM(conn))) {
3328 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3331 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3332 return ERROR_NT(NT_STATUS_NO_MEMORY);
3335 /* Pull out the list of names. */
3336 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3338 talloc_destroy(data_ctx);
3339 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3344 case SMB_QUERY_POSIX_LOCK:
3346 if (fsp == NULL || fsp->fh->fd == -1) {
3347 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3350 if (total_data != POSIX_LOCK_DATA_SIZE) {
3351 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3354 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3355 return ERROR_NT(NT_STATUS_NO_MEMORY);
3358 /* Copy the lock range data. */
3359 lock_data = (char *)talloc_memdup(
3360 data_ctx, pdata, total_data);
3362 talloc_destroy(data_ctx);
3363 return ERROR_NT(NT_STATUS_NO_MEMORY);
3370 *pparams = (char *)SMB_REALLOC(*pparams,2);
3371 if (*pparams == NULL) {
3372 talloc_destroy(data_ctx);
3373 return ERROR_NT(NT_STATUS_NO_MEMORY);
3377 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3378 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3379 if (*ppdata == NULL ) {
3380 talloc_destroy(data_ctx);
3381 return ERROR_NT(NT_STATUS_NO_MEMORY);
3385 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3386 mtime_ts = get_mtimespec(&sbuf);
3387 atime_ts = get_atimespec(&sbuf);
3389 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3392 if (!null_timespec(fsp->pending_modtime)) {
3393 /* the pending modtime overrides the current modtime */
3394 mtime_ts = fsp->pending_modtime;
3397 /* Do we have this path open ? */
3398 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3399 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3400 /* the pending modtime overrides the current modtime */
3401 mtime_ts = fsp->pending_modtime;
3403 if (fsp1 && fsp1->initial_allocation_size) {
3404 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3408 if (lp_dos_filetime_resolution(SNUM(conn))) {
3409 dos_filetime_timespec(&create_time_ts);
3410 dos_filetime_timespec(&mtime_ts);
3411 dos_filetime_timespec(&atime_ts);
3414 create_time = convert_timespec_to_time_t(create_time_ts);
3415 mtime = convert_timespec_to_time_t(mtime_ts);
3416 atime = convert_timespec_to_time_t(atime_ts);
3418 /* NT expects the name to be in an exact form of the *full*
3419 filename. See the trans2 torture test */
3420 if (strequal(base_name,".")) {
3421 pstrcpy(dos_fname, "\\");
3423 pstr_sprintf(dos_fname, "\\%s", fname);
3424 string_replace(dos_fname, '/', '\\');
3427 switch (info_level) {
3428 case SMB_INFO_STANDARD:
3429 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3431 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3432 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3433 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3434 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3435 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3436 SSVAL(pdata,l1_attrFile,mode);
3439 case SMB_INFO_QUERY_EA_SIZE:
3441 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3442 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3444 srv_put_dos_date2(pdata,0,create_time);
3445 srv_put_dos_date2(pdata,4,atime);
3446 srv_put_dos_date2(pdata,8,mtime); /* write time */
3447 SIVAL(pdata,12,(uint32)file_size);
3448 SIVAL(pdata,16,(uint32)allocation_size);
3449 SSVAL(pdata,20,mode);
3450 SIVAL(pdata,22,ea_size);
3454 case SMB_INFO_IS_NAME_VALID:
3455 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3456 if (tran_call == TRANSACT2_QFILEINFO) {
3457 /* os/2 needs this ? really ?*/
3458 return ERROR_DOS(ERRDOS,ERRbadfunc);
3464 case SMB_INFO_QUERY_EAS_FROM_LIST:
3466 size_t total_ea_len = 0;
3467 struct ea_list *ea_file_list = NULL;
3469 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3471 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3472 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3474 if (!ea_list || (total_ea_len > data_size)) {
3475 talloc_destroy(data_ctx);
3477 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3481 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3482 talloc_destroy(data_ctx);
3486 case SMB_INFO_QUERY_ALL_EAS:
3488 /* We have data_size bytes to put EA's into. */
3489 size_t total_ea_len = 0;
3491 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3493 data_ctx = talloc_init("ea_ctx");
3495 return ERROR_NT(NT_STATUS_NO_MEMORY);
3498 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3499 if (!ea_list || (total_ea_len > data_size)) {
3500 talloc_destroy(data_ctx);
3502 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3506 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3507 talloc_destroy(data_ctx);
3511 case SMB_FILE_BASIC_INFORMATION:
3512 case SMB_QUERY_FILE_BASIC_INFO:
3514 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3515 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3516 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3518 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3522 put_long_date_timespec(pdata,create_time_ts);
3523 put_long_date_timespec(pdata+8,atime_ts);
3524 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3525 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3526 SIVAL(pdata,32,mode);
3528 DEBUG(5,("SMB_QFBI - "));
3529 DEBUG(5,("create: %s ", ctime(&create_time)));
3530 DEBUG(5,("access: %s ", ctime(&atime)));
3531 DEBUG(5,("write: %s ", ctime(&mtime)));
3532 DEBUG(5,("change: %s ", ctime(&mtime)));
3533 DEBUG(5,("mode: %x\n", mode));
3536 case SMB_FILE_STANDARD_INFORMATION:
3537 case SMB_QUERY_FILE_STANDARD_INFO:
3539 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3541 SOFF_T(pdata,0,allocation_size);
3542 SOFF_T(pdata,8,file_size);
3543 SIVAL(pdata,16,nlink);
3544 SCVAL(pdata,20,delete_pending?1:0);
3545 SCVAL(pdata,21,(mode&aDIR)?1:0);
3546 SSVAL(pdata,22,0); /* Padding. */
3549 case SMB_FILE_EA_INFORMATION:
3550 case SMB_QUERY_FILE_EA_INFO:
3552 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3553 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3555 SIVAL(pdata,0,ea_size);
3559 /* Get the 8.3 name - used if NT SMB was negotiated. */
3560 case SMB_QUERY_FILE_ALT_NAME_INFO:
3561 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3565 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3566 pstrcpy(short_name,base_name);
3567 /* Mangle if not already 8.3 */
3568 if(!mangle_is_8_3(short_name, True, conn->params)) {
3569 mangle_map(short_name,True,True,conn->params);
3571 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3572 data_size = 4 + len;
3577 case SMB_QUERY_FILE_NAME_INFO:
3579 this must be *exactly* right for ACLs on mapped drives to work
3581 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3582 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3583 data_size = 4 + len;
3587 case SMB_FILE_ALLOCATION_INFORMATION:
3588 case SMB_QUERY_FILE_ALLOCATION_INFO:
3589 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3591 SOFF_T(pdata,0,allocation_size);
3594 case SMB_FILE_END_OF_FILE_INFORMATION:
3595 case SMB_QUERY_FILE_END_OF_FILEINFO:
3596 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3598 SOFF_T(pdata,0,file_size);
3601 case SMB_QUERY_FILE_ALL_INFO:
3602 case SMB_FILE_ALL_INFORMATION:
3604 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3605 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3606 put_long_date_timespec(pdata,create_time_ts);
3607 put_long_date_timespec(pdata+8,atime_ts);
3608 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3609 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3610 SIVAL(pdata,32,mode);
3611 SIVAL(pdata,36,0); /* padding. */
3613 SOFF_T(pdata,0,allocation_size);
3614 SOFF_T(pdata,8,file_size);
3615 SIVAL(pdata,16,nlink);
3616 SCVAL(pdata,20,delete_pending);
3617 SCVAL(pdata,21,(mode&aDIR)?1:0);
3620 SIVAL(pdata,0,ea_size);
3621 pdata += 4; /* EA info */
3622 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3625 data_size = PTR_DIFF(pdata,(*ppdata));
3628 case SMB_FILE_INTERNAL_INFORMATION:
3629 /* This should be an index number - looks like
3632 I think this causes us to fail the IFSKIT
3633 BasicFileInformationTest. -tpot */
3635 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3636 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3637 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3641 case SMB_FILE_ACCESS_INFORMATION:
3642 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3643 SIVAL(pdata,0,access_mask);
3647 case SMB_FILE_NAME_INFORMATION:
3648 /* Pathname with leading '\'. */
3651 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3652 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3653 SIVAL(pdata,0,byte_len);
3654 data_size = 4 + byte_len;
3658 case SMB_FILE_DISPOSITION_INFORMATION:
3659 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3661 SCVAL(pdata,0,delete_pending);
3664 case SMB_FILE_POSITION_INFORMATION:
3665 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3667 SOFF_T(pdata,0,pos);
3670 case SMB_FILE_MODE_INFORMATION:
3671 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3672 SIVAL(pdata,0,mode);
3676 case SMB_FILE_ALIGNMENT_INFORMATION:
3677 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3678 SIVAL(pdata,0,0); /* No alignment needed. */
3684 * NT4 server just returns "invalid query" to this - if we try to answer
3685 * it then NTws gets a BSOD! (tridge).
3686 * W2K seems to want this. JRA.
3688 case SMB_QUERY_FILE_STREAM_INFO:
3690 case SMB_FILE_STREAM_INFORMATION:
3691 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3695 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3696 SIVAL(pdata,0,0); /* ??? */
3697 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3698 SOFF_T(pdata,8,file_size);
3699 SIVAL(pdata,16,allocation_size);
3700 SIVAL(pdata,20,0); /* ??? */
3701 data_size = 24 + byte_len;
3705 case SMB_QUERY_COMPRESSION_INFO:
3706 case SMB_FILE_COMPRESSION_INFORMATION:
3707 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3708 SOFF_T(pdata,0,file_size);
3709 SIVAL(pdata,8,0); /* ??? */
3710 SIVAL(pdata,12,0); /* ??? */
3714 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3715 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3716 put_long_date_timespec(pdata,create_time_ts);
3717 put_long_date_timespec(pdata+8,atime_ts);
3718 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3719 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3720 SIVAL(pdata,32,allocation_size);
3721 SOFF_T(pdata,40,file_size);
3722 SIVAL(pdata,48,mode);
3723 SIVAL(pdata,52,0); /* ??? */
3727 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3728 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3729 SIVAL(pdata,0,mode);
3735 * CIFS UNIX Extensions.
3738 case SMB_QUERY_FILE_UNIX_BASIC:
3740 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3741 data_size = PTR_DIFF(pdata,(*ppdata));
3745 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3747 for (i=0; i<100; i++)
3748 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3754 case SMB_QUERY_FILE_UNIX_INFO2:
3756 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3757 data_size = PTR_DIFF(pdata,(*ppdata));
3761 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3763 for (i=0; i<100; i++)
3764 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3770 case SMB_QUERY_FILE_UNIX_LINK:
3774 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3776 if(!S_ISLNK(sbuf.st_mode))
3777 return(UNIXERROR(ERRSRV,ERRbadlink));
3779 return(UNIXERROR(ERRDOS,ERRbadlink));
3781 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3783 return(UNIXERROR(ERRDOS,ERRnoaccess));
3785 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3787 data_size = PTR_DIFF(pdata,(*ppdata));
3792 #if defined(HAVE_POSIX_ACLS)
3793 case SMB_QUERY_POSIX_ACL:
3795 SMB_ACL_T file_acl = NULL;
3796 SMB_ACL_T def_acl = NULL;
3797 uint16 num_file_acls = 0;
3798 uint16 num_def_acls = 0;
3800 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3801 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3803 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3806 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3807 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3809 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3812 if (S_ISDIR(sbuf.st_mode)) {
3813 if (fsp && fsp->is_directory) {
3814 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3816 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3818 def_acl = free_empty_sys_acl(conn, def_acl);
3821 num_file_acls = count_acl_entries(conn, file_acl);
3822 num_def_acls = count_acl_entries(conn, def_acl);
3824 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3825 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3827 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3828 SMB_POSIX_ACL_HEADER_SIZE) ));
3830 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3833 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3835 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3838 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3839 SSVAL(pdata,2,num_file_acls);
3840 SSVAL(pdata,4,num_def_acls);
3841 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3843 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3846 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3848 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3850 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3852 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3855 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3857 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3861 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3864 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3866 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3872 case SMB_QUERY_POSIX_LOCK:
3874 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3876 SMB_BIG_UINT offset;
3878 enum brl_type lock_type;
3880 if (total_data != POSIX_LOCK_DATA_SIZE) {
3881 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3884 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3885 case POSIX_LOCK_TYPE_READ:
3886 lock_type = READ_LOCK;
3888 case POSIX_LOCK_TYPE_WRITE:
3889 lock_type = WRITE_LOCK;
3891 case POSIX_LOCK_TYPE_UNLOCK:
3893 /* There's no point in asking for an unlock... */
3894 talloc_destroy(data_ctx);
3895 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3898 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3899 #if defined(HAVE_LONGLONG)
3900 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3901 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3902 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3903 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3904 #else /* HAVE_LONGLONG */
3905 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3906 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3907 #endif /* HAVE_LONGLONG */
3909 status = query_lock(fsp,
3916 if (ERROR_WAS_LOCK_DENIED(status)) {
3917 /* Here we need to report who has it locked... */
3918 data_size = POSIX_LOCK_DATA_SIZE;
3920 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3921 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3922 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3923 #if defined(HAVE_LONGLONG)
3924 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3925 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3926 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3927 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3928 #else /* HAVE_LONGLONG */
3929 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3930 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3931 #endif /* HAVE_LONGLONG */
3933 } else if (NT_STATUS_IS_OK(status)) {
3934 /* For success we just return a copy of what we sent
3935 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3936 data_size = POSIX_LOCK_DATA_SIZE;
3937 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3938 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3940 return ERROR_NT(status);
3946 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3949 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3954 /****************************************************************************
3955 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3957 ****************************************************************************/
3959 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3961 SMB_STRUCT_STAT sbuf1, sbuf2;
3962 pstring last_component_oldname;
3963 pstring last_component_newname;
3964 NTSTATUS status = NT_STATUS_OK;
3969 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3970 if (!NT_STATUS_IS_OK(status)) {
3974 status = check_name(conn, oldname);
3975 if (!NT_STATUS_IS_OK(status)) {
3979 /* source must already exist. */
3980 if (!VALID_STAT(sbuf1)) {
3981 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3984 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
3985 if (!NT_STATUS_IS_OK(status)) {
3989 status = check_name(conn, newname);
3990 if (!NT_STATUS_IS_OK(status)) {
3994 /* Disallow if newname already exists. */
3995 if (VALID_STAT(sbuf2)) {
3996 return NT_STATUS_OBJECT_NAME_COLLISION;
3999 /* No links from a directory. */
4000 if (S_ISDIR(sbuf1.st_mode)) {
4001 return NT_STATUS_FILE_IS_A_DIRECTORY;
4004 /* Ensure this is within the share. */
4005 status = reduce_name(conn, oldname);
4006 if (!NT_STATUS_IS_OK(status)) {
4010 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4012 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4013 status = map_nt_error_from_unix(errno);
4014 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4015 nt_errstr(status), newname, oldname));
4021 /****************************************************************************
4022 Deal with setting the time from any of the setfilepathinfo functions.
4023 ****************************************************************************/
4025 static NTSTATUS smb_set_file_time(connection_struct *conn,
4028 const SMB_STRUCT_STAT *psbuf,
4029 struct timespec ts[2])
4032 FILE_NOTIFY_CHANGE_LAST_ACCESS
4033 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4036 if (!VALID_STAT(*psbuf)) {
4037 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4040 /* get some defaults (no modifications) if any info is zero or -1. */
4041 if (null_timespec(ts[0])) {
4042 ts[0] = get_atimespec(psbuf);
4043 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4046 if (null_timespec(ts[1])) {
4047 ts[1] = get_mtimespec(psbuf);
4048 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4051 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4052 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4055 * Try and set the times of this file if
4056 * they are different from the current values.
4060 struct timespec mts = get_mtimespec(psbuf);
4061 struct timespec ats = get_atimespec(psbuf);
4062 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4063 return NT_STATUS_OK;
4069 * This was a setfileinfo on an open file.
4070 * NT does this a lot. We also need to
4071 * set the time here, as it can be read by
4072 * FindFirst/FindNext and with the patch for bug #2045
4073 * in smbd/fileio.c it ensures that this timestamp is
4074 * kept sticky even after a write. We save the request
4075 * away and will set it on file close and after a write. JRA.
4078 if (!null_timespec(ts[1])) {
4079 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4080 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4081 fsp_set_pending_modtime(fsp, ts[1]);
4085 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4087 if(file_ntimes(conn, fname, ts)!=0) {
4088 return map_nt_error_from_unix(errno);
4091 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4093 return NT_STATUS_OK;
4096 /****************************************************************************
4097 Deal with setting the dosmode from any of the setfilepathinfo functions.
4098 ****************************************************************************/
4100 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4102 SMB_STRUCT_STAT *psbuf,
4105 if (!VALID_STAT(*psbuf)) {
4106 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4110 if (S_ISDIR(psbuf->st_mode)) {
4117 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4119 /* check the mode isn't different, before changing it */
4120 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4122 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4123 fname, (unsigned int)dosmode ));
4125 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4126 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4127 fname, strerror(errno)));
4128 return map_nt_error_from_unix(errno);
4131 return NT_STATUS_OK;
4134 /****************************************************************************
4135 Deal with setting the size from any of the setfilepathinfo functions.
4136 ****************************************************************************/
4138 static NTSTATUS smb_set_file_size(connection_struct *conn,
4141 SMB_STRUCT_STAT *psbuf,
4144 NTSTATUS status = NT_STATUS_OK;
4145 files_struct *new_fsp = NULL;
4147 if (!VALID_STAT(*psbuf)) {
4148 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4151 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4153 if (size == get_file_size(*psbuf)) {
4154 return NT_STATUS_OK;
4157 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4158 fname, (double)size ));
4160 if (fsp && fsp->fh->fd != -1) {
4161 /* Handle based call. */
4162 if (vfs_set_filelen(fsp, size) == -1) {
4163 return map_nt_error_from_unix(errno);
4165 return NT_STATUS_OK;
4168 status = open_file_ntcreate(conn, fname, psbuf,
4170 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4173 FILE_ATTRIBUTE_NORMAL,
4174 FORCE_OPLOCK_BREAK_TO_NONE,
4177 if (!NT_STATUS_IS_OK(status)) {
4178 /* NB. We check for open_was_deferred in the caller. */
4182 if (vfs_set_filelen(new_fsp, size) == -1) {
4183 status = map_nt_error_from_unix(errno);
4184 close_file(new_fsp,NORMAL_CLOSE);
4188 close_file(new_fsp,NORMAL_CLOSE);
4189 return NT_STATUS_OK;
4192 /****************************************************************************
4193 Deal with SMB_INFO_SET_EA.
4194 ****************************************************************************/
4196 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4202 struct ea_list *ea_list = NULL;
4203 TALLOC_CTX *ctx = NULL;
4204 NTSTATUS status = NT_STATUS_OK;
4206 if (total_data < 10) {
4208 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4209 length. They seem to have no effect. Bug #3212. JRA */
4211 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4212 /* We're done. We only get EA info in this call. */
4213 return NT_STATUS_OK;
4216 return NT_STATUS_INVALID_PARAMETER;
4219 if (IVAL(pdata,0) > total_data) {
4220 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4221 IVAL(pdata,0), (unsigned int)total_data));
4222 return NT_STATUS_INVALID_PARAMETER;
4225 ctx = talloc_init("SMB_INFO_SET_EA");
4227 return NT_STATUS_NO_MEMORY;
4229 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4231 talloc_destroy(ctx);
4232 return NT_STATUS_INVALID_PARAMETER;
4234 status = set_ea(conn, fsp, fname, ea_list);
4235 talloc_destroy(ctx);
4240 /****************************************************************************
4241 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4242 ****************************************************************************/
4244 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4249 SMB_STRUCT_STAT *psbuf)
4251 NTSTATUS status = NT_STATUS_OK;
4252 BOOL delete_on_close;
4255 if (total_data < 1) {
4256 return NT_STATUS_INVALID_PARAMETER;
4260 return NT_STATUS_INVALID_HANDLE;
4263 delete_on_close = (CVAL(pdata,0) ? True : False);
4264 dosmode = dos_mode(conn, fname, psbuf);
4266 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4267 "delete_on_close = %u\n",
4269 (unsigned int)dosmode,
4270 (unsigned int)delete_on_close ));
4272 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4274 if (!NT_STATUS_IS_OK(status)) {
4278 /* The set is across all open files on this dev/inode pair. */
4279 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4280 return NT_STATUS_ACCESS_DENIED;
4282 return NT_STATUS_OK;
4285 /****************************************************************************
4286 Deal with SMB_FILE_POSITION_INFORMATION.
4287 ****************************************************************************/
4289 static NTSTATUS smb_file_position_information(connection_struct *conn,
4294 SMB_BIG_UINT position_information;
4296 if (total_data < 8) {
4297 return NT_STATUS_INVALID_PARAMETER;
4301 /* Ignore on pathname based set. */
4302 return NT_STATUS_OK;
4305 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4306 #ifdef LARGE_SMB_OFF_T
4307 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4308 #else /* LARGE_SMB_OFF_T */
4309 if (IVAL(pdata,4) != 0) {
4310 /* more than 32 bits? */
4311 return NT_STATUS_INVALID_PARAMETER;
4313 #endif /* LARGE_SMB_OFF_T */
4315 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4316 fsp->fsp_name, (double)position_information ));
4317 fsp->fh->position_information = position_information;
4318 return NT_STATUS_OK;
4321 /****************************************************************************
4322 Deal with SMB_FILE_MODE_INFORMATION.
4323 ****************************************************************************/
4325 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4331 if (total_data < 4) {
4332 return NT_STATUS_INVALID_PARAMETER;
4334 mode = IVAL(pdata,0);
4335 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4336 return NT_STATUS_INVALID_PARAMETER;
4338 return NT_STATUS_OK;
4341 /****************************************************************************
4342 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4343 ****************************************************************************/
4345 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4351 pstring link_target;
4352 const char *newname = fname;
4353 NTSTATUS status = NT_STATUS_OK;
4355 /* Set a symbolic link. */
4356 /* Don't allow this if follow links is false. */
4358 if (total_data == 0) {
4359 return NT_STATUS_INVALID_PARAMETER;
4362 if (!lp_symlinks(SNUM(conn))) {
4363 return NT_STATUS_ACCESS_DENIED;
4366 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4368 /* !widelinks forces the target path to be within the share. */
4369 /* This means we can interpret the target as a pathname. */
4370 if (!lp_widelinks(SNUM(conn))) {
4372 char *last_dirp = NULL;
4374 unix_format(link_target);
4375 if (*link_target == '/') {
4376 /* No absolute paths allowed. */
4377 return NT_STATUS_ACCESS_DENIED;
4379 pstrcpy(rel_name, newname);
4380 last_dirp = strrchr_m(rel_name, '/');
4382 last_dirp[1] = '\0';
4384 pstrcpy(rel_name, "./");
4386 pstrcat(rel_name, link_target);
4388 status = check_name(conn, rel_name);
4389 if (!NT_STATUS_IS_OK(status)) {
4394 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4395 newname, link_target ));
4397 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4398 return map_nt_error_from_unix(errno);
4401 return NT_STATUS_OK;
4404 /****************************************************************************
4405 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4406 ****************************************************************************/
4408 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4416 NTSTATUS status = NT_STATUS_OK;
4418 /* Set a hard link. */
4419 if (total_data == 0) {
4420 return NT_STATUS_INVALID_PARAMETER;
4423 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4424 if (!NT_STATUS_IS_OK(status)) {
4428 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname)) {
4429 return NT_STATUS_PATH_NOT_COVERED;
4432 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4435 return hardlink_internals(conn, oldname, fname);
4438 /****************************************************************************
4439 Deal with SMB_FILE_RENAME_INFORMATION.
4440 ****************************************************************************/
4442 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4451 /* uint32 root_fid; */ /* Not used */
4455 BOOL dest_has_wcard = False;
4456 NTSTATUS status = NT_STATUS_OK;
4459 if (total_data < 13) {
4460 return NT_STATUS_INVALID_PARAMETER;
4463 overwrite = (CVAL(pdata,0) ? True : False);
4464 /* root_fid = IVAL(pdata,4); */
4465 len = IVAL(pdata,8);
4467 if (len > (total_data - 12) || (len == 0)) {
4468 return NT_STATUS_INVALID_PARAMETER;
4471 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4472 if (!NT_STATUS_IS_OK(status)) {
4476 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) {
4477 return NT_STATUS_PATH_NOT_COVERED;
4480 /* Check the new name has no '/' characters. */
4481 if (strchr_m(newname, '/')) {
4482 return NT_STATUS_NOT_SUPPORTED;
4485 /* Create the base directory. */
4486 pstrcpy(base_name, fname);
4487 p = strrchr_m(base_name, '/');
4491 /* Append the new name. */
4492 pstrcat(base_name, "/");
4493 pstrcat(base_name, newname);
4496 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4497 fsp->fnum, fsp->fsp_name, base_name ));
4498 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4500 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4502 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4508 /****************************************************************************
4509 Deal with SMB_SET_POSIX_ACL.
4510 ****************************************************************************/
4512 #if defined(HAVE_POSIX_ACLS)
4513 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4518 SMB_STRUCT_STAT *psbuf)
4520 uint16 posix_acl_version;
4521 uint16 num_file_acls;
4522 uint16 num_def_acls;
4523 BOOL valid_file_acls = True;
4524 BOOL valid_def_acls = True;
4526 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4527 return NT_STATUS_INVALID_PARAMETER;
4529 posix_acl_version = SVAL(pdata,0);
4530 num_file_acls = SVAL(pdata,2);
4531 num_def_acls = SVAL(pdata,4);
4533 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4534 valid_file_acls = False;
4538 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4539 valid_def_acls = False;
4543 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4544 return NT_STATUS_INVALID_PARAMETER;
4547 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4548 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4549 return NT_STATUS_INVALID_PARAMETER;
4552 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4553 fname ? fname : fsp->fsp_name,
4554 (unsigned int)num_file_acls,
4555 (unsigned int)num_def_acls));
4557 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4558 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4559 return map_nt_error_from_unix(errno);
4562 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4563 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4564 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4565 return map_nt_error_from_unix(errno);
4567 return NT_STATUS_OK;
4571 /****************************************************************************
4572 Deal with SMB_SET_POSIX_LOCK.
4573 ****************************************************************************/
4575 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4583 SMB_BIG_UINT offset;
4585 BOOL blocking_lock = False;
4586 enum brl_type lock_type;
4587 NTSTATUS status = NT_STATUS_OK;
4589 if (fsp == NULL || fsp->fh->fd == -1) {
4590 return NT_STATUS_INVALID_HANDLE;
4593 if (total_data != POSIX_LOCK_DATA_SIZE) {
4594 return NT_STATUS_INVALID_PARAMETER;
4597 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4598 case POSIX_LOCK_TYPE_READ:
4599 lock_type = READ_LOCK;
4601 case POSIX_LOCK_TYPE_WRITE:
4602 /* Return the right POSIX-mappable error code for files opened read-only. */
4603 if (!fsp->can_write) {
4604 return NT_STATUS_INVALID_HANDLE;
4606 lock_type = WRITE_LOCK;
4608 case POSIX_LOCK_TYPE_UNLOCK:
4609 lock_type = UNLOCK_LOCK;
4612 return NT_STATUS_INVALID_PARAMETER;
4615 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4616 blocking_lock = False;
4617 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4618 blocking_lock = True;
4620 return NT_STATUS_INVALID_PARAMETER;
4623 if (!lp_blocking_locks(SNUM(conn))) {
4624 blocking_lock = False;
4627 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4628 #if defined(HAVE_LONGLONG)
4629 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4630 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4631 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4632 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4633 #else /* HAVE_LONGLONG */
4634 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4635 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4636 #endif /* HAVE_LONGLONG */
4638 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4639 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4641 (unsigned int)lock_type,
4642 (unsigned int)lock_pid,
4646 if (lock_type == UNLOCK_LOCK) {
4647 status = do_unlock(fsp,
4653 struct byte_range_lock *br_lck = do_lock(fsp,
4662 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4664 * A blocking lock was requested. Package up
4665 * this smb into a queued request and push it
4666 * onto the blocking lock queue.
4668 if(push_blocking_lock_request(br_lck,
4671 -1, /* infinite timeout. */
4678 TALLOC_FREE(br_lck);
4682 TALLOC_FREE(br_lck);
4688 /****************************************************************************
4689 Deal with SMB_INFO_STANDARD.
4690 ****************************************************************************/
4692 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4697 const SMB_STRUCT_STAT *psbuf)
4699 struct timespec ts[2];
4701 if (total_data < 12) {
4702 return NT_STATUS_INVALID_PARAMETER;
4706 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4708 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4710 DEBUG(10,("smb_set_info_standard: file %s\n",
4711 fname ? fname : fsp->fsp_name ));
4713 return smb_set_file_time(conn,
4720 /****************************************************************************
4721 Deal with SMB_SET_FILE_BASIC_INFO.
4722 ****************************************************************************/
4724 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4729 SMB_STRUCT_STAT *psbuf)
4731 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4732 struct timespec write_time;
4733 struct timespec changed_time;
4735 struct timespec ts[2];
4736 NTSTATUS status = NT_STATUS_OK;
4738 if (total_data < 36) {
4739 return NT_STATUS_INVALID_PARAMETER;
4742 /* Set the attributes */
4743 dosmode = IVAL(pdata,32);
4744 status = smb_set_file_dosmode(conn,
4748 if (!NT_STATUS_IS_OK(status)) {
4752 /* Ignore create time at offset pdata. */
4755 ts[0] = interpret_long_date(pdata+8);
4757 write_time = interpret_long_date(pdata+16);
4758 changed_time = interpret_long_date(pdata+24);
4761 ts[1] = timespec_min(&write_time, &changed_time);
4763 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4767 /* Prefer a defined time to an undefined one. */
4768 if (null_timespec(ts[1])) {
4769 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4772 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4773 fname ? fname : fsp->fsp_name ));
4775 return smb_set_file_time(conn,
4782 /****************************************************************************
4783 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4784 ****************************************************************************/
4786 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4791 SMB_STRUCT_STAT *psbuf)
4793 SMB_BIG_UINT allocation_size = 0;
4794 NTSTATUS status = NT_STATUS_OK;
4795 files_struct *new_fsp = NULL;
4797 if (!VALID_STAT(*psbuf)) {
4798 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4801 if (total_data < 8) {
4802 return NT_STATUS_INVALID_PARAMETER;
4805 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4806 #ifdef LARGE_SMB_OFF_T
4807 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4808 #else /* LARGE_SMB_OFF_T */
4809 if (IVAL(pdata,4) != 0) {
4810 /* more than 32 bits? */
4811 return NT_STATUS_INVALID_PARAMETER;
4813 #endif /* LARGE_SMB_OFF_T */
4815 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4816 fname, (double)allocation_size ));
4818 if (allocation_size) {
4819 allocation_size = smb_roundup(conn, allocation_size);
4822 if(allocation_size == get_file_size(*psbuf)) {
4823 return NT_STATUS_OK;
4826 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4827 fname, (double)allocation_size ));
4829 if (fsp && fsp->fh->fd != -1) {
4830 /* Open file handle. */
4831 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4832 return map_nt_error_from_unix(errno);
4834 return NT_STATUS_OK;
4837 /* Pathname or stat or directory file. */
4839 status = open_file_ntcreate(conn, fname, psbuf,
4841 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4844 FILE_ATTRIBUTE_NORMAL,
4845 FORCE_OPLOCK_BREAK_TO_NONE,
4848 if (!NT_STATUS_IS_OK(status)) {
4849 /* NB. We check for open_was_deferred in the caller. */
4852 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4853 status = map_nt_error_from_unix(errno);
4854 close_file(new_fsp,NORMAL_CLOSE);
4858 close_file(new_fsp,NORMAL_CLOSE);
4859 return NT_STATUS_OK;
4862 /****************************************************************************
4863 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4864 ****************************************************************************/
4866 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4871 SMB_STRUCT_STAT *psbuf)
4875 if (total_data < 8) {
4876 return NT_STATUS_INVALID_PARAMETER;
4879 size = IVAL(pdata,0);
4880 #ifdef LARGE_SMB_OFF_T
4881 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4882 #else /* LARGE_SMB_OFF_T */
4883 if (IVAL(pdata,4) != 0) {
4884 /* more than 32 bits? */
4885 return NT_STATUS_INVALID_PARAMETER;
4887 #endif /* LARGE_SMB_OFF_T */
4888 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4889 "file %s to %.0f\n", fname, (double)size ));
4891 return smb_set_file_size(conn,
4898 /****************************************************************************
4899 Allow a UNIX info mknod.
4900 ****************************************************************************/
4902 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4906 SMB_STRUCT_STAT *psbuf)
4908 uint32 file_type = IVAL(pdata,56);
4909 #if defined(HAVE_MAKEDEV)
4910 uint32 dev_major = IVAL(pdata,60);
4911 uint32 dev_minor = IVAL(pdata,68);
4913 SMB_DEV_T dev = (SMB_DEV_T)0;
4914 uint32 raw_unixmode = IVAL(pdata,84);
4918 if (total_data < 100) {
4919 return NT_STATUS_INVALID_PARAMETER;
4922 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4923 if (!NT_STATUS_IS_OK(status)) {
4927 #if defined(HAVE_MAKEDEV)
4928 dev = makedev(dev_major, dev_minor);
4931 switch (file_type) {
4932 #if defined(S_IFIFO)
4933 case UNIX_TYPE_FIFO:
4934 unixmode |= S_IFIFO;
4937 #if defined(S_IFSOCK)
4938 case UNIX_TYPE_SOCKET:
4939 unixmode |= S_IFSOCK;
4942 #if defined(S_IFCHR)
4943 case UNIX_TYPE_CHARDEV:
4944 unixmode |= S_IFCHR;
4947 #if defined(S_IFBLK)
4948 case UNIX_TYPE_BLKDEV:
4949 unixmode |= S_IFBLK;
4953 return NT_STATUS_INVALID_PARAMETER;
4956 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4957 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
4959 /* Ok - do the mknod. */
4960 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
4961 return map_nt_error_from_unix(errno);
4964 /* If any of the other "set" calls fail we
4965 * don't want to end up with a half-constructed mknod.
4968 if (lp_inherit_perms(SNUM(conn))) {
4970 conn, parent_dirname(fname),
4974 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
4975 status = map_nt_error_from_unix(errno);
4976 SMB_VFS_UNLINK(conn,fname);
4979 return NT_STATUS_OK;
4982 /****************************************************************************
4983 Deal with SMB_SET_FILE_UNIX_BASIC.
4984 ****************************************************************************/
4986 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
4991 SMB_STRUCT_STAT *psbuf)
4993 struct timespec ts[2];
4994 uint32 raw_unixmode;
4997 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4998 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4999 NTSTATUS status = NT_STATUS_OK;
5000 BOOL delete_on_fail = False;
5001 enum perm_type ptype;
5003 if (total_data < 100) {
5004 return NT_STATUS_INVALID_PARAMETER;
5007 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5008 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5009 size=IVAL(pdata,0); /* first 8 Bytes are size */
5010 #ifdef LARGE_SMB_OFF_T
5011 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5012 #else /* LARGE_SMB_OFF_T */
5013 if (IVAL(pdata,4) != 0) {
5014 /* more than 32 bits? */
5015 return NT_STATUS_INVALID_PARAMETER;
5017 #endif /* LARGE_SMB_OFF_T */
5020 ts[0] = interpret_long_date(pdata+24); /* access_time */
5021 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5022 set_owner = (uid_t)IVAL(pdata,40);
5023 set_grp = (gid_t)IVAL(pdata,48);
5024 raw_unixmode = IVAL(pdata,84);
5026 if (VALID_STAT(*psbuf)) {
5027 if (S_ISDIR(psbuf->st_mode)) {
5028 ptype = PERM_EXISTING_DIR;
5030 ptype = PERM_EXISTING_FILE;
5033 ptype = PERM_NEW_FILE;
5036 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5037 if (!NT_STATUS_IS_OK(status)) {
5041 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5042 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5043 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5045 if (!VALID_STAT(*psbuf)) {
5047 * The only valid use of this is to create character and block
5048 * devices, and named pipes. This is deprecated (IMHO) and
5049 * a new info level should be used for mknod. JRA.
5052 status = smb_unix_mknod(conn,
5057 if (!NT_STATUS_IS_OK(status)) {
5061 /* Ensure we don't try and change anything else. */
5062 raw_unixmode = SMB_MODE_NO_CHANGE;
5063 size = get_file_size(*psbuf);
5064 ts[0] = get_atimespec(psbuf);
5065 ts[1] = get_mtimespec(psbuf);
5067 * We continue here as we might want to change the
5070 delete_on_fail = True;
5074 /* Horrible backwards compatibility hack as an old server bug
5075 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5079 size = get_file_size(*psbuf);
5084 * Deal with the UNIX specific mode set.
5087 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5088 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5089 (unsigned int)unixmode, fname ));
5090 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5091 return map_nt_error_from_unix(errno);
5096 * Deal with the UNIX specific uid set.
5099 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5100 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5101 (unsigned int)set_owner, fname ));
5102 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5103 status = map_nt_error_from_unix(errno);
5104 if (delete_on_fail) {
5105 SMB_VFS_UNLINK(conn,fname);
5112 * Deal with the UNIX specific gid set.
5115 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5116 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5117 (unsigned int)set_owner, fname ));
5118 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5119 status = map_nt_error_from_unix(errno);
5120 if (delete_on_fail) {
5121 SMB_VFS_UNLINK(conn,fname);
5127 /* Deal with any size changes. */
5129 status = smb_set_file_size(conn,
5134 if (!NT_STATUS_IS_OK(status)) {
5138 /* Deal with any time changes. */
5140 return smb_set_file_time(conn,
5147 /****************************************************************************
5148 Deal with SMB_SET_FILE_UNIX_INFO2.
5149 ****************************************************************************/
5151 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5156 SMB_STRUCT_STAT *psbuf)
5162 if (total_data < 116) {
5163 return NT_STATUS_INVALID_PARAMETER;
5166 /* Start by setting all the fields that are common between UNIX_BASIC
5169 status = smb_set_file_unix_basic(conn, pdata, total_data,
5171 if (!NT_STATUS_IS_OK(status)) {
5175 smb_fflags = IVAL(pdata, 108);
5176 smb_fmask = IVAL(pdata, 112);
5178 /* NB: We should only attempt to alter the file flags if the client
5179 * sends a non-zero mask.
5181 if (smb_fmask != 0) {
5182 int stat_fflags = 0;
5184 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5186 /* Client asked to alter a flag we don't understand. */
5187 return NT_STATUS_INVALID_PARAMETER;
5190 if (fsp && fsp->fh->fd != -1) {
5191 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5192 return NT_STATUS_NOT_SUPPORTED;
5194 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5195 return map_nt_error_from_unix(errno);
5200 /* XXX: need to add support for changing the create_time here. You
5201 * can do this for paths on Darwin with setattrlist(2). The right way
5202 * to hook this up is probably by extending the VFS utimes interface.
5205 return NT_STATUS_OK;
5208 /****************************************************************************
5209 Create a directory with POSIX semantics.
5210 ****************************************************************************/
5212 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5216 SMB_STRUCT_STAT *psbuf,
5217 int *pdata_return_size)
5219 NTSTATUS status = NT_STATUS_OK;
5220 uint32 raw_unixmode = 0;
5221 uint32 mod_unixmode = 0;
5222 mode_t unixmode = (mode_t)0;
5223 files_struct *fsp = NULL;
5224 uint16 info_level_return = 0;
5225 char *pdata = *ppdata;
5227 if (total_data < 10) {
5228 return NT_STATUS_INVALID_PARAMETER;
5231 raw_unixmode = IVAL(pdata,8);
5232 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5233 if (!NT_STATUS_IS_OK(status)) {
5237 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5239 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5240 fname, (unsigned int)unixmode ));
5242 status = open_directory(conn,
5245 FILE_READ_ATTRIBUTES, /* Just a stat open */
5246 FILE_SHARE_NONE, /* Ignored for stat opens */
5253 if (NT_STATUS_IS_OK(status)) {
5254 close_file(fsp, NORMAL_CLOSE);
5257 info_level_return = SVAL(pdata,12);
5259 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5260 *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
5262 *pdata_return_size = 8;
5265 /* Realloc the data size */
5266 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5267 if (*ppdata == NULL) {
5268 *pdata_return_size = 0;
5269 return NT_STATUS_NO_MEMORY;
5272 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5275 switch (info_level_return) {
5276 case SMB_QUERY_FILE_UNIX_BASIC:
5277 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
5278 SSVAL(pdata,6,0); /* Padding. */
5279 store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
5280 case SMB_QUERY_FILE_UNIX_INFO2:
5281 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_INFO2);
5282 SSVAL(pdata,6,0); /* Padding. */
5283 store_file_unix_basic_info2(conn, pdata + 8, fsp, psbuf);
5285 SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
5286 SSVAL(pdata,6,0); /* Padding. */
5292 /****************************************************************************
5293 Open/Create a file with POSIX semantics.
5294 ****************************************************************************/
5296 static NTSTATUS smb_posix_open(connection_struct *conn,
5300 SMB_STRUCT_STAT *psbuf,
5301 int *pdata_return_size)
5303 BOOL extended_oplock_granted = False;
5304 char *pdata = *ppdata;
5306 uint32 wire_open_mode = 0;
5307 uint32 raw_unixmode = 0;
5308 uint32 mod_unixmode = 0;
5309 uint32 create_disp = 0;
5310 uint32 access_mask = 0;
5311 uint32 create_options = 0;
5312 NTSTATUS status = NT_STATUS_OK;
5313 mode_t unixmode = (mode_t)0;
5314 files_struct *fsp = NULL;
5315 int oplock_request = 0;
5317 uint16 info_level_return = 0;
5319 if (total_data < 14) {
5320 return NT_STATUS_INVALID_PARAMETER;
5323 flags = IVAL(pdata,0);
5324 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5325 if (oplock_request) {
5326 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5329 wire_open_mode = IVAL(pdata,4);
5331 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5332 return smb_posix_mkdir(conn,
5340 switch (wire_open_mode & SMB_ACCMODE) {
5342 access_mask = FILE_READ_DATA;
5345 access_mask = FILE_WRITE_DATA;
5348 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5351 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5352 (unsigned int)wire_open_mode ));
5353 return NT_STATUS_INVALID_PARAMETER;
5356 wire_open_mode &= ~SMB_ACCMODE;
5358 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5359 create_disp = FILE_CREATE;
5360 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5361 create_disp = FILE_OVERWRITE_IF;
5362 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5363 create_disp = FILE_OPEN_IF;
5365 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5366 (unsigned int)wire_open_mode ));
5367 return NT_STATUS_INVALID_PARAMETER;
5370 raw_unixmode = IVAL(pdata,8);
5371 status = unix_perms_from_wire(conn,
5374 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5377 if (!NT_STATUS_IS_OK(status)) {
5381 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5383 if (wire_open_mode & SMB_O_SYNC) {
5384 create_options |= FILE_WRITE_THROUGH;
5386 if (wire_open_mode & SMB_O_APPEND) {
5387 access_mask |= FILE_APPEND_DATA;
5389 if (wire_open_mode & SMB_O_DIRECT) {
5390 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5393 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5395 (unsigned int)wire_open_mode,
5396 (unsigned int)unixmode ));
5398 status = open_file_ntcreate(conn,
5402 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5404 0, /* no create options yet. */
5410 if (!NT_STATUS_IS_OK(status)) {
5414 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5415 extended_oplock_granted = True;
5418 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5419 extended_oplock_granted = True;
5422 info_level_return = SVAL(pdata,12);
5424 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5425 *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
5427 *pdata_return_size = 8;
5430 /* Realloc the data size */
5431 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5432 if (*ppdata == NULL) {
5433 close_file(fsp,ERROR_CLOSE);
5434 *pdata_return_size = 0;
5435 return NT_STATUS_NO_MEMORY;
5438 if (extended_oplock_granted) {
5439 if (flags & REQUEST_BATCH_OPLOCK) {
5440 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5442 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5444 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5445 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5447 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5450 SSVAL(pdata,2,fsp->fnum);
5451 switch (info_level_return) {
5452 case SMB_QUERY_FILE_UNIX_BASIC:
5453 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
5454 SSVAL(pdata,6,0); /* padding. */
5455 store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
5456 case SMB_QUERY_FILE_UNIX_INFO2:
5457 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_INFO2);
5458 SSVAL(pdata,6,0); /* padding. */
5459 store_file_unix_basic_info2(conn, pdata + 8, fsp, psbuf);
5461 SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
5462 SSVAL(pdata,6,0); /* padding. */
5464 return NT_STATUS_OK;
5467 /****************************************************************************
5468 Delete a file with POSIX semantics.
5469 ****************************************************************************/
5471 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5475 SMB_STRUCT_STAT *psbuf)
5477 NTSTATUS status = NT_STATUS_OK;
5478 files_struct *fsp = NULL;
5482 if (total_data < 2) {
5483 return NT_STATUS_INVALID_PARAMETER;
5486 flags = SVAL(pdata,0);
5488 if (!VALID_STAT(*psbuf)) {
5489 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5492 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5493 !VALID_STAT_OF_DIR(*psbuf)) {
5494 return NT_STATUS_NOT_A_DIRECTORY;
5497 DEBUG(10,("smb_posix_unlink: %s %s\n",
5498 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5501 if (VALID_STAT_OF_DIR(*psbuf)) {
5502 status = open_directory(conn,
5506 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5508 FILE_DELETE_ON_CLOSE,
5509 FILE_FLAG_POSIX_SEMANTICS|0777,
5515 status = open_file_ntcreate(conn,
5519 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5522 FILE_FLAG_POSIX_SEMANTICS|0777,
5523 0, /* No oplock, but break existing ones. */
5527 * For file opens we must set the delete on close
5531 if (!NT_STATUS_IS_OK(status)) {
5535 status = smb_set_file_disposition_info(conn,
5543 if (!NT_STATUS_IS_OK(status)) {
5546 return close_file(fsp, NORMAL_CLOSE);
5549 /****************************************************************************
5550 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5551 ****************************************************************************/
5553 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5554 unsigned int tran_call,
5555 char **pparams, int total_params, char **ppdata, int total_data,
5556 unsigned int max_data_bytes)
5558 char *params = *pparams;
5559 char *pdata = *ppdata;
5561 SMB_STRUCT_STAT sbuf;
5563 files_struct *fsp = NULL;
5564 NTSTATUS status = NT_STATUS_OK;
5565 int data_return_size = 0;
5568 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5573 if (tran_call == TRANSACT2_SETFILEINFO) {
5574 if (total_params < 4) {
5575 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5578 fsp = file_fsp(params,0);
5579 info_level = SVAL(params,2);
5581 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5583 * This is actually a SETFILEINFO on a directory
5584 * handle (returned from an NT SMB). NT5.0 seems
5585 * to do this call. JRA.
5587 pstrcpy(fname, fsp->fsp_name);
5588 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5589 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5590 return UNIXERROR(ERRDOS,ERRbadpath);
5592 } else if (fsp && fsp->print_file) {
5594 * Doing a DELETE_ON_CLOSE should cancel a print job.
5596 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5597 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5599 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5602 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5605 return (UNIXERROR(ERRDOS,ERRbadpath));
5608 * Original code - this is an open file.
5610 CHECK_FSP(fsp,conn);
5612 pstrcpy(fname, fsp->fsp_name);
5614 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5615 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5616 return(UNIXERROR(ERRDOS,ERRbadfid));
5621 if (total_params < 7) {
5622 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5625 info_level = SVAL(params,0);
5626 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5627 if (!NT_STATUS_IS_OK(status)) {
5628 return ERROR_NT(status);
5631 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
5632 ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5635 status = unix_convert(conn, fname, False, NULL, &sbuf);
5636 if (!NT_STATUS_IS_OK(status)) {
5637 return ERROR_NT(status);
5640 status = check_name(conn, fname);
5641 if (!NT_STATUS_IS_OK(status)) {
5642 return ERROR_NT(status);
5646 * For CIFS UNIX extensions the target name may not exist.
5649 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5650 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5651 return UNIXERROR(ERRDOS,ERRbadpath);
5655 if (!CAN_WRITE(conn)) {
5656 return ERROR_DOS(ERRSRV,ERRaccess);
5659 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5660 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5663 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5664 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5666 /* Realloc the parameter size */
5667 *pparams = (char *)SMB_REALLOC(*pparams,2);
5668 if (*pparams == NULL) {
5669 return ERROR_NT(NT_STATUS_NO_MEMORY);
5675 if (fsp && !null_timespec(fsp->pending_modtime)) {
5676 /* the pending modtime overrides the current modtime */
5677 set_mtimespec(&sbuf, fsp->pending_modtime);
5680 switch (info_level) {
5682 case SMB_INFO_STANDARD:
5684 status = smb_set_info_standard(conn,
5693 case SMB_INFO_SET_EA:
5695 status = smb_info_set_ea(conn,
5703 case SMB_SET_FILE_BASIC_INFO:
5704 case SMB_FILE_BASIC_INFORMATION:
5706 status = smb_set_file_basic_info(conn,
5715 case SMB_FILE_ALLOCATION_INFORMATION:
5716 case SMB_SET_FILE_ALLOCATION_INFO:
5718 status = smb_set_file_allocation_info(conn,
5727 case SMB_FILE_END_OF_FILE_INFORMATION:
5728 case SMB_SET_FILE_END_OF_FILE_INFO:
5730 status = smb_set_file_end_of_file_info(conn,
5739 case SMB_FILE_DISPOSITION_INFORMATION:
5740 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5743 /* JRA - We used to just ignore this on a path ?
5744 * Shouldn't this be invalid level on a pathname
5747 if (tran_call != TRANSACT2_SETFILEINFO) {
5748 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5751 status = smb_set_file_disposition_info(conn,
5760 case SMB_FILE_POSITION_INFORMATION:
5762 status = smb_file_position_information(conn,
5769 /* From tridge Samba4 :
5770 * MODE_INFORMATION in setfileinfo (I have no
5771 * idea what "mode information" on a file is - it takes a value of 0,
5772 * 2, 4 or 6. What could it be?).
5775 case SMB_FILE_MODE_INFORMATION:
5777 status = smb_file_mode_information(conn,
5784 * CIFS UNIX extensions.
5787 case SMB_SET_FILE_UNIX_BASIC:
5789 status = smb_set_file_unix_basic(conn,
5798 case SMB_SET_FILE_UNIX_INFO2:
5800 status = smb_set_file_unix_info2(conn,
5809 case SMB_SET_FILE_UNIX_LINK:
5811 if (tran_call != TRANSACT2_SETPATHINFO) {
5812 /* We must have a pathname for this. */
5813 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5815 status = smb_set_file_unix_link(conn,
5823 case SMB_SET_FILE_UNIX_HLINK:
5825 if (tran_call != TRANSACT2_SETPATHINFO) {
5826 /* We must have a pathname for this. */
5827 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5829 status = smb_set_file_unix_hlink(conn,
5838 case SMB_FILE_RENAME_INFORMATION:
5840 status = smb_file_rename_information(conn,
5850 #if defined(HAVE_POSIX_ACLS)
5851 case SMB_SET_POSIX_ACL:
5853 status = smb_set_posix_acl(conn,
5863 case SMB_SET_POSIX_LOCK:
5865 if (tran_call != TRANSACT2_SETFILEINFO) {
5866 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5868 status = smb_set_posix_lock(conn,
5877 case SMB_POSIX_PATH_OPEN:
5879 if (tran_call != TRANSACT2_SETPATHINFO) {
5880 /* We must have a pathname for this. */
5881 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5884 status = smb_posix_open(conn,
5893 case SMB_POSIX_PATH_UNLINK:
5895 if (tran_call != TRANSACT2_SETPATHINFO) {
5896 /* We must have a pathname for this. */
5897 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5900 status = smb_posix_unlink(conn,
5909 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5913 if (!NT_STATUS_IS_OK(status)) {
5914 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5915 /* We have re-scheduled this call. */
5918 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5919 /* We have re-scheduled this call. */
5922 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5923 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5925 return ERROR_NT(status);
5929 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
5934 /****************************************************************************
5935 Reply to a TRANS2_MKDIR (make directory with extended attributes).
5936 ****************************************************************************/
5938 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5939 char **pparams, int total_params, char **ppdata, int total_data,
5940 unsigned int max_data_bytes)
5942 char *params = *pparams;
5943 char *pdata = *ppdata;
5945 SMB_STRUCT_STAT sbuf;
5946 NTSTATUS status = NT_STATUS_OK;
5947 struct ea_list *ea_list = NULL;
5949 if (!CAN_WRITE(conn))
5950 return ERROR_DOS(ERRSRV,ERRaccess);
5952 if (total_params < 5) {
5953 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5956 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
5957 if (!NT_STATUS_IS_OK(status)) {
5958 return ERROR_NT(status);
5961 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
5963 status = unix_convert(conn, directory, False, NULL, &sbuf);
5964 if (!NT_STATUS_IS_OK(status)) {
5965 return ERROR_NT(status);
5968 status = check_name(conn, directory);
5969 if (!NT_STATUS_IS_OK(status)) {
5970 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5971 return ERROR_NT(status);
5974 /* Any data in this call is an EA list. */
5975 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5976 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5980 * OS/2 workplace shell seems to send SET_EA requests of "null"
5981 * length (4 bytes containing IVAL 4).
5982 * They seem to have no effect. Bug #3212. JRA.
5985 if (total_data != 4) {
5986 if (total_data < 10) {
5987 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5990 if (IVAL(pdata,0) > total_data) {
5991 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
5992 IVAL(pdata,0), (unsigned int)total_data));
5993 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5996 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
5999 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6001 } else if (IVAL(pdata,0) != 4) {
6002 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6005 status = create_directory(conn, directory);
6007 if (!NT_STATUS_IS_OK(status)) {
6008 return ERROR_NT(status);
6011 /* Try and set any given EA. */
6013 status = set_ea(conn, NULL, directory, ea_list);
6014 if (!NT_STATUS_IS_OK(status)) {
6015 return ERROR_NT(status);
6019 /* Realloc the parameter and data sizes */
6020 *pparams = (char *)SMB_REALLOC(*pparams,2);
6021 if(*pparams == NULL) {
6022 return ERROR_NT(NT_STATUS_NO_MEMORY);
6028 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6033 /****************************************************************************
6034 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6035 We don't actually do this - we just send a null response.
6036 ****************************************************************************/
6038 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6039 char **pparams, int total_params, char **ppdata, int total_data,
6040 unsigned int max_data_bytes)
6042 static uint16 fnf_handle = 257;
6043 char *params = *pparams;
6046 if (total_params < 6) {
6047 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6050 info_level = SVAL(params,4);
6051 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6053 switch (info_level) {
6058 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6061 /* Realloc the parameter and data sizes */
6062 *pparams = (char *)SMB_REALLOC(*pparams,6);
6063 if (*pparams == NULL) {
6064 return ERROR_NT(NT_STATUS_NO_MEMORY);
6068 SSVAL(params,0,fnf_handle);
6069 SSVAL(params,2,0); /* No changes */
6070 SSVAL(params,4,0); /* No EA errors */
6077 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6082 /****************************************************************************
6083 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6084 changes). Currently this does nothing.
6085 ****************************************************************************/
6087 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6088 char **pparams, int total_params, char **ppdata, int total_data,
6089 unsigned int max_data_bytes)
6091 char *params = *pparams;
6093 DEBUG(3,("call_trans2findnotifynext\n"));
6095 /* Realloc the parameter and data sizes */
6096 *pparams = (char *)SMB_REALLOC(*pparams,4);
6097 if (*pparams == NULL) {
6098 return ERROR_NT(NT_STATUS_NO_MEMORY);
6102 SSVAL(params,0,0); /* No changes */
6103 SSVAL(params,2,0); /* No EA errors */
6105 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6110 /****************************************************************************
6111 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6112 ****************************************************************************/
6114 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6115 char **pparams, int total_params, char **ppdata, int total_data,
6116 unsigned int max_data_bytes)
6118 char *params = *pparams;
6121 int max_referral_level;
6123 DEBUG(10,("call_trans2getdfsreferral\n"));
6125 if (total_params < 3) {
6126 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6129 max_referral_level = SVAL(params,0);
6131 if(!lp_host_msdfs())
6132 return ERROR_DOS(ERRDOS,ERRbadfunc);
6134 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6135 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
6136 return UNIXERROR(ERRDOS,ERRbadfile);
6138 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6139 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6144 #define LMCAT_SPL 0x53
6145 #define LMFUNC_GETJOBID 0x60
6147 /****************************************************************************
6148 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6149 ****************************************************************************/
6151 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6152 char **pparams, int total_params, char **ppdata, int total_data,
6153 unsigned int max_data_bytes)
6155 char *pdata = *ppdata;
6156 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6158 /* check for an invalid fid before proceeding */
6161 return(ERROR_DOS(ERRDOS,ERRbadfid));
6163 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6164 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6165 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6166 if (*ppdata == NULL) {
6167 return ERROR_NT(NT_STATUS_NO_MEMORY);
6171 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6172 CAN ACCEPT THIS IN UNICODE. JRA. */
6174 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6175 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6176 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6177 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6180 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6181 return ERROR_DOS(ERRSRV,ERRerror);
6185 /****************************************************************************
6186 Reply to a SMBfindclose (stop trans2 directory search).
6187 ****************************************************************************/
6189 int reply_findclose(connection_struct *conn,
6190 char *inbuf,char *outbuf,int length,int bufsize)
6193 int dptr_num=SVALS(inbuf,smb_vwv0);
6194 START_PROFILE(SMBfindclose);
6196 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6198 dptr_close(&dptr_num);
6200 outsize = set_message(outbuf,0,0,False);
6202 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6204 END_PROFILE(SMBfindclose);
6208 /****************************************************************************
6209 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6210 ****************************************************************************/
6212 int reply_findnclose(connection_struct *conn,
6213 char *inbuf,char *outbuf,int length,int bufsize)
6217 START_PROFILE(SMBfindnclose);
6219 dptr_num = SVAL(inbuf,smb_vwv0);
6221 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6223 /* We never give out valid handles for a
6224 findnotifyfirst - so any dptr_num is ok here.
6227 outsize = set_message(outbuf,0,0,False);
6229 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6231 END_PROFILE(SMBfindnclose);
6235 int handle_trans2(connection_struct *conn,
6236 struct trans_state *state,
6237 char *inbuf, char *outbuf, int size, int bufsize)
6241 if (Protocol >= PROTOCOL_NT1) {
6242 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6245 /* Now we must call the relevant TRANS2 function */
6246 switch(state->call) {
6247 case TRANSACT2_OPEN:
6249 START_PROFILE(Trans2_open);
6250 outsize = call_trans2open(
6251 conn, inbuf, outbuf, bufsize,
6252 &state->param, state->total_param,
6253 &state->data, state->total_data,
6254 state->max_data_return);
6255 END_PROFILE(Trans2_open);
6259 case TRANSACT2_FINDFIRST:
6261 START_PROFILE(Trans2_findfirst);
6262 outsize = call_trans2findfirst(
6263 conn, inbuf, outbuf, bufsize,
6264 &state->param, state->total_param,
6265 &state->data, state->total_data,
6266 state->max_data_return);
6267 END_PROFILE(Trans2_findfirst);
6271 case TRANSACT2_FINDNEXT:
6273 START_PROFILE(Trans2_findnext);
6274 outsize = call_trans2findnext(
6275 conn, inbuf, outbuf, size, bufsize,
6276 &state->param, state->total_param,
6277 &state->data, state->total_data,
6278 state->max_data_return);
6279 END_PROFILE(Trans2_findnext);
6283 case TRANSACT2_QFSINFO:
6285 START_PROFILE(Trans2_qfsinfo);
6286 outsize = call_trans2qfsinfo(
6287 conn, inbuf, outbuf, size, bufsize,
6288 &state->param, state->total_param,
6289 &state->data, state->total_data,
6290 state->max_data_return);
6291 END_PROFILE(Trans2_qfsinfo);
6295 case TRANSACT2_SETFSINFO:
6297 START_PROFILE(Trans2_setfsinfo);
6298 outsize = call_trans2setfsinfo(
6299 conn, inbuf, outbuf, size, bufsize,
6300 &state->param, state->total_param,
6301 &state->data, state->total_data,
6302 state->max_data_return);
6303 END_PROFILE(Trans2_setfsinfo);
6307 case TRANSACT2_QPATHINFO:
6308 case TRANSACT2_QFILEINFO:
6310 START_PROFILE(Trans2_qpathinfo);
6311 outsize = call_trans2qfilepathinfo(
6312 conn, inbuf, outbuf, size, bufsize, state->call,
6313 &state->param, state->total_param,
6314 &state->data, state->total_data,
6315 state->max_data_return);
6316 END_PROFILE(Trans2_qpathinfo);
6320 case TRANSACT2_SETPATHINFO:
6321 case TRANSACT2_SETFILEINFO:
6323 START_PROFILE(Trans2_setpathinfo);
6324 outsize = call_trans2setfilepathinfo(
6325 conn, inbuf, outbuf, size, bufsize, state->call,
6326 &state->param, state->total_param,
6327 &state->data, state->total_data,
6328 state->max_data_return);
6329 END_PROFILE(Trans2_setpathinfo);
6333 case TRANSACT2_FINDNOTIFYFIRST:
6335 START_PROFILE(Trans2_findnotifyfirst);
6336 outsize = call_trans2findnotifyfirst(
6337 conn, inbuf, outbuf, size, bufsize,
6338 &state->param, state->total_param,
6339 &state->data, state->total_data,
6340 state->max_data_return);
6341 END_PROFILE(Trans2_findnotifyfirst);
6345 case TRANSACT2_FINDNOTIFYNEXT:
6347 START_PROFILE(Trans2_findnotifynext);
6348 outsize = call_trans2findnotifynext(
6349 conn, inbuf, outbuf, size, bufsize,
6350 &state->param, state->total_param,
6351 &state->data, state->total_data,
6352 state->max_data_return);
6353 END_PROFILE(Trans2_findnotifynext);
6357 case TRANSACT2_MKDIR:
6359 START_PROFILE(Trans2_mkdir);
6360 outsize = call_trans2mkdir(
6361 conn, inbuf, outbuf, size, bufsize,
6362 &state->param, state->total_param,
6363 &state->data, state->total_data,
6364 state->max_data_return);
6365 END_PROFILE(Trans2_mkdir);
6369 case TRANSACT2_GET_DFS_REFERRAL:
6371 START_PROFILE(Trans2_get_dfs_referral);
6372 outsize = call_trans2getdfsreferral(
6373 conn, inbuf, outbuf, size, bufsize,
6374 &state->param, state->total_param,
6375 &state->data, state->total_data,
6376 state->max_data_return);
6377 END_PROFILE(Trans2_get_dfs_referral);
6381 case TRANSACT2_IOCTL:
6383 START_PROFILE(Trans2_ioctl);
6384 outsize = call_trans2ioctl(
6385 conn, inbuf, outbuf, size, bufsize,
6386 &state->param, state->total_param,
6387 &state->data, state->total_data,
6388 state->max_data_return);
6389 END_PROFILE(Trans2_ioctl);
6394 /* Error in request */
6395 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6396 outsize = ERROR_DOS(ERRSRV,ERRerror);
6402 /****************************************************************************
6403 Reply to a SMBtrans2.
6404 ****************************************************************************/
6406 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6407 int size, int bufsize)
6410 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6411 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6412 unsigned int psoff = SVAL(inbuf, smb_psoff);
6413 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6414 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6415 struct trans_state *state;
6418 START_PROFILE(SMBtrans2);
6420 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6421 if (!NT_STATUS_IS_OK(result)) {
6422 DEBUG(2, ("Got invalid trans2 request: %s\n",
6423 nt_errstr(result)));
6424 END_PROFILE(SMBtrans2);
6425 return ERROR_NT(result);
6428 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6429 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6430 END_PROFILE(SMBtrans2);
6431 return ERROR_DOS(ERRSRV,ERRaccess);
6434 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6435 DEBUG(0, ("talloc failed\n"));
6436 END_PROFILE(SMBtrans2);
6437 return ERROR_NT(NT_STATUS_NO_MEMORY);
6440 state->cmd = SMBtrans2;
6442 state->mid = SVAL(inbuf, smb_mid);
6443 state->vuid = SVAL(inbuf, smb_uid);
6444 state->setup_count = SVAL(inbuf, smb_suwcnt);
6445 state->setup = NULL;
6446 state->total_param = SVAL(inbuf, smb_tpscnt);
6447 state->param = NULL;
6448 state->total_data = SVAL(inbuf, smb_tdscnt);
6450 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6451 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6452 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6453 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6454 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6456 state->call = tran_call;
6458 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6459 is so as a sanity check */
6460 if (state->setup_count != 1) {
6462 * Need to have rc=0 for ioctl to get job id for OS/2.
6463 * Network printing will fail if function is not successful.
6464 * Similar function in reply.c will be used if protocol
6465 * is LANMAN1.0 instead of LM1.2X002.
6466 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6467 * outbuf doesn't have to be set(only job id is used).
6469 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6470 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6471 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6472 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6474 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6475 DEBUG(2,("Transaction is %d\n",tran_call));
6477 END_PROFILE(SMBtrans2);
6478 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6482 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6485 if (state->total_data) {
6486 /* Can't use talloc here, the core routines do realloc on the
6487 * params and data. */
6488 state->data = (char *)SMB_MALLOC(state->total_data);
6489 if (state->data == NULL) {
6490 DEBUG(0,("reply_trans2: data malloc fail for %u "
6491 "bytes !\n", (unsigned int)state->total_data));
6493 END_PROFILE(SMBtrans2);
6494 return(ERROR_DOS(ERRDOS,ERRnomem));
6496 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6498 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6499 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6502 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6505 if (state->total_param) {
6506 /* Can't use talloc here, the core routines do realloc on the
6507 * params and data. */
6508 state->param = (char *)SMB_MALLOC(state->total_param);
6509 if (state->param == NULL) {
6510 DEBUG(0,("reply_trans: param malloc fail for %u "
6511 "bytes !\n", (unsigned int)state->total_param));
6512 SAFE_FREE(state->data);
6514 END_PROFILE(SMBtrans2);
6515 return(ERROR_DOS(ERRDOS,ERRnomem));
6517 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6519 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6520 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6523 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6526 state->received_data = dscnt;
6527 state->received_param = pscnt;
6529 if ((state->received_param == state->total_param) &&
6530 (state->received_data == state->total_data)) {
6532 outsize = handle_trans2(conn, state, inbuf, outbuf,
6534 SAFE_FREE(state->data);
6535 SAFE_FREE(state->param);
6537 END_PROFILE(SMBtrans2);
6541 DLIST_ADD(conn->pending_trans, state);
6543 /* We need to send an interim response then receive the rest
6544 of the parameter/data bytes */
6545 outsize = set_message(outbuf,0,0,False);
6547 END_PROFILE(SMBtrans2);
6552 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6553 SAFE_FREE(state->data);
6554 SAFE_FREE(state->param);
6556 END_PROFILE(SMBtrans2);
6557 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6561 /****************************************************************************
6562 Reply to a SMBtranss2
6563 ****************************************************************************/
6565 int reply_transs2(connection_struct *conn,
6566 char *inbuf,char *outbuf,int size,int bufsize)
6569 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6570 struct trans_state *state;
6572 START_PROFILE(SMBtranss2);
6576 for (state = conn->pending_trans; state != NULL;
6577 state = state->next) {
6578 if (state->mid == SVAL(inbuf,smb_mid)) {
6583 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6584 END_PROFILE(SMBtranss2);
6585 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6588 /* Revise state->total_param and state->total_data in case they have
6589 changed downwards */
6591 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6592 state->total_param = SVAL(inbuf, smb_tpscnt);
6593 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6594 state->total_data = SVAL(inbuf, smb_tdscnt);
6596 pcnt = SVAL(inbuf, smb_spscnt);
6597 poff = SVAL(inbuf, smb_spsoff);
6598 pdisp = SVAL(inbuf, smb_spsdisp);
6600 dcnt = SVAL(inbuf, smb_sdscnt);
6601 doff = SVAL(inbuf, smb_sdsoff);
6602 ddisp = SVAL(inbuf, smb_sdsdisp);
6604 state->received_param += pcnt;
6605 state->received_data += dcnt;
6607 if ((state->received_data > state->total_data) ||
6608 (state->received_param > state->total_param))
6612 if (pdisp+pcnt > state->total_param)
6614 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6616 if (pdisp > state->total_param)
6618 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6619 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6621 if (state->param + pdisp < state->param)
6624 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6629 if (ddisp+dcnt > state->total_data)
6631 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6633 if (ddisp > state->total_data)
6635 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6636 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6638 if (state->data + ddisp < state->data)
6641 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6645 if ((state->received_param < state->total_param) ||
6646 (state->received_data < state->total_data)) {
6647 END_PROFILE(SMBtranss2);
6651 /* construct_reply_common has done us the favor to pre-fill the
6652 * command field with SMBtranss2 which is wrong :-)
6654 SCVAL(outbuf,smb_com,SMBtrans2);
6656 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6658 DLIST_REMOVE(conn->pending_trans, state);
6659 SAFE_FREE(state->data);
6660 SAFE_FREE(state->param);
6664 END_PROFILE(SMBtranss2);
6665 return(ERROR_DOS(ERRSRV,ERRnosupport));
6668 END_PROFILE(SMBtranss2);
6673 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6674 DLIST_REMOVE(conn->pending_trans, state);
6675 SAFE_FREE(state->data);
6676 SAFE_FREE(state->param);
6678 END_PROFILE(SMBtranss2);
6679 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);