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 },
3044 /* Do not remove. We need to guarantee that this array has at least one
3045 * entry to build on HP-UX.
3051 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3052 uint32 *smb_fflags, uint32 *smb_fmask)
3054 #ifdef HAVE_STAT_ST_FLAGS
3057 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3058 *smb_fmask |= info2_flags_map[i].smb_fflag;
3059 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3060 *smb_fflags |= info2_flags_map[i].smb_fflag;
3063 #endif /* HAVE_STAT_ST_FLAGS */
3066 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3067 const uint32 smb_fflags,
3068 const uint32 smb_fmask,
3071 #ifdef HAVE_STAT_ST_FLAGS
3072 uint32 max_fmask = 0;
3075 *stat_fflags = psbuf->st_flags;
3077 /* For each flags requested in smb_fmask, check the state of the
3078 * corresponding flag in smb_fflags and set or clear the matching
3082 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3083 max_fmask |= info2_flags_map[i].smb_fflag;
3084 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3085 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3086 *stat_fflags |= info2_flags_map[i].stat_fflag;
3088 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3093 /* If smb_fmask is asking to set any bits that are not supported by
3094 * our flag mappings, we should fail.
3096 if ((smb_fmask & max_fmask) != smb_fmask) {
3103 #endif /* HAVE_STAT_ST_FLAGS */
3107 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3108 * of file flags and birth (create) time.
3110 static char *store_file_unix_basic_info2(connection_struct *conn,
3113 const SMB_STRUCT_STAT *psbuf)
3115 uint32 file_flags = 0;
3116 uint32 flags_mask = 0;
3118 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3120 /* Create (birth) time 64 bit */
3121 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3124 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3125 SIVAL(pdata, 0, file_flags); /* flags */
3126 SIVAL(pdata, 4, flags_mask); /* mask */
3132 /****************************************************************************
3133 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3134 file name or file id).
3135 ****************************************************************************/
3137 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3138 unsigned int tran_call,
3139 char **pparams, int total_params, char **ppdata, int total_data,
3140 unsigned int max_data_bytes)
3142 char *params = *pparams;
3143 char *pdata = *ppdata;
3147 SMB_OFF_T file_size=0;
3148 SMB_BIG_UINT allocation_size=0;
3149 unsigned int data_size = 0;
3150 unsigned int param_size = 2;
3151 SMB_STRUCT_STAT sbuf;
3152 pstring fname, dos_fname;
3157 BOOL delete_pending = False;
3159 time_t create_time, mtime, atime;
3160 struct timespec create_time_ts, mtime_ts, atime_ts;
3161 files_struct *fsp = NULL;
3162 TALLOC_CTX *data_ctx = NULL;
3163 struct ea_list *ea_list = NULL;
3164 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3165 char *lock_data = NULL;
3168 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3172 if (tran_call == TRANSACT2_QFILEINFO) {
3173 if (total_params < 4) {
3174 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3177 fsp = file_fsp(params,0);
3178 info_level = SVAL(params,2);
3180 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3182 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3183 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3186 if(fsp && (fsp->fake_file_handle)) {
3188 * This is actually for the QUOTA_FAKE_FILE --metze
3191 pstrcpy(fname, fsp->fsp_name);
3192 /* We know this name is ok, it's already passed the checks. */
3194 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3196 * This is actually a QFILEINFO on a directory
3197 * handle (returned from an NT SMB). NT5.0 seems
3198 * to do this call. JRA.
3200 /* We know this name is ok, it's already passed the checks. */
3201 pstrcpy(fname, fsp->fsp_name);
3203 if (INFO_LEVEL_IS_UNIX(info_level)) {
3204 /* Always do lstat for UNIX calls. */
3205 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3206 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3207 return UNIXERROR(ERRDOS,ERRbadpath);
3209 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3210 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3211 return UNIXERROR(ERRDOS,ERRbadpath);
3214 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3217 * Original code - this is an open file.
3219 CHECK_FSP(fsp,conn);
3221 pstrcpy(fname, fsp->fsp_name);
3222 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3223 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3224 return(UNIXERROR(ERRDOS,ERRbadfid));
3226 pos = fsp->fh->position_information;
3227 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3228 access_mask = fsp->access_mask;
3231 NTSTATUS status = NT_STATUS_OK;
3234 if (total_params < 7) {
3235 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3238 info_level = SVAL(params,0);
3240 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3242 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3243 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3246 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 return ERROR_NT(status);
3251 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
3252 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3255 status = unix_convert(conn, fname, False, NULL, &sbuf);
3256 if (!NT_STATUS_IS_OK(status)) {
3257 return ERROR_NT(status);
3259 status = check_name(conn, fname);
3260 if (!NT_STATUS_IS_OK(status)) {
3261 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3262 return ERROR_NT(status);
3265 if (INFO_LEVEL_IS_UNIX(info_level)) {
3266 /* Always do lstat for UNIX calls. */
3267 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3268 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3269 return UNIXERROR(ERRDOS,ERRbadpath);
3271 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3272 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3273 return UNIXERROR(ERRDOS,ERRbadpath);
3276 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3277 if (delete_pending) {
3278 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3282 nlink = sbuf.st_nlink;
3284 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3285 /* NTFS does not seem to count ".." */
3289 if ((nlink > 0) && delete_pending) {
3293 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3294 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3297 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3298 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3300 p = strrchr_m(fname,'/');
3306 mode = dos_mode(conn,fname,&sbuf);
3308 mode = FILE_ATTRIBUTE_NORMAL;
3310 fullpathname = fname;
3312 file_size = get_file_size(sbuf);
3314 /* Pull out any data sent here before we realloc. */
3315 switch (info_level) {
3316 case SMB_INFO_QUERY_EAS_FROM_LIST:
3318 /* Pull any EA list from the data portion. */
3321 if (total_data < 4) {
3322 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3324 ea_size = IVAL(pdata,0);
3326 if (total_data > 0 && ea_size != total_data) {
3327 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3328 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3329 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3332 if (!lp_ea_support(SNUM(conn))) {
3333 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3336 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3337 return ERROR_NT(NT_STATUS_NO_MEMORY);
3340 /* Pull out the list of names. */
3341 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3343 talloc_destroy(data_ctx);
3344 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3349 case SMB_QUERY_POSIX_LOCK:
3351 if (fsp == NULL || fsp->fh->fd == -1) {
3352 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3355 if (total_data != POSIX_LOCK_DATA_SIZE) {
3356 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3359 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3360 return ERROR_NT(NT_STATUS_NO_MEMORY);
3363 /* Copy the lock range data. */
3364 lock_data = (char *)talloc_memdup(
3365 data_ctx, pdata, total_data);
3367 talloc_destroy(data_ctx);
3368 return ERROR_NT(NT_STATUS_NO_MEMORY);
3375 *pparams = (char *)SMB_REALLOC(*pparams,2);
3376 if (*pparams == NULL) {
3377 talloc_destroy(data_ctx);
3378 return ERROR_NT(NT_STATUS_NO_MEMORY);
3382 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3383 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3384 if (*ppdata == NULL ) {
3385 talloc_destroy(data_ctx);
3386 return ERROR_NT(NT_STATUS_NO_MEMORY);
3390 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3391 mtime_ts = get_mtimespec(&sbuf);
3392 atime_ts = get_atimespec(&sbuf);
3394 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3397 if (!null_timespec(fsp->pending_modtime)) {
3398 /* the pending modtime overrides the current modtime */
3399 mtime_ts = fsp->pending_modtime;
3402 /* Do we have this path open ? */
3403 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3404 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3405 /* the pending modtime overrides the current modtime */
3406 mtime_ts = fsp1->pending_modtime;
3408 if (fsp1 && fsp1->initial_allocation_size) {
3409 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3413 if (lp_dos_filetime_resolution(SNUM(conn))) {
3414 dos_filetime_timespec(&create_time_ts);
3415 dos_filetime_timespec(&mtime_ts);
3416 dos_filetime_timespec(&atime_ts);
3419 create_time = convert_timespec_to_time_t(create_time_ts);
3420 mtime = convert_timespec_to_time_t(mtime_ts);
3421 atime = convert_timespec_to_time_t(atime_ts);
3423 /* NT expects the name to be in an exact form of the *full*
3424 filename. See the trans2 torture test */
3425 if (strequal(base_name,".")) {
3426 pstrcpy(dos_fname, "\\");
3428 pstr_sprintf(dos_fname, "\\%s", fname);
3429 string_replace(dos_fname, '/', '\\');
3432 switch (info_level) {
3433 case SMB_INFO_STANDARD:
3434 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3436 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3437 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3438 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3439 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3440 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3441 SSVAL(pdata,l1_attrFile,mode);
3444 case SMB_INFO_QUERY_EA_SIZE:
3446 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3447 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3449 srv_put_dos_date2(pdata,0,create_time);
3450 srv_put_dos_date2(pdata,4,atime);
3451 srv_put_dos_date2(pdata,8,mtime); /* write time */
3452 SIVAL(pdata,12,(uint32)file_size);
3453 SIVAL(pdata,16,(uint32)allocation_size);
3454 SSVAL(pdata,20,mode);
3455 SIVAL(pdata,22,ea_size);
3459 case SMB_INFO_IS_NAME_VALID:
3460 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3461 if (tran_call == TRANSACT2_QFILEINFO) {
3462 /* os/2 needs this ? really ?*/
3463 return ERROR_DOS(ERRDOS,ERRbadfunc);
3469 case SMB_INFO_QUERY_EAS_FROM_LIST:
3471 size_t total_ea_len = 0;
3472 struct ea_list *ea_file_list = NULL;
3474 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3476 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3477 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3479 if (!ea_list || (total_ea_len > data_size)) {
3480 talloc_destroy(data_ctx);
3482 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3486 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3487 talloc_destroy(data_ctx);
3491 case SMB_INFO_QUERY_ALL_EAS:
3493 /* We have data_size bytes to put EA's into. */
3494 size_t total_ea_len = 0;
3496 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3498 data_ctx = talloc_init("ea_ctx");
3500 return ERROR_NT(NT_STATUS_NO_MEMORY);
3503 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3504 if (!ea_list || (total_ea_len > data_size)) {
3505 talloc_destroy(data_ctx);
3507 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3511 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3512 talloc_destroy(data_ctx);
3516 case SMB_FILE_BASIC_INFORMATION:
3517 case SMB_QUERY_FILE_BASIC_INFO:
3519 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3520 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3521 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3523 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3527 put_long_date_timespec(pdata,create_time_ts);
3528 put_long_date_timespec(pdata+8,atime_ts);
3529 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3530 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3531 SIVAL(pdata,32,mode);
3533 DEBUG(5,("SMB_QFBI - "));
3534 DEBUG(5,("create: %s ", ctime(&create_time)));
3535 DEBUG(5,("access: %s ", ctime(&atime)));
3536 DEBUG(5,("write: %s ", ctime(&mtime)));
3537 DEBUG(5,("change: %s ", ctime(&mtime)));
3538 DEBUG(5,("mode: %x\n", mode));
3541 case SMB_FILE_STANDARD_INFORMATION:
3542 case SMB_QUERY_FILE_STANDARD_INFO:
3544 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3546 SOFF_T(pdata,0,allocation_size);
3547 SOFF_T(pdata,8,file_size);
3548 SIVAL(pdata,16,nlink);
3549 SCVAL(pdata,20,delete_pending?1:0);
3550 SCVAL(pdata,21,(mode&aDIR)?1:0);
3551 SSVAL(pdata,22,0); /* Padding. */
3554 case SMB_FILE_EA_INFORMATION:
3555 case SMB_QUERY_FILE_EA_INFO:
3557 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3558 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3560 SIVAL(pdata,0,ea_size);
3564 /* Get the 8.3 name - used if NT SMB was negotiated. */
3565 case SMB_QUERY_FILE_ALT_NAME_INFO:
3566 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3570 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3571 pstrcpy(short_name,base_name);
3572 /* Mangle if not already 8.3 */
3573 if(!mangle_is_8_3(short_name, True, conn->params)) {
3574 mangle_map(short_name,True,True,conn->params);
3576 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3577 data_size = 4 + len;
3582 case SMB_QUERY_FILE_NAME_INFO:
3584 this must be *exactly* right for ACLs on mapped drives to work
3586 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3587 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3588 data_size = 4 + len;
3592 case SMB_FILE_ALLOCATION_INFORMATION:
3593 case SMB_QUERY_FILE_ALLOCATION_INFO:
3594 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3596 SOFF_T(pdata,0,allocation_size);
3599 case SMB_FILE_END_OF_FILE_INFORMATION:
3600 case SMB_QUERY_FILE_END_OF_FILEINFO:
3601 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3603 SOFF_T(pdata,0,file_size);
3606 case SMB_QUERY_FILE_ALL_INFO:
3607 case SMB_FILE_ALL_INFORMATION:
3609 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3610 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3611 put_long_date_timespec(pdata,create_time_ts);
3612 put_long_date_timespec(pdata+8,atime_ts);
3613 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3614 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3615 SIVAL(pdata,32,mode);
3616 SIVAL(pdata,36,0); /* padding. */
3618 SOFF_T(pdata,0,allocation_size);
3619 SOFF_T(pdata,8,file_size);
3620 SIVAL(pdata,16,nlink);
3621 SCVAL(pdata,20,delete_pending);
3622 SCVAL(pdata,21,(mode&aDIR)?1:0);
3625 SIVAL(pdata,0,ea_size);
3626 pdata += 4; /* EA info */
3627 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3630 data_size = PTR_DIFF(pdata,(*ppdata));
3633 case SMB_FILE_INTERNAL_INFORMATION:
3634 /* This should be an index number - looks like
3637 I think this causes us to fail the IFSKIT
3638 BasicFileInformationTest. -tpot */
3640 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3641 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3642 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3646 case SMB_FILE_ACCESS_INFORMATION:
3647 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3648 SIVAL(pdata,0,access_mask);
3652 case SMB_FILE_NAME_INFORMATION:
3653 /* Pathname with leading '\'. */
3656 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3657 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3658 SIVAL(pdata,0,byte_len);
3659 data_size = 4 + byte_len;
3663 case SMB_FILE_DISPOSITION_INFORMATION:
3664 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3666 SCVAL(pdata,0,delete_pending);
3669 case SMB_FILE_POSITION_INFORMATION:
3670 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3672 SOFF_T(pdata,0,pos);
3675 case SMB_FILE_MODE_INFORMATION:
3676 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3677 SIVAL(pdata,0,mode);
3681 case SMB_FILE_ALIGNMENT_INFORMATION:
3682 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3683 SIVAL(pdata,0,0); /* No alignment needed. */
3689 * NT4 server just returns "invalid query" to this - if we try to answer
3690 * it then NTws gets a BSOD! (tridge).
3691 * W2K seems to want this. JRA.
3693 case SMB_QUERY_FILE_STREAM_INFO:
3695 case SMB_FILE_STREAM_INFORMATION:
3696 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3700 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3701 SIVAL(pdata,0,0); /* ??? */
3702 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3703 SOFF_T(pdata,8,file_size);
3704 SIVAL(pdata,16,allocation_size);
3705 SIVAL(pdata,20,0); /* ??? */
3706 data_size = 24 + byte_len;
3710 case SMB_QUERY_COMPRESSION_INFO:
3711 case SMB_FILE_COMPRESSION_INFORMATION:
3712 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3713 SOFF_T(pdata,0,file_size);
3714 SIVAL(pdata,8,0); /* ??? */
3715 SIVAL(pdata,12,0); /* ??? */
3719 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3720 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3721 put_long_date_timespec(pdata,create_time_ts);
3722 put_long_date_timespec(pdata+8,atime_ts);
3723 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3724 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3725 SIVAL(pdata,32,allocation_size);
3726 SOFF_T(pdata,40,file_size);
3727 SIVAL(pdata,48,mode);
3728 SIVAL(pdata,52,0); /* ??? */
3732 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3733 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3734 SIVAL(pdata,0,mode);
3740 * CIFS UNIX Extensions.
3743 case SMB_QUERY_FILE_UNIX_BASIC:
3745 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3746 data_size = PTR_DIFF(pdata,(*ppdata));
3750 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3752 for (i=0; i<100; i++)
3753 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3759 case SMB_QUERY_FILE_UNIX_INFO2:
3761 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3762 data_size = PTR_DIFF(pdata,(*ppdata));
3766 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3768 for (i=0; i<100; i++)
3769 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3775 case SMB_QUERY_FILE_UNIX_LINK:
3779 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3781 if(!S_ISLNK(sbuf.st_mode))
3782 return(UNIXERROR(ERRSRV,ERRbadlink));
3784 return(UNIXERROR(ERRDOS,ERRbadlink));
3786 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3788 return(UNIXERROR(ERRDOS,ERRnoaccess));
3790 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3792 data_size = PTR_DIFF(pdata,(*ppdata));
3797 #if defined(HAVE_POSIX_ACLS)
3798 case SMB_QUERY_POSIX_ACL:
3800 SMB_ACL_T file_acl = NULL;
3801 SMB_ACL_T def_acl = NULL;
3802 uint16 num_file_acls = 0;
3803 uint16 num_def_acls = 0;
3805 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3806 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3808 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3811 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3812 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3814 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3817 if (S_ISDIR(sbuf.st_mode)) {
3818 if (fsp && fsp->is_directory) {
3819 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3821 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3823 def_acl = free_empty_sys_acl(conn, def_acl);
3826 num_file_acls = count_acl_entries(conn, file_acl);
3827 num_def_acls = count_acl_entries(conn, def_acl);
3829 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3830 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3832 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3833 SMB_POSIX_ACL_HEADER_SIZE) ));
3835 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3838 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3840 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3843 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3844 SSVAL(pdata,2,num_file_acls);
3845 SSVAL(pdata,4,num_def_acls);
3846 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3848 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3851 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3853 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3855 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3857 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3860 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3862 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3866 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3869 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3871 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3877 case SMB_QUERY_POSIX_LOCK:
3879 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3881 SMB_BIG_UINT offset;
3883 enum brl_type lock_type;
3885 if (total_data != POSIX_LOCK_DATA_SIZE) {
3886 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3889 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3890 case POSIX_LOCK_TYPE_READ:
3891 lock_type = READ_LOCK;
3893 case POSIX_LOCK_TYPE_WRITE:
3894 lock_type = WRITE_LOCK;
3896 case POSIX_LOCK_TYPE_UNLOCK:
3898 /* There's no point in asking for an unlock... */
3899 talloc_destroy(data_ctx);
3900 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3903 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3904 #if defined(HAVE_LONGLONG)
3905 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3906 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3907 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3908 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3909 #else /* HAVE_LONGLONG */
3910 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3911 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3912 #endif /* HAVE_LONGLONG */
3914 status = query_lock(fsp,
3921 if (ERROR_WAS_LOCK_DENIED(status)) {
3922 /* Here we need to report who has it locked... */
3923 data_size = POSIX_LOCK_DATA_SIZE;
3925 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3926 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3927 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3928 #if defined(HAVE_LONGLONG)
3929 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3930 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3931 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3932 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3933 #else /* HAVE_LONGLONG */
3934 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3935 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3936 #endif /* HAVE_LONGLONG */
3938 } else if (NT_STATUS_IS_OK(status)) {
3939 /* For success we just return a copy of what we sent
3940 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3941 data_size = POSIX_LOCK_DATA_SIZE;
3942 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3943 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3945 return ERROR_NT(status);
3951 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3954 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3959 /****************************************************************************
3960 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3962 ****************************************************************************/
3964 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3966 SMB_STRUCT_STAT sbuf1, sbuf2;
3967 pstring last_component_oldname;
3968 pstring last_component_newname;
3969 NTSTATUS status = NT_STATUS_OK;
3974 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3975 if (!NT_STATUS_IS_OK(status)) {
3979 status = check_name(conn, oldname);
3980 if (!NT_STATUS_IS_OK(status)) {
3984 /* source must already exist. */
3985 if (!VALID_STAT(sbuf1)) {
3986 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3989 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
3990 if (!NT_STATUS_IS_OK(status)) {
3994 status = check_name(conn, newname);
3995 if (!NT_STATUS_IS_OK(status)) {
3999 /* Disallow if newname already exists. */
4000 if (VALID_STAT(sbuf2)) {
4001 return NT_STATUS_OBJECT_NAME_COLLISION;
4004 /* No links from a directory. */
4005 if (S_ISDIR(sbuf1.st_mode)) {
4006 return NT_STATUS_FILE_IS_A_DIRECTORY;
4009 /* Ensure this is within the share. */
4010 status = reduce_name(conn, oldname);
4011 if (!NT_STATUS_IS_OK(status)) {
4015 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4017 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4018 status = map_nt_error_from_unix(errno);
4019 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4020 nt_errstr(status), newname, oldname));
4026 /****************************************************************************
4027 Deal with setting the time from any of the setfilepathinfo functions.
4028 ****************************************************************************/
4030 static NTSTATUS smb_set_file_time(connection_struct *conn,
4033 const SMB_STRUCT_STAT *psbuf,
4034 struct timespec ts[2])
4037 FILE_NOTIFY_CHANGE_LAST_ACCESS
4038 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4041 if (!VALID_STAT(*psbuf)) {
4042 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4045 /* get some defaults (no modifications) if any info is zero or -1. */
4046 if (null_timespec(ts[0])) {
4047 ts[0] = get_atimespec(psbuf);
4048 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4051 if (null_timespec(ts[1])) {
4052 ts[1] = get_mtimespec(psbuf);
4053 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4056 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4057 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4060 * Try and set the times of this file if
4061 * they are different from the current values.
4065 struct timespec mts = get_mtimespec(psbuf);
4066 struct timespec ats = get_atimespec(psbuf);
4067 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4068 return NT_STATUS_OK;
4074 * This was a setfileinfo on an open file.
4075 * NT does this a lot. We also need to
4076 * set the time here, as it can be read by
4077 * FindFirst/FindNext and with the patch for bug #2045
4078 * in smbd/fileio.c it ensures that this timestamp is
4079 * kept sticky even after a write. We save the request
4080 * away and will set it on file close and after a write. JRA.
4083 if (!null_timespec(ts[1])) {
4084 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4085 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4086 fsp_set_pending_modtime(fsp, ts[1]);
4090 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4092 if(file_ntimes(conn, fname, ts)!=0) {
4093 return map_nt_error_from_unix(errno);
4096 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4098 return NT_STATUS_OK;
4101 /****************************************************************************
4102 Deal with setting the dosmode from any of the setfilepathinfo functions.
4103 ****************************************************************************/
4105 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4107 SMB_STRUCT_STAT *psbuf,
4110 if (!VALID_STAT(*psbuf)) {
4111 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4115 if (S_ISDIR(psbuf->st_mode)) {
4122 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4124 /* check the mode isn't different, before changing it */
4125 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4127 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4128 fname, (unsigned int)dosmode ));
4130 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4131 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4132 fname, strerror(errno)));
4133 return map_nt_error_from_unix(errno);
4136 return NT_STATUS_OK;
4139 /****************************************************************************
4140 Deal with setting the size from any of the setfilepathinfo functions.
4141 ****************************************************************************/
4143 static NTSTATUS smb_set_file_size(connection_struct *conn,
4146 SMB_STRUCT_STAT *psbuf,
4149 NTSTATUS status = NT_STATUS_OK;
4150 files_struct *new_fsp = NULL;
4152 if (!VALID_STAT(*psbuf)) {
4153 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4156 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4158 if (size == get_file_size(*psbuf)) {
4159 return NT_STATUS_OK;
4162 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4163 fname, (double)size ));
4165 if (fsp && fsp->fh->fd != -1) {
4166 /* Handle based call. */
4167 if (vfs_set_filelen(fsp, size) == -1) {
4168 return map_nt_error_from_unix(errno);
4170 return NT_STATUS_OK;
4173 status = open_file_ntcreate(conn, fname, psbuf,
4175 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4178 FILE_ATTRIBUTE_NORMAL,
4179 FORCE_OPLOCK_BREAK_TO_NONE,
4182 if (!NT_STATUS_IS_OK(status)) {
4183 /* NB. We check for open_was_deferred in the caller. */
4187 if (vfs_set_filelen(new_fsp, size) == -1) {
4188 status = map_nt_error_from_unix(errno);
4189 close_file(new_fsp,NORMAL_CLOSE);
4193 close_file(new_fsp,NORMAL_CLOSE);
4194 return NT_STATUS_OK;
4197 /****************************************************************************
4198 Deal with SMB_INFO_SET_EA.
4199 ****************************************************************************/
4201 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4207 struct ea_list *ea_list = NULL;
4208 TALLOC_CTX *ctx = NULL;
4209 NTSTATUS status = NT_STATUS_OK;
4211 if (total_data < 10) {
4213 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4214 length. They seem to have no effect. Bug #3212. JRA */
4216 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4217 /* We're done. We only get EA info in this call. */
4218 return NT_STATUS_OK;
4221 return NT_STATUS_INVALID_PARAMETER;
4224 if (IVAL(pdata,0) > total_data) {
4225 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4226 IVAL(pdata,0), (unsigned int)total_data));
4227 return NT_STATUS_INVALID_PARAMETER;
4230 ctx = talloc_init("SMB_INFO_SET_EA");
4232 return NT_STATUS_NO_MEMORY;
4234 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4236 talloc_destroy(ctx);
4237 return NT_STATUS_INVALID_PARAMETER;
4239 status = set_ea(conn, fsp, fname, ea_list);
4240 talloc_destroy(ctx);
4245 /****************************************************************************
4246 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4247 ****************************************************************************/
4249 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4254 SMB_STRUCT_STAT *psbuf)
4256 NTSTATUS status = NT_STATUS_OK;
4257 BOOL delete_on_close;
4260 if (total_data < 1) {
4261 return NT_STATUS_INVALID_PARAMETER;
4265 return NT_STATUS_INVALID_HANDLE;
4268 delete_on_close = (CVAL(pdata,0) ? True : False);
4269 dosmode = dos_mode(conn, fname, psbuf);
4271 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4272 "delete_on_close = %u\n",
4274 (unsigned int)dosmode,
4275 (unsigned int)delete_on_close ));
4277 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4279 if (!NT_STATUS_IS_OK(status)) {
4283 /* The set is across all open files on this dev/inode pair. */
4284 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4285 return NT_STATUS_ACCESS_DENIED;
4287 return NT_STATUS_OK;
4290 /****************************************************************************
4291 Deal with SMB_FILE_POSITION_INFORMATION.
4292 ****************************************************************************/
4294 static NTSTATUS smb_file_position_information(connection_struct *conn,
4299 SMB_BIG_UINT position_information;
4301 if (total_data < 8) {
4302 return NT_STATUS_INVALID_PARAMETER;
4306 /* Ignore on pathname based set. */
4307 return NT_STATUS_OK;
4310 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4311 #ifdef LARGE_SMB_OFF_T
4312 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4313 #else /* LARGE_SMB_OFF_T */
4314 if (IVAL(pdata,4) != 0) {
4315 /* more than 32 bits? */
4316 return NT_STATUS_INVALID_PARAMETER;
4318 #endif /* LARGE_SMB_OFF_T */
4320 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4321 fsp->fsp_name, (double)position_information ));
4322 fsp->fh->position_information = position_information;
4323 return NT_STATUS_OK;
4326 /****************************************************************************
4327 Deal with SMB_FILE_MODE_INFORMATION.
4328 ****************************************************************************/
4330 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4336 if (total_data < 4) {
4337 return NT_STATUS_INVALID_PARAMETER;
4339 mode = IVAL(pdata,0);
4340 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4341 return NT_STATUS_INVALID_PARAMETER;
4343 return NT_STATUS_OK;
4346 /****************************************************************************
4347 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4348 ****************************************************************************/
4350 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4356 pstring link_target;
4357 const char *newname = fname;
4358 NTSTATUS status = NT_STATUS_OK;
4360 /* Set a symbolic link. */
4361 /* Don't allow this if follow links is false. */
4363 if (total_data == 0) {
4364 return NT_STATUS_INVALID_PARAMETER;
4367 if (!lp_symlinks(SNUM(conn))) {
4368 return NT_STATUS_ACCESS_DENIED;
4371 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4373 /* !widelinks forces the target path to be within the share. */
4374 /* This means we can interpret the target as a pathname. */
4375 if (!lp_widelinks(SNUM(conn))) {
4377 char *last_dirp = NULL;
4379 unix_format(link_target);
4380 if (*link_target == '/') {
4381 /* No absolute paths allowed. */
4382 return NT_STATUS_ACCESS_DENIED;
4384 pstrcpy(rel_name, newname);
4385 last_dirp = strrchr_m(rel_name, '/');
4387 last_dirp[1] = '\0';
4389 pstrcpy(rel_name, "./");
4391 pstrcat(rel_name, link_target);
4393 status = check_name(conn, rel_name);
4394 if (!NT_STATUS_IS_OK(status)) {
4399 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4400 newname, link_target ));
4402 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4403 return map_nt_error_from_unix(errno);
4406 return NT_STATUS_OK;
4409 /****************************************************************************
4410 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4411 ****************************************************************************/
4413 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4421 NTSTATUS status = NT_STATUS_OK;
4423 /* Set a hard link. */
4424 if (total_data == 0) {
4425 return NT_STATUS_INVALID_PARAMETER;
4428 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4429 if (!NT_STATUS_IS_OK(status)) {
4433 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname)) {
4434 return NT_STATUS_PATH_NOT_COVERED;
4437 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4440 return hardlink_internals(conn, oldname, fname);
4443 /****************************************************************************
4444 Deal with SMB_FILE_RENAME_INFORMATION.
4445 ****************************************************************************/
4447 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4456 /* uint32 root_fid; */ /* Not used */
4460 BOOL dest_has_wcard = False;
4461 NTSTATUS status = NT_STATUS_OK;
4464 if (total_data < 13) {
4465 return NT_STATUS_INVALID_PARAMETER;
4468 overwrite = (CVAL(pdata,0) ? True : False);
4469 /* root_fid = IVAL(pdata,4); */
4470 len = IVAL(pdata,8);
4472 if (len > (total_data - 12) || (len == 0)) {
4473 return NT_STATUS_INVALID_PARAMETER;
4476 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4477 if (!NT_STATUS_IS_OK(status)) {
4481 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) {
4482 return NT_STATUS_PATH_NOT_COVERED;
4485 /* Check the new name has no '/' characters. */
4486 if (strchr_m(newname, '/')) {
4487 return NT_STATUS_NOT_SUPPORTED;
4490 /* Create the base directory. */
4491 pstrcpy(base_name, fname);
4492 p = strrchr_m(base_name, '/');
4496 /* Append the new name. */
4497 pstrcat(base_name, "/");
4498 pstrcat(base_name, newname);
4501 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4502 fsp->fnum, fsp->fsp_name, base_name ));
4503 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4505 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4507 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4513 /****************************************************************************
4514 Deal with SMB_SET_POSIX_ACL.
4515 ****************************************************************************/
4517 #if defined(HAVE_POSIX_ACLS)
4518 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4523 SMB_STRUCT_STAT *psbuf)
4525 uint16 posix_acl_version;
4526 uint16 num_file_acls;
4527 uint16 num_def_acls;
4528 BOOL valid_file_acls = True;
4529 BOOL valid_def_acls = True;
4531 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4532 return NT_STATUS_INVALID_PARAMETER;
4534 posix_acl_version = SVAL(pdata,0);
4535 num_file_acls = SVAL(pdata,2);
4536 num_def_acls = SVAL(pdata,4);
4538 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4539 valid_file_acls = False;
4543 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4544 valid_def_acls = False;
4548 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4549 return NT_STATUS_INVALID_PARAMETER;
4552 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4553 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4554 return NT_STATUS_INVALID_PARAMETER;
4557 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4558 fname ? fname : fsp->fsp_name,
4559 (unsigned int)num_file_acls,
4560 (unsigned int)num_def_acls));
4562 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4563 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4564 return map_nt_error_from_unix(errno);
4567 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4568 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4569 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4570 return map_nt_error_from_unix(errno);
4572 return NT_STATUS_OK;
4576 /****************************************************************************
4577 Deal with SMB_SET_POSIX_LOCK.
4578 ****************************************************************************/
4580 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4588 SMB_BIG_UINT offset;
4590 BOOL blocking_lock = False;
4591 enum brl_type lock_type;
4592 NTSTATUS status = NT_STATUS_OK;
4594 if (fsp == NULL || fsp->fh->fd == -1) {
4595 return NT_STATUS_INVALID_HANDLE;
4598 if (total_data != POSIX_LOCK_DATA_SIZE) {
4599 return NT_STATUS_INVALID_PARAMETER;
4602 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4603 case POSIX_LOCK_TYPE_READ:
4604 lock_type = READ_LOCK;
4606 case POSIX_LOCK_TYPE_WRITE:
4607 /* Return the right POSIX-mappable error code for files opened read-only. */
4608 if (!fsp->can_write) {
4609 return NT_STATUS_INVALID_HANDLE;
4611 lock_type = WRITE_LOCK;
4613 case POSIX_LOCK_TYPE_UNLOCK:
4614 lock_type = UNLOCK_LOCK;
4617 return NT_STATUS_INVALID_PARAMETER;
4620 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4621 blocking_lock = False;
4622 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4623 blocking_lock = True;
4625 return NT_STATUS_INVALID_PARAMETER;
4628 if (!lp_blocking_locks(SNUM(conn))) {
4629 blocking_lock = False;
4632 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4633 #if defined(HAVE_LONGLONG)
4634 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4635 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4636 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4637 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4638 #else /* HAVE_LONGLONG */
4639 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4640 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4641 #endif /* HAVE_LONGLONG */
4643 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4644 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4646 (unsigned int)lock_type,
4647 (unsigned int)lock_pid,
4651 if (lock_type == UNLOCK_LOCK) {
4652 status = do_unlock(fsp,
4658 struct byte_range_lock *br_lck = do_lock(fsp,
4667 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4669 * A blocking lock was requested. Package up
4670 * this smb into a queued request and push it
4671 * onto the blocking lock queue.
4673 if(push_blocking_lock_request(br_lck,
4676 -1, /* infinite timeout. */
4683 TALLOC_FREE(br_lck);
4687 TALLOC_FREE(br_lck);
4693 /****************************************************************************
4694 Deal with SMB_INFO_STANDARD.
4695 ****************************************************************************/
4697 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4702 const SMB_STRUCT_STAT *psbuf)
4704 struct timespec ts[2];
4706 if (total_data < 12) {
4707 return NT_STATUS_INVALID_PARAMETER;
4711 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4713 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4715 DEBUG(10,("smb_set_info_standard: file %s\n",
4716 fname ? fname : fsp->fsp_name ));
4718 return smb_set_file_time(conn,
4725 /****************************************************************************
4726 Deal with SMB_SET_FILE_BASIC_INFO.
4727 ****************************************************************************/
4729 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4734 SMB_STRUCT_STAT *psbuf)
4736 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4737 struct timespec write_time;
4738 struct timespec changed_time;
4740 struct timespec ts[2];
4741 NTSTATUS status = NT_STATUS_OK;
4743 if (total_data < 36) {
4744 return NT_STATUS_INVALID_PARAMETER;
4747 /* Set the attributes */
4748 dosmode = IVAL(pdata,32);
4749 status = smb_set_file_dosmode(conn,
4753 if (!NT_STATUS_IS_OK(status)) {
4757 /* Ignore create time at offset pdata. */
4760 ts[0] = interpret_long_date(pdata+8);
4762 write_time = interpret_long_date(pdata+16);
4763 changed_time = interpret_long_date(pdata+24);
4766 ts[1] = timespec_min(&write_time, &changed_time);
4768 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4772 /* Prefer a defined time to an undefined one. */
4773 if (null_timespec(ts[1])) {
4774 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4777 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4778 fname ? fname : fsp->fsp_name ));
4780 return smb_set_file_time(conn,
4787 /****************************************************************************
4788 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4789 ****************************************************************************/
4791 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4796 SMB_STRUCT_STAT *psbuf)
4798 SMB_BIG_UINT allocation_size = 0;
4799 NTSTATUS status = NT_STATUS_OK;
4800 files_struct *new_fsp = NULL;
4802 if (!VALID_STAT(*psbuf)) {
4803 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4806 if (total_data < 8) {
4807 return NT_STATUS_INVALID_PARAMETER;
4810 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4811 #ifdef LARGE_SMB_OFF_T
4812 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4813 #else /* LARGE_SMB_OFF_T */
4814 if (IVAL(pdata,4) != 0) {
4815 /* more than 32 bits? */
4816 return NT_STATUS_INVALID_PARAMETER;
4818 #endif /* LARGE_SMB_OFF_T */
4820 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4821 fname, (double)allocation_size ));
4823 if (allocation_size) {
4824 allocation_size = smb_roundup(conn, allocation_size);
4827 if(allocation_size == get_file_size(*psbuf)) {
4828 return NT_STATUS_OK;
4831 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4832 fname, (double)allocation_size ));
4834 if (fsp && fsp->fh->fd != -1) {
4835 /* Open file handle. */
4836 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4837 return map_nt_error_from_unix(errno);
4839 return NT_STATUS_OK;
4842 /* Pathname or stat or directory file. */
4844 status = open_file_ntcreate(conn, fname, psbuf,
4846 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4849 FILE_ATTRIBUTE_NORMAL,
4850 FORCE_OPLOCK_BREAK_TO_NONE,
4853 if (!NT_STATUS_IS_OK(status)) {
4854 /* NB. We check for open_was_deferred in the caller. */
4857 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4858 status = map_nt_error_from_unix(errno);
4859 close_file(new_fsp,NORMAL_CLOSE);
4863 close_file(new_fsp,NORMAL_CLOSE);
4864 return NT_STATUS_OK;
4867 /****************************************************************************
4868 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4869 ****************************************************************************/
4871 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4876 SMB_STRUCT_STAT *psbuf)
4880 if (total_data < 8) {
4881 return NT_STATUS_INVALID_PARAMETER;
4884 size = IVAL(pdata,0);
4885 #ifdef LARGE_SMB_OFF_T
4886 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4887 #else /* LARGE_SMB_OFF_T */
4888 if (IVAL(pdata,4) != 0) {
4889 /* more than 32 bits? */
4890 return NT_STATUS_INVALID_PARAMETER;
4892 #endif /* LARGE_SMB_OFF_T */
4893 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4894 "file %s to %.0f\n", fname, (double)size ));
4896 return smb_set_file_size(conn,
4903 /****************************************************************************
4904 Allow a UNIX info mknod.
4905 ****************************************************************************/
4907 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4911 SMB_STRUCT_STAT *psbuf)
4913 uint32 file_type = IVAL(pdata,56);
4914 #if defined(HAVE_MAKEDEV)
4915 uint32 dev_major = IVAL(pdata,60);
4916 uint32 dev_minor = IVAL(pdata,68);
4918 SMB_DEV_T dev = (SMB_DEV_T)0;
4919 uint32 raw_unixmode = IVAL(pdata,84);
4923 if (total_data < 100) {
4924 return NT_STATUS_INVALID_PARAMETER;
4927 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4928 if (!NT_STATUS_IS_OK(status)) {
4932 #if defined(HAVE_MAKEDEV)
4933 dev = makedev(dev_major, dev_minor);
4936 switch (file_type) {
4937 #if defined(S_IFIFO)
4938 case UNIX_TYPE_FIFO:
4939 unixmode |= S_IFIFO;
4942 #if defined(S_IFSOCK)
4943 case UNIX_TYPE_SOCKET:
4944 unixmode |= S_IFSOCK;
4947 #if defined(S_IFCHR)
4948 case UNIX_TYPE_CHARDEV:
4949 unixmode |= S_IFCHR;
4952 #if defined(S_IFBLK)
4953 case UNIX_TYPE_BLKDEV:
4954 unixmode |= S_IFBLK;
4958 return NT_STATUS_INVALID_PARAMETER;
4961 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4962 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
4964 /* Ok - do the mknod. */
4965 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
4966 return map_nt_error_from_unix(errno);
4969 /* If any of the other "set" calls fail we
4970 * don't want to end up with a half-constructed mknod.
4973 if (lp_inherit_perms(SNUM(conn))) {
4975 conn, parent_dirname(fname),
4979 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
4980 status = map_nt_error_from_unix(errno);
4981 SMB_VFS_UNLINK(conn,fname);
4984 return NT_STATUS_OK;
4987 /****************************************************************************
4988 Deal with SMB_SET_FILE_UNIX_BASIC.
4989 ****************************************************************************/
4991 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
4996 SMB_STRUCT_STAT *psbuf)
4998 struct timespec ts[2];
4999 uint32 raw_unixmode;
5002 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5003 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5004 NTSTATUS status = NT_STATUS_OK;
5005 BOOL delete_on_fail = False;
5006 enum perm_type ptype;
5008 if (total_data < 100) {
5009 return NT_STATUS_INVALID_PARAMETER;
5012 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5013 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5014 size=IVAL(pdata,0); /* first 8 Bytes are size */
5015 #ifdef LARGE_SMB_OFF_T
5016 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5017 #else /* LARGE_SMB_OFF_T */
5018 if (IVAL(pdata,4) != 0) {
5019 /* more than 32 bits? */
5020 return NT_STATUS_INVALID_PARAMETER;
5022 #endif /* LARGE_SMB_OFF_T */
5025 ts[0] = interpret_long_date(pdata+24); /* access_time */
5026 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5027 set_owner = (uid_t)IVAL(pdata,40);
5028 set_grp = (gid_t)IVAL(pdata,48);
5029 raw_unixmode = IVAL(pdata,84);
5031 if (VALID_STAT(*psbuf)) {
5032 if (S_ISDIR(psbuf->st_mode)) {
5033 ptype = PERM_EXISTING_DIR;
5035 ptype = PERM_EXISTING_FILE;
5038 ptype = PERM_NEW_FILE;
5041 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5042 if (!NT_STATUS_IS_OK(status)) {
5046 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5047 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5048 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5050 if (!VALID_STAT(*psbuf)) {
5052 * The only valid use of this is to create character and block
5053 * devices, and named pipes. This is deprecated (IMHO) and
5054 * a new info level should be used for mknod. JRA.
5057 status = smb_unix_mknod(conn,
5062 if (!NT_STATUS_IS_OK(status)) {
5066 /* Ensure we don't try and change anything else. */
5067 raw_unixmode = SMB_MODE_NO_CHANGE;
5068 size = get_file_size(*psbuf);
5069 ts[0] = get_atimespec(psbuf);
5070 ts[1] = get_mtimespec(psbuf);
5072 * We continue here as we might want to change the
5075 delete_on_fail = True;
5079 /* Horrible backwards compatibility hack as an old server bug
5080 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5084 size = get_file_size(*psbuf);
5089 * Deal with the UNIX specific mode set.
5092 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5093 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5094 (unsigned int)unixmode, fname ));
5095 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5096 return map_nt_error_from_unix(errno);
5101 * Deal with the UNIX specific uid set.
5104 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5105 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5106 (unsigned int)set_owner, fname ));
5107 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5108 status = map_nt_error_from_unix(errno);
5109 if (delete_on_fail) {
5110 SMB_VFS_UNLINK(conn,fname);
5117 * Deal with the UNIX specific gid set.
5120 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5121 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5122 (unsigned int)set_owner, fname ));
5123 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5124 status = map_nt_error_from_unix(errno);
5125 if (delete_on_fail) {
5126 SMB_VFS_UNLINK(conn,fname);
5132 /* Deal with any size changes. */
5134 status = smb_set_file_size(conn,
5139 if (!NT_STATUS_IS_OK(status)) {
5143 /* Deal with any time changes. */
5145 return smb_set_file_time(conn,
5152 /****************************************************************************
5153 Deal with SMB_SET_FILE_UNIX_INFO2.
5154 ****************************************************************************/
5156 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5161 SMB_STRUCT_STAT *psbuf)
5167 if (total_data < 116) {
5168 return NT_STATUS_INVALID_PARAMETER;
5171 /* Start by setting all the fields that are common between UNIX_BASIC
5174 status = smb_set_file_unix_basic(conn, pdata, total_data,
5176 if (!NT_STATUS_IS_OK(status)) {
5180 smb_fflags = IVAL(pdata, 108);
5181 smb_fmask = IVAL(pdata, 112);
5183 /* NB: We should only attempt to alter the file flags if the client
5184 * sends a non-zero mask.
5186 if (smb_fmask != 0) {
5187 int stat_fflags = 0;
5189 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5191 /* Client asked to alter a flag we don't understand. */
5192 return NT_STATUS_INVALID_PARAMETER;
5195 if (fsp && fsp->fh->fd != -1) {
5196 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5197 return NT_STATUS_NOT_SUPPORTED;
5199 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5200 return map_nt_error_from_unix(errno);
5205 /* XXX: need to add support for changing the create_time here. You
5206 * can do this for paths on Darwin with setattrlist(2). The right way
5207 * to hook this up is probably by extending the VFS utimes interface.
5210 return NT_STATUS_OK;
5213 /****************************************************************************
5214 Create a directory with POSIX semantics.
5215 ****************************************************************************/
5217 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5221 SMB_STRUCT_STAT *psbuf,
5222 int *pdata_return_size)
5224 NTSTATUS status = NT_STATUS_OK;
5225 uint32 raw_unixmode = 0;
5226 uint32 mod_unixmode = 0;
5227 mode_t unixmode = (mode_t)0;
5228 files_struct *fsp = NULL;
5229 uint16 info_level_return = 0;
5231 char *pdata = *ppdata;
5233 if (total_data < 18) {
5234 return NT_STATUS_INVALID_PARAMETER;
5237 raw_unixmode = IVAL(pdata,8);
5238 /* Next 4 bytes are not yet defined. */
5240 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5241 if (!NT_STATUS_IS_OK(status)) {
5245 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5247 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5248 fname, (unsigned int)unixmode ));
5250 status = open_directory(conn,
5253 FILE_READ_ATTRIBUTES, /* Just a stat open */
5254 FILE_SHARE_NONE, /* Ignored for stat opens */
5261 if (NT_STATUS_IS_OK(status)) {
5262 close_file(fsp, NORMAL_CLOSE);
5265 info_level_return = SVAL(pdata,16);
5267 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5268 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5269 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5270 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5272 *pdata_return_size = 12;
5275 /* Realloc the data size */
5276 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5277 if (*ppdata == NULL) {
5278 *pdata_return_size = 0;
5279 return NT_STATUS_NO_MEMORY;
5282 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5283 SSVAL(pdata,2,0); /* No fnum. */
5284 SIVAL(pdata,4,info); /* Was directory created. */
5286 switch (info_level_return) {
5287 case SMB_QUERY_FILE_UNIX_BASIC:
5288 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5289 SSVAL(pdata,10,0); /* Padding. */
5290 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5291 case SMB_QUERY_FILE_UNIX_INFO2:
5292 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5293 SSVAL(pdata,10,0); /* Padding. */
5294 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5296 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5297 SSVAL(pdata,10,0); /* Padding. */
5303 /****************************************************************************
5304 Open/Create a file with POSIX semantics.
5305 ****************************************************************************/
5307 static NTSTATUS smb_posix_open(connection_struct *conn,
5311 SMB_STRUCT_STAT *psbuf,
5312 int *pdata_return_size)
5314 BOOL extended_oplock_granted = False;
5315 char *pdata = *ppdata;
5317 uint32 wire_open_mode = 0;
5318 uint32 raw_unixmode = 0;
5319 uint32 mod_unixmode = 0;
5320 uint32 create_disp = 0;
5321 uint32 access_mask = 0;
5322 uint32 create_options = 0;
5323 NTSTATUS status = NT_STATUS_OK;
5324 mode_t unixmode = (mode_t)0;
5325 files_struct *fsp = NULL;
5326 int oplock_request = 0;
5328 uint16 info_level_return = 0;
5330 if (total_data < 18) {
5331 return NT_STATUS_INVALID_PARAMETER;
5334 flags = IVAL(pdata,0);
5335 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5336 if (oplock_request) {
5337 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5340 wire_open_mode = IVAL(pdata,4);
5342 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5343 return smb_posix_mkdir(conn,
5351 switch (wire_open_mode & SMB_ACCMODE) {
5353 access_mask = FILE_READ_DATA;
5356 access_mask = FILE_WRITE_DATA;
5359 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5362 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5363 (unsigned int)wire_open_mode ));
5364 return NT_STATUS_INVALID_PARAMETER;
5367 wire_open_mode &= ~SMB_ACCMODE;
5369 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5370 create_disp = FILE_CREATE;
5371 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5372 create_disp = FILE_OVERWRITE_IF;
5373 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5374 create_disp = FILE_OPEN_IF;
5376 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5377 (unsigned int)wire_open_mode ));
5378 return NT_STATUS_INVALID_PARAMETER;
5381 raw_unixmode = IVAL(pdata,8);
5382 /* Next 4 bytes are not yet defined. */
5384 status = unix_perms_from_wire(conn,
5387 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5390 if (!NT_STATUS_IS_OK(status)) {
5394 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5396 if (wire_open_mode & SMB_O_SYNC) {
5397 create_options |= FILE_WRITE_THROUGH;
5399 if (wire_open_mode & SMB_O_APPEND) {
5400 access_mask |= FILE_APPEND_DATA;
5402 if (wire_open_mode & SMB_O_DIRECT) {
5403 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5406 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5408 (unsigned int)wire_open_mode,
5409 (unsigned int)unixmode ));
5411 status = open_file_ntcreate(conn,
5415 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5417 0, /* no create options yet. */
5423 if (!NT_STATUS_IS_OK(status)) {
5427 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5428 extended_oplock_granted = True;
5431 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5432 extended_oplock_granted = True;
5435 info_level_return = SVAL(pdata,16);
5437 /* Allocate the correct return size. */
5439 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5440 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5441 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5442 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5444 *pdata_return_size = 12;
5447 /* Realloc the data size */
5448 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5449 if (*ppdata == NULL) {
5450 close_file(fsp,ERROR_CLOSE);
5451 *pdata_return_size = 0;
5452 return NT_STATUS_NO_MEMORY;
5455 if (extended_oplock_granted) {
5456 if (flags & REQUEST_BATCH_OPLOCK) {
5457 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5459 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5461 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5462 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5464 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5467 SSVAL(pdata,2,fsp->fnum);
5468 SIVAL(pdata,4,info); /* Was file created etc. */
5470 switch (info_level_return) {
5471 case SMB_QUERY_FILE_UNIX_BASIC:
5472 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5473 SSVAL(pdata,10,0); /* padding. */
5474 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5475 case SMB_QUERY_FILE_UNIX_INFO2:
5476 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5477 SSVAL(pdata,10,0); /* padding. */
5478 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5480 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5481 SSVAL(pdata,10,0); /* padding. */
5483 return NT_STATUS_OK;
5486 /****************************************************************************
5487 Delete a file with POSIX semantics.
5488 ****************************************************************************/
5490 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5494 SMB_STRUCT_STAT *psbuf)
5496 NTSTATUS status = NT_STATUS_OK;
5497 files_struct *fsp = NULL;
5501 if (total_data < 2) {
5502 return NT_STATUS_INVALID_PARAMETER;
5505 flags = SVAL(pdata,0);
5507 if (!VALID_STAT(*psbuf)) {
5508 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5511 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5512 !VALID_STAT_OF_DIR(*psbuf)) {
5513 return NT_STATUS_NOT_A_DIRECTORY;
5516 DEBUG(10,("smb_posix_unlink: %s %s\n",
5517 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5520 if (VALID_STAT_OF_DIR(*psbuf)) {
5521 status = open_directory(conn,
5525 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5527 FILE_DELETE_ON_CLOSE,
5528 FILE_FLAG_POSIX_SEMANTICS|0777,
5534 status = open_file_ntcreate(conn,
5538 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5541 FILE_FLAG_POSIX_SEMANTICS|0777,
5542 0, /* No oplock, but break existing ones. */
5546 * For file opens we must set the delete on close
5550 if (!NT_STATUS_IS_OK(status)) {
5554 status = smb_set_file_disposition_info(conn,
5562 if (!NT_STATUS_IS_OK(status)) {
5565 return close_file(fsp, NORMAL_CLOSE);
5568 /****************************************************************************
5569 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5570 ****************************************************************************/
5572 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5573 unsigned int tran_call,
5574 char **pparams, int total_params, char **ppdata, int total_data,
5575 unsigned int max_data_bytes)
5577 char *params = *pparams;
5578 char *pdata = *ppdata;
5580 SMB_STRUCT_STAT sbuf;
5582 files_struct *fsp = NULL;
5583 NTSTATUS status = NT_STATUS_OK;
5584 int data_return_size = 0;
5587 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5592 if (tran_call == TRANSACT2_SETFILEINFO) {
5593 if (total_params < 4) {
5594 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5597 fsp = file_fsp(params,0);
5598 info_level = SVAL(params,2);
5600 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5602 * This is actually a SETFILEINFO on a directory
5603 * handle (returned from an NT SMB). NT5.0 seems
5604 * to do this call. JRA.
5606 pstrcpy(fname, fsp->fsp_name);
5607 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5608 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5609 return UNIXERROR(ERRDOS,ERRbadpath);
5611 } else if (fsp && fsp->print_file) {
5613 * Doing a DELETE_ON_CLOSE should cancel a print job.
5615 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5616 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5618 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5621 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5624 return (UNIXERROR(ERRDOS,ERRbadpath));
5627 * Original code - this is an open file.
5629 CHECK_FSP(fsp,conn);
5631 pstrcpy(fname, fsp->fsp_name);
5633 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5634 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5635 return(UNIXERROR(ERRDOS,ERRbadfid));
5640 if (total_params < 7) {
5641 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5644 info_level = SVAL(params,0);
5645 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5646 if (!NT_STATUS_IS_OK(status)) {
5647 return ERROR_NT(status);
5650 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
5651 ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5654 status = unix_convert(conn, fname, False, NULL, &sbuf);
5655 if (!NT_STATUS_IS_OK(status)) {
5656 return ERROR_NT(status);
5659 status = check_name(conn, fname);
5660 if (!NT_STATUS_IS_OK(status)) {
5661 return ERROR_NT(status);
5665 * For CIFS UNIX extensions the target name may not exist.
5668 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5669 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5670 return UNIXERROR(ERRDOS,ERRbadpath);
5674 if (!CAN_WRITE(conn)) {
5675 return ERROR_DOS(ERRSRV,ERRaccess);
5678 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5679 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5682 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5683 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5685 /* Realloc the parameter size */
5686 *pparams = (char *)SMB_REALLOC(*pparams,2);
5687 if (*pparams == NULL) {
5688 return ERROR_NT(NT_STATUS_NO_MEMORY);
5694 if (fsp && !null_timespec(fsp->pending_modtime)) {
5695 /* the pending modtime overrides the current modtime */
5696 set_mtimespec(&sbuf, fsp->pending_modtime);
5699 switch (info_level) {
5701 case SMB_INFO_STANDARD:
5703 status = smb_set_info_standard(conn,
5712 case SMB_INFO_SET_EA:
5714 status = smb_info_set_ea(conn,
5722 case SMB_SET_FILE_BASIC_INFO:
5723 case SMB_FILE_BASIC_INFORMATION:
5725 status = smb_set_file_basic_info(conn,
5734 case SMB_FILE_ALLOCATION_INFORMATION:
5735 case SMB_SET_FILE_ALLOCATION_INFO:
5737 status = smb_set_file_allocation_info(conn,
5746 case SMB_FILE_END_OF_FILE_INFORMATION:
5747 case SMB_SET_FILE_END_OF_FILE_INFO:
5749 status = smb_set_file_end_of_file_info(conn,
5758 case SMB_FILE_DISPOSITION_INFORMATION:
5759 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5762 /* JRA - We used to just ignore this on a path ?
5763 * Shouldn't this be invalid level on a pathname
5766 if (tran_call != TRANSACT2_SETFILEINFO) {
5767 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5770 status = smb_set_file_disposition_info(conn,
5779 case SMB_FILE_POSITION_INFORMATION:
5781 status = smb_file_position_information(conn,
5788 /* From tridge Samba4 :
5789 * MODE_INFORMATION in setfileinfo (I have no
5790 * idea what "mode information" on a file is - it takes a value of 0,
5791 * 2, 4 or 6. What could it be?).
5794 case SMB_FILE_MODE_INFORMATION:
5796 status = smb_file_mode_information(conn,
5803 * CIFS UNIX extensions.
5806 case SMB_SET_FILE_UNIX_BASIC:
5808 status = smb_set_file_unix_basic(conn,
5817 case SMB_SET_FILE_UNIX_INFO2:
5819 status = smb_set_file_unix_info2(conn,
5828 case SMB_SET_FILE_UNIX_LINK:
5830 if (tran_call != TRANSACT2_SETPATHINFO) {
5831 /* We must have a pathname for this. */
5832 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5834 status = smb_set_file_unix_link(conn,
5842 case SMB_SET_FILE_UNIX_HLINK:
5844 if (tran_call != TRANSACT2_SETPATHINFO) {
5845 /* We must have a pathname for this. */
5846 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5848 status = smb_set_file_unix_hlink(conn,
5857 case SMB_FILE_RENAME_INFORMATION:
5859 status = smb_file_rename_information(conn,
5869 #if defined(HAVE_POSIX_ACLS)
5870 case SMB_SET_POSIX_ACL:
5872 status = smb_set_posix_acl(conn,
5882 case SMB_SET_POSIX_LOCK:
5884 if (tran_call != TRANSACT2_SETFILEINFO) {
5885 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5887 status = smb_set_posix_lock(conn,
5896 case SMB_POSIX_PATH_OPEN:
5898 if (tran_call != TRANSACT2_SETPATHINFO) {
5899 /* We must have a pathname for this. */
5900 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5903 status = smb_posix_open(conn,
5912 case SMB_POSIX_PATH_UNLINK:
5914 if (tran_call != TRANSACT2_SETPATHINFO) {
5915 /* We must have a pathname for this. */
5916 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5919 status = smb_posix_unlink(conn,
5928 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5932 if (!NT_STATUS_IS_OK(status)) {
5933 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5934 /* We have re-scheduled this call. */
5937 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5938 /* We have re-scheduled this call. */
5941 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5942 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5944 return ERROR_NT(status);
5948 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
5953 /****************************************************************************
5954 Reply to a TRANS2_MKDIR (make directory with extended attributes).
5955 ****************************************************************************/
5957 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5958 char **pparams, int total_params, char **ppdata, int total_data,
5959 unsigned int max_data_bytes)
5961 char *params = *pparams;
5962 char *pdata = *ppdata;
5964 SMB_STRUCT_STAT sbuf;
5965 NTSTATUS status = NT_STATUS_OK;
5966 struct ea_list *ea_list = NULL;
5968 if (!CAN_WRITE(conn))
5969 return ERROR_DOS(ERRSRV,ERRaccess);
5971 if (total_params < 5) {
5972 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5975 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
5976 if (!NT_STATUS_IS_OK(status)) {
5977 return ERROR_NT(status);
5980 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
5982 status = unix_convert(conn, directory, False, NULL, &sbuf);
5983 if (!NT_STATUS_IS_OK(status)) {
5984 return ERROR_NT(status);
5987 status = check_name(conn, directory);
5988 if (!NT_STATUS_IS_OK(status)) {
5989 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5990 return ERROR_NT(status);
5993 /* Any data in this call is an EA list. */
5994 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5995 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5999 * OS/2 workplace shell seems to send SET_EA requests of "null"
6000 * length (4 bytes containing IVAL 4).
6001 * They seem to have no effect. Bug #3212. JRA.
6004 if (total_data != 4) {
6005 if (total_data < 10) {
6006 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6009 if (IVAL(pdata,0) > total_data) {
6010 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6011 IVAL(pdata,0), (unsigned int)total_data));
6012 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6015 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6018 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6020 } else if (IVAL(pdata,0) != 4) {
6021 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6024 status = create_directory(conn, directory);
6026 if (!NT_STATUS_IS_OK(status)) {
6027 return ERROR_NT(status);
6030 /* Try and set any given EA. */
6032 status = set_ea(conn, NULL, directory, ea_list);
6033 if (!NT_STATUS_IS_OK(status)) {
6034 return ERROR_NT(status);
6038 /* Realloc the parameter and data sizes */
6039 *pparams = (char *)SMB_REALLOC(*pparams,2);
6040 if(*pparams == NULL) {
6041 return ERROR_NT(NT_STATUS_NO_MEMORY);
6047 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6052 /****************************************************************************
6053 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6054 We don't actually do this - we just send a null response.
6055 ****************************************************************************/
6057 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6058 char **pparams, int total_params, char **ppdata, int total_data,
6059 unsigned int max_data_bytes)
6061 static uint16 fnf_handle = 257;
6062 char *params = *pparams;
6065 if (total_params < 6) {
6066 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6069 info_level = SVAL(params,4);
6070 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6072 switch (info_level) {
6077 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6080 /* Realloc the parameter and data sizes */
6081 *pparams = (char *)SMB_REALLOC(*pparams,6);
6082 if (*pparams == NULL) {
6083 return ERROR_NT(NT_STATUS_NO_MEMORY);
6087 SSVAL(params,0,fnf_handle);
6088 SSVAL(params,2,0); /* No changes */
6089 SSVAL(params,4,0); /* No EA errors */
6096 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6101 /****************************************************************************
6102 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6103 changes). Currently this does nothing.
6104 ****************************************************************************/
6106 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6107 char **pparams, int total_params, char **ppdata, int total_data,
6108 unsigned int max_data_bytes)
6110 char *params = *pparams;
6112 DEBUG(3,("call_trans2findnotifynext\n"));
6114 /* Realloc the parameter and data sizes */
6115 *pparams = (char *)SMB_REALLOC(*pparams,4);
6116 if (*pparams == NULL) {
6117 return ERROR_NT(NT_STATUS_NO_MEMORY);
6121 SSVAL(params,0,0); /* No changes */
6122 SSVAL(params,2,0); /* No EA errors */
6124 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6129 /****************************************************************************
6130 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6131 ****************************************************************************/
6133 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6134 char **pparams, int total_params, char **ppdata, int total_data,
6135 unsigned int max_data_bytes)
6137 char *params = *pparams;
6140 int max_referral_level;
6142 DEBUG(10,("call_trans2getdfsreferral\n"));
6144 if (total_params < 3) {
6145 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6148 max_referral_level = SVAL(params,0);
6150 if(!lp_host_msdfs())
6151 return ERROR_DOS(ERRDOS,ERRbadfunc);
6153 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6154 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
6155 return UNIXERROR(ERRDOS,ERRbadfile);
6157 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6158 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6163 #define LMCAT_SPL 0x53
6164 #define LMFUNC_GETJOBID 0x60
6166 /****************************************************************************
6167 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6168 ****************************************************************************/
6170 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6171 char **pparams, int total_params, char **ppdata, int total_data,
6172 unsigned int max_data_bytes)
6174 char *pdata = *ppdata;
6175 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6177 /* check for an invalid fid before proceeding */
6180 return(ERROR_DOS(ERRDOS,ERRbadfid));
6182 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6183 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6184 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6185 if (*ppdata == NULL) {
6186 return ERROR_NT(NT_STATUS_NO_MEMORY);
6190 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6191 CAN ACCEPT THIS IN UNICODE. JRA. */
6193 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6194 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6195 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6196 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6199 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6200 return ERROR_DOS(ERRSRV,ERRerror);
6204 /****************************************************************************
6205 Reply to a SMBfindclose (stop trans2 directory search).
6206 ****************************************************************************/
6208 int reply_findclose(connection_struct *conn,
6209 char *inbuf,char *outbuf,int length,int bufsize)
6212 int dptr_num=SVALS(inbuf,smb_vwv0);
6213 START_PROFILE(SMBfindclose);
6215 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6217 dptr_close(&dptr_num);
6219 outsize = set_message(outbuf,0,0,False);
6221 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6223 END_PROFILE(SMBfindclose);
6227 /****************************************************************************
6228 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6229 ****************************************************************************/
6231 int reply_findnclose(connection_struct *conn,
6232 char *inbuf,char *outbuf,int length,int bufsize)
6236 START_PROFILE(SMBfindnclose);
6238 dptr_num = SVAL(inbuf,smb_vwv0);
6240 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6242 /* We never give out valid handles for a
6243 findnotifyfirst - so any dptr_num is ok here.
6246 outsize = set_message(outbuf,0,0,False);
6248 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6250 END_PROFILE(SMBfindnclose);
6254 int handle_trans2(connection_struct *conn,
6255 struct trans_state *state,
6256 char *inbuf, char *outbuf, int size, int bufsize)
6260 if (Protocol >= PROTOCOL_NT1) {
6261 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6264 /* Now we must call the relevant TRANS2 function */
6265 switch(state->call) {
6266 case TRANSACT2_OPEN:
6268 START_PROFILE(Trans2_open);
6269 outsize = call_trans2open(
6270 conn, inbuf, outbuf, bufsize,
6271 &state->param, state->total_param,
6272 &state->data, state->total_data,
6273 state->max_data_return);
6274 END_PROFILE(Trans2_open);
6278 case TRANSACT2_FINDFIRST:
6280 START_PROFILE(Trans2_findfirst);
6281 outsize = call_trans2findfirst(
6282 conn, inbuf, outbuf, bufsize,
6283 &state->param, state->total_param,
6284 &state->data, state->total_data,
6285 state->max_data_return);
6286 END_PROFILE(Trans2_findfirst);
6290 case TRANSACT2_FINDNEXT:
6292 START_PROFILE(Trans2_findnext);
6293 outsize = call_trans2findnext(
6294 conn, inbuf, outbuf, size, bufsize,
6295 &state->param, state->total_param,
6296 &state->data, state->total_data,
6297 state->max_data_return);
6298 END_PROFILE(Trans2_findnext);
6302 case TRANSACT2_QFSINFO:
6304 START_PROFILE(Trans2_qfsinfo);
6305 outsize = call_trans2qfsinfo(
6306 conn, inbuf, outbuf, size, bufsize,
6307 &state->param, state->total_param,
6308 &state->data, state->total_data,
6309 state->max_data_return);
6310 END_PROFILE(Trans2_qfsinfo);
6314 case TRANSACT2_SETFSINFO:
6316 START_PROFILE(Trans2_setfsinfo);
6317 outsize = call_trans2setfsinfo(
6318 conn, inbuf, outbuf, size, bufsize,
6319 &state->param, state->total_param,
6320 &state->data, state->total_data,
6321 state->max_data_return);
6322 END_PROFILE(Trans2_setfsinfo);
6326 case TRANSACT2_QPATHINFO:
6327 case TRANSACT2_QFILEINFO:
6329 START_PROFILE(Trans2_qpathinfo);
6330 outsize = call_trans2qfilepathinfo(
6331 conn, inbuf, outbuf, size, bufsize, state->call,
6332 &state->param, state->total_param,
6333 &state->data, state->total_data,
6334 state->max_data_return);
6335 END_PROFILE(Trans2_qpathinfo);
6339 case TRANSACT2_SETPATHINFO:
6340 case TRANSACT2_SETFILEINFO:
6342 START_PROFILE(Trans2_setpathinfo);
6343 outsize = call_trans2setfilepathinfo(
6344 conn, inbuf, outbuf, size, bufsize, state->call,
6345 &state->param, state->total_param,
6346 &state->data, state->total_data,
6347 state->max_data_return);
6348 END_PROFILE(Trans2_setpathinfo);
6352 case TRANSACT2_FINDNOTIFYFIRST:
6354 START_PROFILE(Trans2_findnotifyfirst);
6355 outsize = call_trans2findnotifyfirst(
6356 conn, inbuf, outbuf, size, bufsize,
6357 &state->param, state->total_param,
6358 &state->data, state->total_data,
6359 state->max_data_return);
6360 END_PROFILE(Trans2_findnotifyfirst);
6364 case TRANSACT2_FINDNOTIFYNEXT:
6366 START_PROFILE(Trans2_findnotifynext);
6367 outsize = call_trans2findnotifynext(
6368 conn, inbuf, outbuf, size, bufsize,
6369 &state->param, state->total_param,
6370 &state->data, state->total_data,
6371 state->max_data_return);
6372 END_PROFILE(Trans2_findnotifynext);
6376 case TRANSACT2_MKDIR:
6378 START_PROFILE(Trans2_mkdir);
6379 outsize = call_trans2mkdir(
6380 conn, inbuf, outbuf, size, bufsize,
6381 &state->param, state->total_param,
6382 &state->data, state->total_data,
6383 state->max_data_return);
6384 END_PROFILE(Trans2_mkdir);
6388 case TRANSACT2_GET_DFS_REFERRAL:
6390 START_PROFILE(Trans2_get_dfs_referral);
6391 outsize = call_trans2getdfsreferral(
6392 conn, inbuf, outbuf, size, bufsize,
6393 &state->param, state->total_param,
6394 &state->data, state->total_data,
6395 state->max_data_return);
6396 END_PROFILE(Trans2_get_dfs_referral);
6400 case TRANSACT2_IOCTL:
6402 START_PROFILE(Trans2_ioctl);
6403 outsize = call_trans2ioctl(
6404 conn, inbuf, outbuf, size, bufsize,
6405 &state->param, state->total_param,
6406 &state->data, state->total_data,
6407 state->max_data_return);
6408 END_PROFILE(Trans2_ioctl);
6413 /* Error in request */
6414 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6415 outsize = ERROR_DOS(ERRSRV,ERRerror);
6421 /****************************************************************************
6422 Reply to a SMBtrans2.
6423 ****************************************************************************/
6425 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6426 int size, int bufsize)
6429 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6430 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6431 unsigned int psoff = SVAL(inbuf, smb_psoff);
6432 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6433 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6434 struct trans_state *state;
6437 START_PROFILE(SMBtrans2);
6439 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6440 if (!NT_STATUS_IS_OK(result)) {
6441 DEBUG(2, ("Got invalid trans2 request: %s\n",
6442 nt_errstr(result)));
6443 END_PROFILE(SMBtrans2);
6444 return ERROR_NT(result);
6447 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6448 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6449 END_PROFILE(SMBtrans2);
6450 return ERROR_DOS(ERRSRV,ERRaccess);
6453 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6454 DEBUG(0, ("talloc failed\n"));
6455 END_PROFILE(SMBtrans2);
6456 return ERROR_NT(NT_STATUS_NO_MEMORY);
6459 state->cmd = SMBtrans2;
6461 state->mid = SVAL(inbuf, smb_mid);
6462 state->vuid = SVAL(inbuf, smb_uid);
6463 state->setup_count = SVAL(inbuf, smb_suwcnt);
6464 state->setup = NULL;
6465 state->total_param = SVAL(inbuf, smb_tpscnt);
6466 state->param = NULL;
6467 state->total_data = SVAL(inbuf, smb_tdscnt);
6469 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6470 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6471 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6472 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6473 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6475 state->call = tran_call;
6477 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6478 is so as a sanity check */
6479 if (state->setup_count != 1) {
6481 * Need to have rc=0 for ioctl to get job id for OS/2.
6482 * Network printing will fail if function is not successful.
6483 * Similar function in reply.c will be used if protocol
6484 * is LANMAN1.0 instead of LM1.2X002.
6485 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6486 * outbuf doesn't have to be set(only job id is used).
6488 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6489 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6490 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6491 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6493 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6494 DEBUG(2,("Transaction is %d\n",tran_call));
6496 END_PROFILE(SMBtrans2);
6497 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6501 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6504 if (state->total_data) {
6505 /* Can't use talloc here, the core routines do realloc on the
6506 * params and data. */
6507 state->data = (char *)SMB_MALLOC(state->total_data);
6508 if (state->data == NULL) {
6509 DEBUG(0,("reply_trans2: data malloc fail for %u "
6510 "bytes !\n", (unsigned int)state->total_data));
6512 END_PROFILE(SMBtrans2);
6513 return(ERROR_DOS(ERRDOS,ERRnomem));
6515 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6517 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6518 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6521 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6524 if (state->total_param) {
6525 /* Can't use talloc here, the core routines do realloc on the
6526 * params and data. */
6527 state->param = (char *)SMB_MALLOC(state->total_param);
6528 if (state->param == NULL) {
6529 DEBUG(0,("reply_trans: param malloc fail for %u "
6530 "bytes !\n", (unsigned int)state->total_param));
6531 SAFE_FREE(state->data);
6533 END_PROFILE(SMBtrans2);
6534 return(ERROR_DOS(ERRDOS,ERRnomem));
6536 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6538 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6539 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6542 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6545 state->received_data = dscnt;
6546 state->received_param = pscnt;
6548 if ((state->received_param == state->total_param) &&
6549 (state->received_data == state->total_data)) {
6551 outsize = handle_trans2(conn, state, inbuf, outbuf,
6553 SAFE_FREE(state->data);
6554 SAFE_FREE(state->param);
6556 END_PROFILE(SMBtrans2);
6560 DLIST_ADD(conn->pending_trans, state);
6562 /* We need to send an interim response then receive the rest
6563 of the parameter/data bytes */
6564 outsize = set_message(outbuf,0,0,False);
6566 END_PROFILE(SMBtrans2);
6571 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6572 SAFE_FREE(state->data);
6573 SAFE_FREE(state->param);
6575 END_PROFILE(SMBtrans2);
6576 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6580 /****************************************************************************
6581 Reply to a SMBtranss2
6582 ****************************************************************************/
6584 int reply_transs2(connection_struct *conn,
6585 char *inbuf,char *outbuf,int size,int bufsize)
6588 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6589 struct trans_state *state;
6591 START_PROFILE(SMBtranss2);
6595 for (state = conn->pending_trans; state != NULL;
6596 state = state->next) {
6597 if (state->mid == SVAL(inbuf,smb_mid)) {
6602 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6603 END_PROFILE(SMBtranss2);
6604 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6607 /* Revise state->total_param and state->total_data in case they have
6608 changed downwards */
6610 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6611 state->total_param = SVAL(inbuf, smb_tpscnt);
6612 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6613 state->total_data = SVAL(inbuf, smb_tdscnt);
6615 pcnt = SVAL(inbuf, smb_spscnt);
6616 poff = SVAL(inbuf, smb_spsoff);
6617 pdisp = SVAL(inbuf, smb_spsdisp);
6619 dcnt = SVAL(inbuf, smb_sdscnt);
6620 doff = SVAL(inbuf, smb_sdsoff);
6621 ddisp = SVAL(inbuf, smb_sdsdisp);
6623 state->received_param += pcnt;
6624 state->received_data += dcnt;
6626 if ((state->received_data > state->total_data) ||
6627 (state->received_param > state->total_param))
6631 if (pdisp+pcnt > state->total_param)
6633 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6635 if (pdisp > state->total_param)
6637 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6638 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6640 if (state->param + pdisp < state->param)
6643 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6648 if (ddisp+dcnt > state->total_data)
6650 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6652 if (ddisp > state->total_data)
6654 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6655 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6657 if (state->data + ddisp < state->data)
6660 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6664 if ((state->received_param < state->total_param) ||
6665 (state->received_data < state->total_data)) {
6666 END_PROFILE(SMBtranss2);
6670 /* construct_reply_common has done us the favor to pre-fill the
6671 * command field with SMBtranss2 which is wrong :-)
6673 SCVAL(outbuf,smb_com,SMBtrans2);
6675 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6677 DLIST_REMOVE(conn->pending_trans, state);
6678 SAFE_FREE(state->data);
6679 SAFE_FREE(state->param);
6683 END_PROFILE(SMBtranss2);
6684 return(ERROR_DOS(ERRSRV,ERRnosupport));
6687 END_PROFILE(SMBtranss2);
6692 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6693 DLIST_REMOVE(conn->pending_trans, state);
6694 SAFE_FREE(state->data);
6695 SAFE_FREE(state->param);
6697 END_PROFILE(SMBtranss2);
6698 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);