2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct *conn,
41 const SMB_STRUCT_STAT *psbuf);
43 static char *store_file_unix_basic_info2(connection_struct *conn,
46 const SMB_STRUCT_STAT *psbuf);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
55 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type = get_remote_arch();
59 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60 val = SMB_ROUNDUP(val,rval);
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
68 ********************************************************************/
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
74 if(S_ISDIR(sbuf->st_mode)) {
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
81 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
84 if (fsp && fsp->initial_allocation_size)
85 ret = MAX(ret,fsp->initial_allocation_size);
87 return smb_roundup(conn, ret);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120 const char *fname, char *ea_name, struct ea_struct *pea)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size = 256;
129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 if (fsp && fsp->fh->fd != -1) {
135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150 dump_data(10, (uint8 *)val, sizeret);
153 if (strnequal(ea_name, "user.", 5)) {
154 pea->name = &ea_name[5];
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168 const char *fname, size_t *pea_total_len)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size = 1024;
176 struct ea_list *ea_list_head = NULL;
180 if (!lp_ea_support(SNUM(conn))) {
184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
191 if (fsp && fsp->fh->fd != -1) {
192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
197 if (sizeret == -1 && errno == ERANGE) {
198 ea_namelist_size *= 2;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211 struct ea_list *listp;
213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
216 listp = TALLOC_P(mem_ctx, struct ea_list);
220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
226 push_ascii_fstring(dos_ea_name, listp->ea.name);
227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len, dos_ea_name,
230 (unsigned int)listp->ea.value.length ));
232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
234 /* Add on 4 for total length. */
235 if (*pea_total_len) {
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250 connection_struct *conn, struct ea_list *ea_list)
252 unsigned int ret_data_size = 4;
255 SMB_ASSERT(total_data_size >= 4);
257 if (!lp_ea_support(SNUM(conn))) {
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
270 if (ea_list->ea.value.length > 65535) {
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290 SIVAL(pdata,0,ret_data_size);
291 return ret_data_size;
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
296 size_t total_ea_len = 0;
297 TALLOC_CTX *mem_ctx = NULL;
299 if (!lp_ea_support(SNUM(conn))) {
302 mem_ctx = talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304 talloc_destroy(mem_ctx);
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
318 for (; ea_list; ea_list = ea_list->next) {
319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name[5], ea_list->ea.name));
322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
326 talloc_destroy(mem_ctx);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
335 if (!lp_ea_support(SNUM(conn))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED;
339 for (;ea_list; ea_list = ea_list->next) {
341 fstring unix_ea_name;
343 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name, ea_list->ea.name);
346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
350 if (samba_private_attr_name(unix_ea_name)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352 return NT_STATUS_ACCESS_DENIED;
355 if (ea_list->ea.value.length == 0) {
356 /* Remove the attribute. */
357 if (fsp && (fsp->fh->fd != -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name, fsp->fsp_name));
360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name, fname));
364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
367 /* Removing a non existent attribute always succeeds. */
368 if (ret == -1 && errno == ENOATTR) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
375 if (fsp && (fsp->fh->fd != -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name, fsp->fsp_name));
378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name, fname));
383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
390 if (errno == ENOTSUP) {
391 return NT_STATUS_EAS_NOT_SUPPORTED;
394 return map_nt_error_from_unix(errno);
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
406 struct ea_list *ea_list_head = NULL;
409 while (offset + 2 < data_size) {
410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411 unsigned int namelen = CVAL(pdata,offset);
413 offset++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417 (offset > data_size) || (namelen > data_size) ||
418 (offset + namelen >= data_size)) {
421 /* Ensure the name is null terminated. */
422 if (pdata[offset + namelen] != '\0') {
425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
430 offset += (namelen + 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
446 unsigned int namelen;
456 eal->ea.flags = CVAL(pdata,0);
457 namelen = CVAL(pdata,1);
458 val_len = SVAL(pdata,2);
460 if (4 + namelen + 1 + val_len > data_size) {
464 /* Ensure the name is null terminated. */
465 if (pdata[namelen + 4] != '\0') {
468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474 if (!eal->ea.value.data) {
478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal->ea.value.data[val_len] = '\0';
482 /* But don't count the null. */
483 eal->ea.value.length--;
486 *pbytes_used = 4 + namelen + 1 + val_len;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490 dump_data(10, eal->ea.value.data, eal->ea.value.length);
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
501 struct ea_list *ea_list_head = NULL;
503 size_t bytes_used = 0;
505 while (offset < data_size) {
506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513 offset += bytes_used;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list *ealist)
526 struct ea_list *listp;
529 for (listp = ealist; listp; listp = listp->next) {
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 /* Add on 4 for total length. */
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
549 struct ea_list *nlistp, *flistp;
551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552 for (flistp = file_list; flistp; flistp = flistp->next) {
553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
559 /* Copy the data from this entry. */
560 nlistp->ea.flags = flistp->ea.flags;
561 nlistp->ea.value = flistp->ea.value;
564 nlistp->ea.flags = 0;
565 ZERO_STRUCT(nlistp->ea.value);
569 *total_ea_len = ea_list_size(name_list);
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(char *outbuf,
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
738 /****************************************************************************
739 Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
742 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
743 char **pparams, int total_params, char **ppdata, int total_data,
744 unsigned int max_data_bytes)
746 char *params = *pparams;
747 char *pdata = *ppdata;
752 BOOL return_additional_info;
763 SMB_STRUCT_STAT sbuf;
766 struct ea_list *ea_list = NULL;
771 uint32 create_disposition;
772 uint32 create_options = 0;
775 * Ensure we have enough parameters to perform the operation.
778 if (total_params < 29) {
779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
782 flags = SVAL(params, 0);
783 deny_mode = SVAL(params, 2);
784 open_attr = SVAL(params,6);
785 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
786 if (oplock_request) {
787 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
791 return_additional_info = BITSETW(params,0);
792 open_sattr = SVAL(params, 4);
793 open_time = make_unix_date3(params+8);
795 open_ofun = SVAL(params,12);
796 open_size = IVAL(params,14);
800 return(ERROR_DOS(ERRSRV,ERRaccess));
803 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
809 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
810 (unsigned int)open_ofun, open_size));
812 /* XXXX we need to handle passed times, sattr and flags */
814 status = unix_convert(conn, fname, False, NULL, &sbuf);
815 if (!NT_STATUS_IS_OK(status)) {
816 return ERROR_NT(status);
819 status = check_name(conn, fname);
820 if (!NT_STATUS_IS_OK(status)) {
821 return ERROR_NT(status);
824 if (open_ofun == 0) {
825 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
828 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
833 return ERROR_DOS(ERRDOS, ERRbadaccess);
836 /* Any data in this call is an EA list. */
837 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
838 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
841 if (total_data != 4) {
842 if (total_data < 10) {
843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 if (IVAL(pdata,0) > total_data) {
847 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
848 IVAL(pdata,0), (unsigned int)total_data));
849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
852 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
857 } else if (IVAL(pdata,0) != 4) {
858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
861 status = open_file_ntcreate(conn,fname,&sbuf,
870 if (!NT_STATUS_IS_OK(status)) {
871 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
872 /* We have re-scheduled this call. */
875 return ERROR_NT(status);
878 size = get_file_size(sbuf);
879 fattr = dos_mode(conn,fname,&sbuf);
880 mtime = sbuf.st_mtime;
883 close_file(fsp,ERROR_CLOSE);
884 return(ERROR_DOS(ERRDOS,ERRnoaccess));
887 /* Save the requested allocation size. */
888 /* Allocate space for the file if a size hint is supplied */
889 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
890 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
891 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
892 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
893 if (fsp->is_directory) {
894 close_file(fsp,ERROR_CLOSE);
895 /* Can't set allocation size on a directory. */
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
898 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
899 close_file(fsp,ERROR_CLOSE);
900 return ERROR_NT(NT_STATUS_DISK_FULL);
903 /* Adjust size here to return the right size in the reply.
904 Windows does it this way. */
905 size = fsp->initial_allocation_size;
907 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
911 if (ea_list && smb_action == FILE_WAS_CREATED) {
912 status = set_ea(conn, fsp, fname, ea_list);
913 if (!NT_STATUS_IS_OK(status)) {
914 close_file(fsp,ERROR_CLOSE);
915 return ERROR_NT(status);
919 /* Realloc the size of parameters and data we will return */
920 *pparams = (char *)SMB_REALLOC(*pparams, 30);
921 if(*pparams == NULL ) {
922 return ERROR_NT(NT_STATUS_NO_MEMORY);
926 SSVAL(params,0,fsp->fnum);
927 SSVAL(params,2,fattr);
928 srv_put_dos_date2(params,4, mtime);
929 SIVAL(params,8, (uint32)size);
930 SSVAL(params,12,deny_mode);
931 SSVAL(params,14,0); /* open_type - file or directory. */
932 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
934 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
935 smb_action |= EXTENDED_OPLOCK_GRANTED;
938 SSVAL(params,18,smb_action);
941 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
943 SIVAL(params,20,inode);
944 SSVAL(params,24,0); /* Padding. */
946 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
947 SIVAL(params, 26, ea_size);
949 SIVAL(params, 26, 0);
952 /* Send the required number of replies */
953 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
958 /*********************************************************
959 Routine to check if a given string matches exactly.
960 as a special case a mask of "." does NOT match. That
961 is required for correct wildcard semantics
962 Case can be significant or not.
963 **********************************************************/
965 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
967 if (mask[0] == '.' && mask[1] == 0)
969 if (conn->case_sensitive)
970 return strcmp(str,mask)==0;
971 if (StrCaseCmp(str,mask) != 0) {
974 if (dptr_has_wild(conn->dirptr)) {
980 /****************************************************************************
981 Return the filetype for UNIX extensions.
982 ****************************************************************************/
984 static uint32 unix_filetype(mode_t mode)
987 return UNIX_TYPE_FILE;
988 else if(S_ISDIR(mode))
989 return UNIX_TYPE_DIR;
991 else if(S_ISLNK(mode))
992 return UNIX_TYPE_SYMLINK;
995 else if(S_ISCHR(mode))
996 return UNIX_TYPE_CHARDEV;
999 else if(S_ISBLK(mode))
1000 return UNIX_TYPE_BLKDEV;
1003 else if(S_ISFIFO(mode))
1004 return UNIX_TYPE_FIFO;
1007 else if(S_ISSOCK(mode))
1008 return UNIX_TYPE_SOCKET;
1011 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1012 return UNIX_TYPE_UNKNOWN;
1015 /****************************************************************************
1016 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1017 ****************************************************************************/
1019 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1021 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1022 SMB_STRUCT_STAT *psbuf,
1024 enum perm_type ptype,
1029 if (perms == SMB_MODE_NO_CHANGE) {
1030 if (!VALID_STAT(*psbuf)) {
1031 return NT_STATUS_INVALID_PARAMETER;
1033 *ret_perms = psbuf->st_mode;
1034 return NT_STATUS_OK;
1038 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1039 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1040 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1041 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1042 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1043 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1044 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1045 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1046 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1048 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1051 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1054 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1059 /* Apply mode mask */
1060 ret &= lp_create_mask(SNUM(conn));
1061 /* Add in force bits */
1062 ret |= lp_force_create_mode(SNUM(conn));
1065 ret &= lp_dir_mask(SNUM(conn));
1066 /* Add in force bits */
1067 ret |= lp_force_dir_mode(SNUM(conn));
1069 case PERM_EXISTING_FILE:
1070 /* Apply mode mask */
1071 ret &= lp_security_mask(SNUM(conn));
1072 /* Add in force bits */
1073 ret |= lp_force_security_mode(SNUM(conn));
1075 case PERM_EXISTING_DIR:
1076 /* Apply mode mask */
1077 ret &= lp_dir_security_mask(SNUM(conn));
1078 /* Add in force bits */
1079 ret |= lp_force_dir_security_mode(SNUM(conn));
1084 return NT_STATUS_OK;
1087 /****************************************************************************
1088 Get a level dependent lanman2 dir entry.
1089 ****************************************************************************/
1091 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1092 void *inbuf, char *outbuf,
1093 char *path_mask,uint32 dirtype,int info_level,
1094 int requires_resume_key,
1095 BOOL dont_descend,char **ppdata,
1096 char *base_data, int space_remaining,
1097 BOOL *out_of_space, BOOL *got_exact_match,
1098 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1102 SMB_STRUCT_STAT sbuf;
1106 char *p, *q, *pdata = *ppdata;
1110 SMB_OFF_T file_size = 0;
1111 SMB_BIG_UINT allocation_size = 0;
1113 struct timespec mdate_ts, adate_ts, create_date_ts;
1114 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1116 char *last_entry_ptr;
1118 uint32 nt_extmode; /* Used for NT connections instead of mode */
1119 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1120 BOOL check_mangled_names = lp_manglednames(conn->params);
1123 *out_of_space = False;
1124 *got_exact_match = False;
1126 ZERO_STRUCT(mdate_ts);
1127 ZERO_STRUCT(adate_ts);
1128 ZERO_STRUCT(create_date_ts);
1133 p = strrchr_m(path_mask,'/');
1136 pstrcpy(mask,"*.*");
1140 pstrcpy(mask, path_mask);
1145 BOOL ms_dfs_link = False;
1147 /* Needed if we run out of space */
1148 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1149 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1152 * Due to bugs in NT client redirectors we are not using
1153 * resume keys any more - set them to zero.
1154 * Check out the related comments in findfirst/findnext.
1160 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1161 (long)conn->dirptr,curr_dirpos));
1168 * fname may get mangled, dname is never mangled.
1169 * Whenever we're accessing the filesystem we use
1170 * pathreal which is composed from dname.
1173 pstrcpy(fname,dname);
1175 /* This will mangle fname if it's an illegal name. */
1176 mangle_map(fname,False,True,conn->params);
1178 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1179 got_match = mask_match(fname, mask, conn->case_sensitive);
1182 if(!got_match && check_mangled_names &&
1183 !mangle_is_8_3(fname, False, conn->params)) {
1184 pstring mangled_name;
1187 * It turns out that NT matches wildcards against
1188 * both long *and* short names. This may explain some
1189 * of the wildcard wierdness from old DOS clients
1190 * that some people have been seeing.... JRA.
1193 pstrcpy(mangled_name, fname);
1195 /* Force the mangling into 8.3. */
1196 mangle_map( mangled_name, True, False, conn->params);
1197 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1198 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1203 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1204 if (dont_descend && !isdots) {
1208 pstrcpy(pathreal,conn->dirpath);
1210 pstrcat(pathreal,"/");
1212 pstrcat(pathreal,dname);
1214 if (INFO_LEVEL_IS_UNIX(info_level)) {
1215 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1216 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1217 pathreal,strerror(errno)));
1220 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1221 pstring link_target;
1223 /* Needed to show the msdfs symlinks as
1226 if(lp_host_msdfs() &&
1227 lp_msdfs_root(SNUM(conn)) &&
1228 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1229 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1232 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1236 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1237 pathreal,strerror(errno)));
1243 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1245 mode = dos_mode(conn,pathreal,&sbuf);
1248 if (!dir_check_ftype(conn,mode,dirtype)) {
1249 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1253 if (!(mode & aDIR)) {
1254 file_size = get_file_size(sbuf);
1256 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1258 mdate_ts = get_mtimespec(&sbuf);
1259 adate_ts = get_atimespec(&sbuf);
1260 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1262 if (lp_dos_filetime_resolution(SNUM(conn))) {
1263 dos_filetime_timespec(&create_date_ts);
1264 dos_filetime_timespec(&mdate_ts);
1265 dos_filetime_timespec(&adate_ts);
1268 create_date = convert_timespec_to_time_t(create_date_ts);
1269 mdate = convert_timespec_to_time_t(mdate_ts);
1270 adate = convert_timespec_to_time_t(adate_ts);
1272 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1276 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1283 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1285 switch (info_level) {
1286 case SMB_FIND_INFO_STANDARD:
1287 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1288 if(requires_resume_key) {
1292 srv_put_dos_date2(p,0,create_date);
1293 srv_put_dos_date2(p,4,adate);
1294 srv_put_dos_date2(p,8,mdate);
1295 SIVAL(p,12,(uint32)file_size);
1296 SIVAL(p,16,(uint32)allocation_size);
1300 p += align_string(outbuf, p, 0);
1301 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1302 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1304 SCVAL(nameptr, -1, len - 2);
1306 SCVAL(nameptr, -1, 0);
1310 SCVAL(nameptr, -1, len - 1);
1312 SCVAL(nameptr, -1, 0);
1318 case SMB_FIND_EA_SIZE:
1319 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1320 if(requires_resume_key) {
1324 srv_put_dos_date2(p,0,create_date);
1325 srv_put_dos_date2(p,4,adate);
1326 srv_put_dos_date2(p,8,mdate);
1327 SIVAL(p,12,(uint32)file_size);
1328 SIVAL(p,16,(uint32)allocation_size);
1331 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1332 SIVAL(p,22,ea_size); /* Extended attributes */
1336 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1337 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1350 SCVAL(nameptr,0,len);
1352 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1355 case SMB_FIND_EA_LIST:
1357 struct ea_list *file_list = NULL;
1360 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1364 if(requires_resume_key) {
1368 srv_put_dos_date2(p,0,create_date);
1369 srv_put_dos_date2(p,4,adate);
1370 srv_put_dos_date2(p,8,mdate);
1371 SIVAL(p,12,(uint32)file_size);
1372 SIVAL(p,16,(uint32)allocation_size);
1374 p += 22; /* p now points to the EA area. */
1376 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1377 name_list = ea_list_union(name_list, file_list, &ea_len);
1379 /* We need to determine if this entry will fit in the space available. */
1380 /* Max string size is 255 bytes. */
1381 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1382 /* Move the dirptr back to prev_dirpos */
1383 dptr_SeekDir(conn->dirptr, prev_dirpos);
1384 *out_of_space = True;
1385 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1386 return False; /* Not finished - just out of space */
1389 /* Push the ea_data followed by the name. */
1390 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1392 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1393 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1406 SCVAL(nameptr,0,len);
1408 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1412 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1413 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1414 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1416 SIVAL(p,0,reskey); p += 4;
1417 put_long_date_timespec(p,create_date_ts); p += 8;
1418 put_long_date_timespec(p,adate_ts); p += 8;
1419 put_long_date_timespec(p,mdate_ts); p += 8;
1420 put_long_date_timespec(p,mdate_ts); p += 8;
1421 SOFF_T(p,0,file_size); p += 8;
1422 SOFF_T(p,0,allocation_size); p += 8;
1423 SIVAL(p,0,nt_extmode); p += 4;
1424 q = p; p += 4; /* q is placeholder for name length. */
1426 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1427 SIVAL(p,0,ea_size); /* Extended attributes */
1430 /* Clear the short name buffer. This is
1431 * IMPORTANT as not doing so will trigger
1432 * a Win2k client bug. JRA.
1434 if (!was_8_3 && check_mangled_names) {
1435 pstring mangled_name;
1436 pstrcpy(mangled_name, fname);
1437 mangle_map(mangled_name,True,True,
1439 mangled_name[12] = 0;
1440 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1442 memset(p + 2 + len,'\0',24 - len);
1449 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1452 SIVAL(p,0,0); /* Ensure any padding is null. */
1453 len = PTR_DIFF(p, pdata);
1454 len = (len + 3) & ~3;
1459 case SMB_FIND_FILE_DIRECTORY_INFO:
1460 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1462 SIVAL(p,0,reskey); p += 4;
1463 put_long_date_timespec(p,create_date_ts); p += 8;
1464 put_long_date_timespec(p,adate_ts); p += 8;
1465 put_long_date_timespec(p,mdate_ts); p += 8;
1466 put_long_date_timespec(p,mdate_ts); p += 8;
1467 SOFF_T(p,0,file_size); p += 8;
1468 SOFF_T(p,0,allocation_size); p += 8;
1469 SIVAL(p,0,nt_extmode); p += 4;
1470 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1473 SIVAL(p,0,0); /* Ensure any padding is null. */
1474 len = PTR_DIFF(p, pdata);
1475 len = (len + 3) & ~3;
1480 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1481 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1483 SIVAL(p,0,reskey); p += 4;
1484 put_long_date_timespec(p,create_date_ts); p += 8;
1485 put_long_date_timespec(p,adate_ts); p += 8;
1486 put_long_date_timespec(p,mdate_ts); p += 8;
1487 put_long_date_timespec(p,mdate_ts); p += 8;
1488 SOFF_T(p,0,file_size); p += 8;
1489 SOFF_T(p,0,allocation_size); p += 8;
1490 SIVAL(p,0,nt_extmode); p += 4;
1491 q = p; p += 4; /* q is placeholder for name length. */
1493 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1494 SIVAL(p,0,ea_size); /* Extended attributes */
1497 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1501 SIVAL(p,0,0); /* Ensure any padding is null. */
1502 len = PTR_DIFF(p, pdata);
1503 len = (len + 3) & ~3;
1508 case SMB_FIND_FILE_NAMES_INFO:
1509 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1511 SIVAL(p,0,reskey); p += 4;
1513 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1514 acl on a dir (tridge) */
1515 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1518 SIVAL(p,0,0); /* Ensure any padding is null. */
1519 len = PTR_DIFF(p, pdata);
1520 len = (len + 3) & ~3;
1525 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1526 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1528 SIVAL(p,0,reskey); p += 4;
1529 put_long_date_timespec(p,create_date_ts); p += 8;
1530 put_long_date_timespec(p,adate_ts); p += 8;
1531 put_long_date_timespec(p,mdate_ts); p += 8;
1532 put_long_date_timespec(p,mdate_ts); p += 8;
1533 SOFF_T(p,0,file_size); p += 8;
1534 SOFF_T(p,0,allocation_size); p += 8;
1535 SIVAL(p,0,nt_extmode); p += 4;
1536 q = p; p += 4; /* q is placeholder for name length. */
1538 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1539 SIVAL(p,0,ea_size); /* Extended attributes */
1542 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1543 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1544 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1545 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1548 SIVAL(p,0,0); /* Ensure any padding is null. */
1549 len = PTR_DIFF(p, pdata);
1550 len = (len + 3) & ~3;
1555 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1556 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1557 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1559 SIVAL(p,0,reskey); p += 4;
1560 put_long_date_timespec(p,create_date_ts); p += 8;
1561 put_long_date_timespec(p,adate_ts); p += 8;
1562 put_long_date_timespec(p,mdate_ts); p += 8;
1563 put_long_date_timespec(p,mdate_ts); p += 8;
1564 SOFF_T(p,0,file_size); p += 8;
1565 SOFF_T(p,0,allocation_size); p += 8;
1566 SIVAL(p,0,nt_extmode); p += 4;
1567 q = p; p += 4; /* q is placeholder for name length */
1569 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1570 SIVAL(p,0,ea_size); /* Extended attributes */
1573 /* Clear the short name buffer. This is
1574 * IMPORTANT as not doing so will trigger
1575 * a Win2k client bug. JRA.
1577 if (!was_8_3 && check_mangled_names) {
1578 pstring mangled_name;
1579 pstrcpy(mangled_name, fname);
1580 mangle_map(mangled_name,True,True,
1582 mangled_name[12] = 0;
1583 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1586 memset(p + 2 + len,'\0',24 - len);
1593 SSVAL(p,0,0); p += 2; /* Reserved ? */
1594 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1595 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1596 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1599 SIVAL(p,0,0); /* Ensure any padding is null. */
1600 len = PTR_DIFF(p, pdata);
1601 len = (len + 3) & ~3;
1606 /* CIFS UNIX Extension. */
1608 case SMB_FIND_FILE_UNIX:
1609 case SMB_FIND_FILE_UNIX_INFO2:
1611 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1613 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1615 if (info_level == SMB_FIND_FILE_UNIX) {
1616 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1617 p = store_file_unix_basic(conn, p,
1619 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1621 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1622 p = store_file_unix_basic_info2(conn, p,
1626 len = srvstr_push(outbuf, p, fname, -1, 0);
1627 SIVAL(nameptr, 0, len);
1631 SIVAL(p,0,0); /* Ensure any padding is null. */
1633 len = PTR_DIFF(p, pdata);
1634 len = (len + 3) & ~3;
1635 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1637 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1646 if (PTR_DIFF(p,pdata) > space_remaining) {
1647 /* Move the dirptr back to prev_dirpos */
1648 dptr_SeekDir(conn->dirptr, prev_dirpos);
1649 *out_of_space = True;
1650 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1651 return False; /* Not finished - just out of space */
1654 /* Setup the last entry pointer, as an offset from base_data */
1655 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1656 /* Advance the data pointer to the next slot */
1662 /****************************************************************************
1663 Reply to a TRANS2_FINDFIRST.
1664 ****************************************************************************/
1666 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1667 char **pparams, int total_params, char **ppdata, int total_data,
1668 unsigned int max_data_bytes)
1670 /* We must be careful here that we don't return more than the
1671 allowed number of data bytes. If this means returning fewer than
1672 maxentries then so be it. We assume that the redirector has
1673 enough room for the fixed number of parameter bytes it has
1675 char *params = *pparams;
1676 char *pdata = *ppdata;
1679 uint16 findfirst_flags;
1680 BOOL close_after_first;
1682 BOOL requires_resume_key;
1687 int last_entry_off=0;
1691 BOOL finished = False;
1692 BOOL dont_descend = False;
1693 BOOL out_of_space = False;
1694 int space_remaining;
1695 BOOL mask_contains_wcard = False;
1696 SMB_STRUCT_STAT sbuf;
1697 TALLOC_CTX *ea_ctx = NULL;
1698 struct ea_list *ea_list = NULL;
1699 NTSTATUS ntstatus = NT_STATUS_OK;
1701 if (total_params < 13) {
1702 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1705 dirtype = SVAL(params,0);
1706 maxentries = SVAL(params,2);
1707 findfirst_flags = SVAL(params,4);
1708 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1709 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1710 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1711 info_level = SVAL(params,6);
1713 *directory = *mask = 0;
1715 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1716 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1717 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1718 info_level, max_data_bytes));
1721 /* W2K3 seems to treat zero as 1. */
1725 switch (info_level) {
1726 case SMB_FIND_INFO_STANDARD:
1727 case SMB_FIND_EA_SIZE:
1728 case SMB_FIND_EA_LIST:
1729 case SMB_FIND_FILE_DIRECTORY_INFO:
1730 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1731 case SMB_FIND_FILE_NAMES_INFO:
1732 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1733 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1734 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1736 case SMB_FIND_FILE_UNIX:
1737 case SMB_FIND_FILE_UNIX_INFO2:
1738 if (!lp_unix_extensions()) {
1739 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1743 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1746 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1747 if (!NT_STATUS_IS_OK(ntstatus)) {
1748 return ERROR_NT(ntstatus);
1751 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1752 if (!NT_STATUS_IS_OK(ntstatus)) {
1753 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1754 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1756 return ERROR_NT(ntstatus);
1759 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1760 if (!NT_STATUS_IS_OK(ntstatus)) {
1761 return ERROR_NT(ntstatus);
1763 ntstatus = check_name(conn, directory);
1764 if (!NT_STATUS_IS_OK(ntstatus)) {
1765 return ERROR_NT(ntstatus);
1768 p = strrchr_m(directory,'/');
1770 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1771 if((directory[0] == '.') && (directory[1] == '\0')) {
1773 mask_contains_wcard = True;
1775 pstrcpy(mask,directory);
1777 pstrcpy(directory,"./");
1783 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1785 if (info_level == SMB_FIND_EA_LIST) {
1788 if (total_data < 4) {
1789 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1792 ea_size = IVAL(pdata,0);
1793 if (ea_size != total_data) {
1794 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1795 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1799 if (!lp_ea_support(SNUM(conn))) {
1800 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1803 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1804 return ERROR_NT(NT_STATUS_NO_MEMORY);
1807 /* Pull out the list of names. */
1808 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1810 talloc_destroy(ea_ctx);
1811 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1815 *ppdata = (char *)SMB_REALLOC(
1816 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1817 if(*ppdata == NULL ) {
1818 talloc_destroy(ea_ctx);
1819 return ERROR_NT(NT_STATUS_NO_MEMORY);
1823 /* Realloc the params space */
1824 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1825 if (*pparams == NULL) {
1826 talloc_destroy(ea_ctx);
1827 return ERROR_NT(NT_STATUS_NO_MEMORY);
1831 /* Save the wildcard match and attribs we are using on this directory -
1832 needed as lanman2 assumes these are being saved between calls */
1834 ntstatus = dptr_create(conn,
1838 SVAL(inbuf,smb_pid),
1840 mask_contains_wcard,
1844 if (!NT_STATUS_IS_OK(ntstatus)) {
1845 talloc_destroy(ea_ctx);
1846 return ERROR_NT(ntstatus);
1849 dptr_num = dptr_dnum(conn->dirptr);
1850 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1852 /* We don't need to check for VOL here as this is returned by
1853 a different TRANS2 call. */
1855 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1856 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1857 dont_descend = True;
1860 space_remaining = max_data_bytes;
1861 out_of_space = False;
1863 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1864 BOOL got_exact_match = False;
1866 /* this is a heuristic to avoid seeking the dirptr except when
1867 absolutely necessary. It allows for a filename of about 40 chars */
1868 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1869 out_of_space = True;
1872 finished = !get_lanman2_dir_entry(conn,
1874 mask,dirtype,info_level,
1875 requires_resume_key,dont_descend,
1876 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1877 &last_entry_off, ea_list, ea_ctx);
1880 if (finished && out_of_space)
1883 if (!finished && !out_of_space)
1887 * As an optimisation if we know we aren't looking
1888 * for a wildcard name (ie. the name matches the wildcard exactly)
1889 * then we can finish on any (first) match.
1890 * This speeds up large directory searches. JRA.
1896 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1899 talloc_destroy(ea_ctx);
1901 /* Check if we can close the dirptr */
1902 if(close_after_first || (finished && close_if_end)) {
1903 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1904 dptr_close(&dptr_num);
1908 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1909 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1910 * the protocol level is less than NT1. Tested with smbclient. JRA.
1911 * This should fix the OS/2 client bug #2335.
1914 if(numentries == 0) {
1915 dptr_close(&dptr_num);
1916 if (Protocol < PROTOCOL_NT1) {
1917 return ERROR_DOS(ERRDOS,ERRnofiles);
1919 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1923 /* At this point pdata points to numentries directory entries. */
1925 /* Set up the return parameter block */
1926 SSVAL(params,0,dptr_num);
1927 SSVAL(params,2,numentries);
1928 SSVAL(params,4,finished);
1929 SSVAL(params,6,0); /* Never an EA error */
1930 SSVAL(params,8,last_entry_off);
1932 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1934 if ((! *directory) && dptr_path(dptr_num))
1935 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1937 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1938 smb_fn_name(CVAL(inbuf,smb_com)),
1939 mask, directory, dirtype, numentries ) );
1942 * Force a name mangle here to ensure that the
1943 * mask as an 8.3 name is top of the mangled cache.
1944 * The reasons for this are subtle. Don't remove
1945 * this code unless you know what you are doing
1946 * (see PR#13758). JRA.
1949 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1950 mangle_map(mask, True, True, conn->params);
1955 /****************************************************************************
1956 Reply to a TRANS2_FINDNEXT.
1957 ****************************************************************************/
1959 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1960 char **pparams, int total_params, char **ppdata, int total_data,
1961 unsigned int max_data_bytes)
1963 /* We must be careful here that we don't return more than the
1964 allowed number of data bytes. If this means returning fewer than
1965 maxentries then so be it. We assume that the redirector has
1966 enough room for the fixed number of parameter bytes it has
1968 char *params = *pparams;
1969 char *pdata = *ppdata;
1974 uint16 findnext_flags;
1975 BOOL close_after_request;
1977 BOOL requires_resume_key;
1979 BOOL mask_contains_wcard = False;
1980 pstring resume_name;
1986 int i, last_entry_off=0;
1987 BOOL finished = False;
1988 BOOL dont_descend = False;
1989 BOOL out_of_space = False;
1990 int space_remaining;
1991 TALLOC_CTX *ea_ctx = NULL;
1992 struct ea_list *ea_list = NULL;
1993 NTSTATUS ntstatus = NT_STATUS_OK;
1995 if (total_params < 13) {
1996 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1999 dptr_num = SVAL(params,0);
2000 maxentries = SVAL(params,2);
2001 info_level = SVAL(params,4);
2002 resume_key = IVAL(params,6);
2003 findnext_flags = SVAL(params,10);
2004 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2005 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2006 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2007 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2009 *mask = *directory = *resume_name = 0;
2011 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2012 if (!NT_STATUS_IS_OK(ntstatus)) {
2013 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2014 complain (it thinks we're asking for the directory above the shared
2015 path or an invalid name). Catch this as the resume name is only compared, never used in
2016 a file access. JRA. */
2017 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2018 pstrcpy(resume_name, "..");
2019 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2020 pstrcpy(resume_name, ".");
2022 return ERROR_NT(ntstatus);
2026 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2027 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2028 resume_key = %d resume name = %s continue=%d level = %d\n",
2029 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2030 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2033 /* W2K3 seems to treat zero as 1. */
2037 switch (info_level) {
2038 case SMB_FIND_INFO_STANDARD:
2039 case SMB_FIND_EA_SIZE:
2040 case SMB_FIND_EA_LIST:
2041 case SMB_FIND_FILE_DIRECTORY_INFO:
2042 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2043 case SMB_FIND_FILE_NAMES_INFO:
2044 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2045 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2046 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2048 case SMB_FIND_FILE_UNIX:
2049 case SMB_FIND_FILE_UNIX_INFO2:
2050 if (!lp_unix_extensions()) {
2051 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2055 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2058 if (info_level == SMB_FIND_EA_LIST) {
2061 if (total_data < 4) {
2062 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2065 ea_size = IVAL(pdata,0);
2066 if (ea_size != total_data) {
2067 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2068 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2069 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2072 if (!lp_ea_support(SNUM(conn))) {
2073 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2076 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2077 return ERROR_NT(NT_STATUS_NO_MEMORY);
2080 /* Pull out the list of names. */
2081 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2083 talloc_destroy(ea_ctx);
2084 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2088 *ppdata = (char *)SMB_REALLOC(
2089 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2090 if(*ppdata == NULL) {
2091 talloc_destroy(ea_ctx);
2092 return ERROR_NT(NT_STATUS_NO_MEMORY);
2097 /* Realloc the params space */
2098 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2099 if(*pparams == NULL ) {
2100 talloc_destroy(ea_ctx);
2101 return ERROR_NT(NT_STATUS_NO_MEMORY);
2106 /* Check that the dptr is valid */
2107 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2108 talloc_destroy(ea_ctx);
2109 return ERROR_DOS(ERRDOS,ERRnofiles);
2112 string_set(&conn->dirpath,dptr_path(dptr_num));
2114 /* Get the wildcard mask from the dptr */
2115 if((p = dptr_wcard(dptr_num))== NULL) {
2116 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2117 talloc_destroy(ea_ctx);
2118 return ERROR_DOS(ERRDOS,ERRnofiles);
2122 pstrcpy(directory,conn->dirpath);
2124 /* Get the attr mask from the dptr */
2125 dirtype = dptr_attr(dptr_num);
2127 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2128 dptr_num, mask, dirtype,
2130 dptr_TellDir(conn->dirptr)));
2132 /* We don't need to check for VOL here as this is returned by
2133 a different TRANS2 call. */
2135 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2136 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2137 dont_descend = True;
2140 space_remaining = max_data_bytes;
2141 out_of_space = False;
2144 * Seek to the correct position. We no longer use the resume key but
2145 * depend on the last file name instead.
2148 if(*resume_name && !continue_bit) {
2151 long current_pos = 0;
2153 * Remember, mangle_map is called by
2154 * get_lanman2_dir_entry(), so the resume name
2155 * could be mangled. Ensure we check the unmangled name.
2158 if (mangle_is_mangled(resume_name, conn->params)) {
2159 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2164 * Fix for NT redirector problem triggered by resume key indexes
2165 * changing between directory scans. We now return a resume key of 0
2166 * and instead look for the filename to continue from (also given
2167 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2168 * findfirst/findnext (as is usual) then the directory pointer
2169 * should already be at the correct place.
2172 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2173 } /* end if resume_name && !continue_bit */
2175 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2176 BOOL got_exact_match = False;
2178 /* this is a heuristic to avoid seeking the dirptr except when
2179 absolutely necessary. It allows for a filename of about 40 chars */
2180 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2181 out_of_space = True;
2184 finished = !get_lanman2_dir_entry(conn,
2186 mask,dirtype,info_level,
2187 requires_resume_key,dont_descend,
2188 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2189 &last_entry_off, ea_list, ea_ctx);
2192 if (finished && out_of_space)
2195 if (!finished && !out_of_space)
2199 * As an optimisation if we know we aren't looking
2200 * for a wildcard name (ie. the name matches the wildcard exactly)
2201 * then we can finish on any (first) match.
2202 * This speeds up large directory searches. JRA.
2208 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2211 talloc_destroy(ea_ctx);
2213 /* Check if we can close the dirptr */
2214 if(close_after_request || (finished && close_if_end)) {
2215 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2216 dptr_close(&dptr_num); /* This frees up the saved mask */
2219 /* Set up the return parameter block */
2220 SSVAL(params,0,numentries);
2221 SSVAL(params,2,finished);
2222 SSVAL(params,4,0); /* Never an EA error */
2223 SSVAL(params,6,last_entry_off);
2225 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2227 if ((! *directory) && dptr_path(dptr_num))
2228 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2230 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2231 smb_fn_name(CVAL(inbuf,smb_com)),
2232 mask, directory, dirtype, numentries ) );
2237 /****************************************************************************
2238 Reply to a TRANS2_QFSINFO (query filesystem info).
2239 ****************************************************************************/
2241 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2242 char **pparams, int total_params, char **ppdata, int total_data,
2243 unsigned int max_data_bytes)
2246 char *params = *pparams;
2250 const char *vname = volume_label(SNUM(conn));
2251 int snum = SNUM(conn);
2252 char *fstype = lp_fstype(SNUM(conn));
2255 if (total_params < 2) {
2256 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2259 info_level = SVAL(params,0);
2261 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2263 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2264 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2265 return ERROR_DOS(ERRSRV,ERRinvdevice);
2268 *ppdata = (char *)SMB_REALLOC(
2269 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2270 if (*ppdata == NULL ) {
2271 return ERROR_NT(NT_STATUS_NO_MEMORY);
2275 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2277 switch (info_level) {
2278 case SMB_INFO_ALLOCATION:
2280 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2282 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2283 return(UNIXERROR(ERRHRD,ERRgeneral));
2286 block_size = lp_block_size(snum);
2287 if (bsize < block_size) {
2288 SMB_BIG_UINT factor = block_size/bsize;
2293 if (bsize > block_size) {
2294 SMB_BIG_UINT factor = bsize/block_size;
2299 bytes_per_sector = 512;
2300 sectors_per_unit = bsize/bytes_per_sector;
2302 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2303 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2304 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2306 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2307 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2308 SIVAL(pdata,l1_cUnit,dsize);
2309 SIVAL(pdata,l1_cUnitAvail,dfree);
2310 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2314 case SMB_INFO_VOLUME:
2315 /* Return volume name */
2317 * Add volume serial number - hash of a combination of
2318 * the called hostname and the service name.
2320 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2322 * Win2k3 and previous mess this up by sending a name length
2323 * one byte short. I believe only older clients (OS/2 Win9x) use
2324 * this call so try fixing this by adding a terminating null to
2325 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2327 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2328 SCVAL(pdata,l2_vol_cch,len);
2329 data_len = l2_vol_szVolLabel + len;
2330 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2331 (unsigned)st.st_ctime, len, vname));
2334 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2335 case SMB_FS_ATTRIBUTE_INFORMATION:
2338 #if defined(HAVE_SYS_QUOTAS)
2339 quota_flag = FILE_VOLUME_QUOTAS;
2342 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2343 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2344 quota_flag); /* FS ATTRIBUTES */
2346 SIVAL(pdata,4,255); /* Max filename component length */
2347 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2348 and will think we can't do long filenames */
2349 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2351 data_len = 12 + len;
2354 case SMB_QUERY_FS_LABEL_INFO:
2355 case SMB_FS_LABEL_INFORMATION:
2356 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2361 case SMB_QUERY_FS_VOLUME_INFO:
2362 case SMB_FS_VOLUME_INFORMATION:
2365 * Add volume serial number - hash of a combination of
2366 * the called hostname and the service name.
2368 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2369 (str_checksum(get_local_machine_name())<<16));
2371 /* Max label len is 32 characters. */
2372 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2373 SIVAL(pdata,12,len);
2376 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2377 (int)strlen(vname),vname, lp_servicename(snum)));
2380 case SMB_QUERY_FS_SIZE_INFO:
2381 case SMB_FS_SIZE_INFORMATION:
2383 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2385 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2386 return(UNIXERROR(ERRHRD,ERRgeneral));
2388 block_size = lp_block_size(snum);
2389 if (bsize < block_size) {
2390 SMB_BIG_UINT factor = block_size/bsize;
2395 if (bsize > block_size) {
2396 SMB_BIG_UINT factor = bsize/block_size;
2401 bytes_per_sector = 512;
2402 sectors_per_unit = bsize/bytes_per_sector;
2403 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2404 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2405 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2406 SBIG_UINT(pdata,0,dsize);
2407 SBIG_UINT(pdata,8,dfree);
2408 SIVAL(pdata,16,sectors_per_unit);
2409 SIVAL(pdata,20,bytes_per_sector);
2413 case SMB_FS_FULL_SIZE_INFORMATION:
2415 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2417 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2418 return(UNIXERROR(ERRHRD,ERRgeneral));
2420 block_size = lp_block_size(snum);
2421 if (bsize < block_size) {
2422 SMB_BIG_UINT factor = block_size/bsize;
2427 if (bsize > block_size) {
2428 SMB_BIG_UINT factor = bsize/block_size;
2433 bytes_per_sector = 512;
2434 sectors_per_unit = bsize/bytes_per_sector;
2435 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2436 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2437 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2438 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2439 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2440 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2441 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2442 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2446 case SMB_QUERY_FS_DEVICE_INFO:
2447 case SMB_FS_DEVICE_INFORMATION:
2449 SIVAL(pdata,0,0); /* dev type */
2450 SIVAL(pdata,4,0); /* characteristics */
2453 #ifdef HAVE_SYS_QUOTAS
2454 case SMB_FS_QUOTA_INFORMATION:
2456 * what we have to send --metze:
2458 * Unknown1: 24 NULL bytes
2459 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2460 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2461 * Quota Flags: 2 byte :
2462 * Unknown3: 6 NULL bytes
2466 * details for Quota Flags:
2468 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2469 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2470 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2471 * 0x0001 Enable Quotas: enable quota for this fs
2475 /* we need to fake up a fsp here,
2476 * because its not send in this call
2479 SMB_NTQUOTA_STRUCT quotas;
2482 ZERO_STRUCT(quotas);
2488 if (current_user.ut.uid != 0) {
2489 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2490 lp_servicename(SNUM(conn)),conn->user));
2491 return ERROR_DOS(ERRDOS,ERRnoaccess);
2494 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2495 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2496 return ERROR_DOS(ERRSRV,ERRerror);
2501 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2503 /* Unknown1 24 NULL bytes*/
2504 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2505 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2506 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2508 /* Default Soft Quota 8 bytes */
2509 SBIG_UINT(pdata,24,quotas.softlim);
2511 /* Default Hard Quota 8 bytes */
2512 SBIG_UINT(pdata,32,quotas.hardlim);
2514 /* Quota flag 2 bytes */
2515 SSVAL(pdata,40,quotas.qflags);
2517 /* Unknown3 6 NULL bytes */
2523 #endif /* HAVE_SYS_QUOTAS */
2524 case SMB_FS_OBJECTID_INFORMATION:
2529 * Query the version and capabilities of the CIFS UNIX extensions
2533 case SMB_QUERY_CIFS_UNIX_INFO:
2534 if (!lp_unix_extensions()) {
2535 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2538 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2539 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2540 /* We have POSIX ACLs, pathname and locking capability. */
2541 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2542 CIFS_UNIX_POSIX_ACLS_CAP|
2543 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2544 CIFS_UNIX_FCNTL_LOCKS_CAP|
2545 CIFS_UNIX_EXTATTR_CAP|
2546 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2549 case SMB_QUERY_POSIX_FS_INFO:
2552 vfs_statvfs_struct svfs;
2554 if (!lp_unix_extensions()) {
2555 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2558 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2562 SIVAL(pdata,0,svfs.OptimalTransferSize);
2563 SIVAL(pdata,4,svfs.BlockSize);
2564 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2565 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2566 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2567 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2568 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2569 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2570 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2572 } else if (rc == EOPNOTSUPP) {
2573 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2574 #endif /* EOPNOTSUPP */
2576 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2577 return ERROR_DOS(ERRSRV,ERRerror);
2582 case SMB_QUERY_POSIX_WHOAMI:
2588 if (!lp_unix_extensions()) {
2589 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2592 if (max_data_bytes < 40) {
2593 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2596 /* We ARE guest if global_sid_Builtin_Guests is
2597 * in our list of SIDs.
2599 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2600 current_user.nt_user_token)) {
2601 flags |= SMB_WHOAMI_GUEST;
2604 /* We are NOT guest if global_sid_Authenticated_Users
2605 * is in our list of SIDs.
2607 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2608 current_user.nt_user_token)) {
2609 flags &= ~SMB_WHOAMI_GUEST;
2612 /* NOTE: 8 bytes for UID/GID, irrespective of native
2613 * platform size. This matches
2614 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2616 data_len = 4 /* flags */
2623 + 4 /* pad/reserved */
2624 + (current_user.ut.ngroups * 8)
2626 + (current_user.nt_user_token->num_sids *
2630 SIVAL(pdata, 0, flags);
2631 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2632 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2633 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2636 if (data_len >= max_data_bytes) {
2637 /* Potential overflow, skip the GIDs and SIDs. */
2639 SIVAL(pdata, 24, 0); /* num_groups */
2640 SIVAL(pdata, 28, 0); /* num_sids */
2641 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2642 SIVAL(pdata, 36, 0); /* reserved */
2648 SIVAL(pdata, 24, current_user.ut.ngroups);
2650 current_user.nt_user_token->num_sids);
2652 /* We walk the SID list twice, but this call is fairly
2653 * infrequent, and I don't expect that it's performance
2654 * sensitive -- jpeach
2656 for (i = 0, sid_bytes = 0;
2657 i < current_user.nt_user_token->num_sids; ++i) {
2659 sid_size(¤t_user.nt_user_token->user_sids[i]);
2662 /* SID list byte count */
2663 SIVAL(pdata, 32, sid_bytes);
2665 /* 4 bytes pad/reserved - must be zero */
2666 SIVAL(pdata, 36, 0);
2670 for (i = 0; i < current_user.ut.ngroups; ++i) {
2671 SBIG_UINT(pdata, data_len,
2672 (SMB_BIG_UINT)current_user.ut.groups[i]);
2678 i < current_user.nt_user_token->num_sids; ++i) {
2680 sid_size(¤t_user.nt_user_token->user_sids[i]);
2682 sid_linearize(pdata + data_len, sid_len,
2683 ¤t_user.nt_user_token->user_sids[i]);
2684 data_len += sid_len;
2690 case SMB_MAC_QUERY_FS_INFO:
2692 * Thursby MAC extension... ONLY on NTFS filesystems
2693 * once we do streams then we don't need this
2695 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2697 SIVAL(pdata,84,0x100); /* Don't support mac... */
2702 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2706 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2708 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2713 /****************************************************************************
2714 Reply to a TRANS2_SETFSINFO (set filesystem info).
2715 ****************************************************************************/
2717 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2718 char **pparams, int total_params, char **ppdata, int total_data,
2719 unsigned int max_data_bytes)
2721 char *pdata = *ppdata;
2722 char *params = *pparams;
2726 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2729 if (total_params < 4) {
2730 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2732 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2735 info_level = SVAL(params,2);
2737 switch(info_level) {
2738 case SMB_SET_CIFS_UNIX_INFO:
2740 uint16 client_unix_major;
2741 uint16 client_unix_minor;
2742 uint32 client_unix_cap_low;
2743 uint32 client_unix_cap_high;
2745 if (!lp_unix_extensions()) {
2746 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2749 /* There should be 12 bytes of capabilities set. */
2750 if (total_data < 8) {
2751 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2753 client_unix_major = SVAL(pdata,0);
2754 client_unix_minor = SVAL(pdata,2);
2755 client_unix_cap_low = IVAL(pdata,4);
2756 client_unix_cap_high = IVAL(pdata,8);
2757 /* Just print these values for now. */
2758 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2759 cap_low = 0x%x, cap_high = 0x%x\n",
2760 (unsigned int)client_unix_major,
2761 (unsigned int)client_unix_minor,
2762 (unsigned int)client_unix_cap_low,
2763 (unsigned int)client_unix_cap_high ));
2765 /* Here is where we must switch to posix pathname processing... */
2766 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2767 lp_set_posix_pathnames();
2768 mangle_change_to_posix();
2771 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2772 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2773 /* Client that knows how to do posix locks,
2774 * but not posix open/mkdir operations. Set a
2775 * default type for read/write checks. */
2777 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2782 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2785 size_t param_len = 0;
2786 size_t data_len = total_data;
2788 if (!lp_unix_extensions()) {
2789 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2792 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2794 status = srv_request_encryption_setup(conn,
2795 (unsigned char **)ppdata,
2797 (unsigned char **)pparams,
2801 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2802 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2803 } else if (!NT_STATUS_IS_OK(status)) {
2804 return ERROR_NT(status);
2807 send_trans2_replies(outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2809 if (NT_STATUS_IS_OK(status)) {
2810 /* Server-side transport encryption is now *on*. */
2811 status = srv_encryption_start(conn);
2812 if (!NT_STATUS_IS_OK(status)) {
2813 exit_server_cleanly("Failure in setting up encrypted transport");
2818 case SMB_FS_QUOTA_INFORMATION:
2820 files_struct *fsp = NULL;
2821 SMB_NTQUOTA_STRUCT quotas;
2823 ZERO_STRUCT(quotas);
2826 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2827 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2828 lp_servicename(SNUM(conn)),conn->user));
2829 return ERROR_DOS(ERRSRV,ERRaccess);
2832 /* note: normaly there're 48 bytes,
2833 * but we didn't use the last 6 bytes for now
2836 fsp = file_fsp(params,0);
2837 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2838 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2839 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2842 if (total_data < 42) {
2843 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2845 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2848 /* unknown_1 24 NULL bytes in pdata*/
2850 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2851 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2852 #ifdef LARGE_SMB_OFF_T
2853 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2854 #else /* LARGE_SMB_OFF_T */
2855 if ((IVAL(pdata,28) != 0)&&
2856 ((quotas.softlim != 0xFFFFFFFF)||
2857 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2858 /* more than 32 bits? */
2859 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2861 #endif /* LARGE_SMB_OFF_T */
2863 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2864 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2865 #ifdef LARGE_SMB_OFF_T
2866 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2867 #else /* LARGE_SMB_OFF_T */
2868 if ((IVAL(pdata,36) != 0)&&
2869 ((quotas.hardlim != 0xFFFFFFFF)||
2870 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2871 /* more than 32 bits? */
2872 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2874 #endif /* LARGE_SMB_OFF_T */
2876 /* quota_flags 2 bytes **/
2877 quotas.qflags = SVAL(pdata,40);
2879 /* unknown_2 6 NULL bytes follow*/
2881 /* now set the quotas */
2882 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2883 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2884 return ERROR_DOS(ERRSRV,ERRerror);
2890 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2892 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2897 * sending this reply works fine,
2898 * but I'm not sure it's the same
2899 * like windows do...
2902 outsize = set_message(outbuf,10,0,True);
2907 #if defined(HAVE_POSIX_ACLS)
2908 /****************************************************************************
2909 Utility function to count the number of entries in a POSIX acl.
2910 ****************************************************************************/
2912 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2914 unsigned int ace_count = 0;
2915 int entry_id = SMB_ACL_FIRST_ENTRY;
2916 SMB_ACL_ENTRY_T entry;
2918 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2920 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2921 entry_id = SMB_ACL_NEXT_ENTRY;
2928 /****************************************************************************
2929 Utility function to marshall a POSIX acl into wire format.
2930 ****************************************************************************/
2932 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2934 int entry_id = SMB_ACL_FIRST_ENTRY;
2935 SMB_ACL_ENTRY_T entry;
2937 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2938 SMB_ACL_TAG_T tagtype;
2939 SMB_ACL_PERMSET_T permset;
2940 unsigned char perms = 0;
2941 unsigned int own_grp;
2944 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2945 entry_id = SMB_ACL_NEXT_ENTRY;
2948 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2949 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2953 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2954 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2958 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2959 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2960 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2962 SCVAL(pdata,1,perms);
2965 case SMB_ACL_USER_OBJ:
2966 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2967 own_grp = (unsigned int)pst->st_uid;
2968 SIVAL(pdata,2,own_grp);
2973 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2975 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2977 own_grp = (unsigned int)*puid;
2978 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2979 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2980 SIVAL(pdata,2,own_grp);
2984 case SMB_ACL_GROUP_OBJ:
2985 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2986 own_grp = (unsigned int)pst->st_gid;
2987 SIVAL(pdata,2,own_grp);
2992 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2994 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2996 own_grp = (unsigned int)*pgid;
2997 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2998 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2999 SIVAL(pdata,2,own_grp);
3004 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3005 SIVAL(pdata,2,0xFFFFFFFF);
3006 SIVAL(pdata,6,0xFFFFFFFF);
3009 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3010 SIVAL(pdata,2,0xFFFFFFFF);
3011 SIVAL(pdata,6,0xFFFFFFFF);
3014 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3017 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3024 /****************************************************************************
3025 Store the FILE_UNIX_BASIC info.
3026 ****************************************************************************/
3028 static char *store_file_unix_basic(connection_struct *conn,
3031 const SMB_STRUCT_STAT *psbuf)
3033 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3034 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3036 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3039 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3042 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3043 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3044 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3047 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3051 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3055 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3058 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3062 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3066 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3069 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3073 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3080 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3081 * the chflags(2) (or equivalent) flags.
3083 * XXX: this really should be behind the VFS interface. To do this, we would
3084 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3085 * Each VFS module could then implement it's own mapping as appropriate for the
3086 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3088 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3092 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3096 { UF_IMMUTABLE, EXT_IMMUTABLE },
3100 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3104 { UF_HIDDEN, EXT_HIDDEN },
3107 /* Do not remove. We need to guarantee that this array has at least one
3108 * entry to build on HP-UX.
3114 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3115 uint32 *smb_fflags, uint32 *smb_fmask)
3117 #ifdef HAVE_STAT_ST_FLAGS
3120 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3121 *smb_fmask |= info2_flags_map[i].smb_fflag;
3122 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3123 *smb_fflags |= info2_flags_map[i].smb_fflag;
3126 #endif /* HAVE_STAT_ST_FLAGS */
3129 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3130 const uint32 smb_fflags,
3131 const uint32 smb_fmask,
3134 #ifdef HAVE_STAT_ST_FLAGS
3135 uint32 max_fmask = 0;
3138 *stat_fflags = psbuf->st_flags;
3140 /* For each flags requested in smb_fmask, check the state of the
3141 * corresponding flag in smb_fflags and set or clear the matching
3145 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3146 max_fmask |= info2_flags_map[i].smb_fflag;
3147 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3148 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3149 *stat_fflags |= info2_flags_map[i].stat_fflag;
3151 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3156 /* If smb_fmask is asking to set any bits that are not supported by
3157 * our flag mappings, we should fail.
3159 if ((smb_fmask & max_fmask) != smb_fmask) {
3166 #endif /* HAVE_STAT_ST_FLAGS */
3170 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3171 * of file flags and birth (create) time.
3173 static char *store_file_unix_basic_info2(connection_struct *conn,
3176 const SMB_STRUCT_STAT *psbuf)
3178 uint32 file_flags = 0;
3179 uint32 flags_mask = 0;
3181 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3183 /* Create (birth) time 64 bit */
3184 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3187 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3188 SIVAL(pdata, 0, file_flags); /* flags */
3189 SIVAL(pdata, 4, flags_mask); /* mask */
3195 /****************************************************************************
3196 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3197 file name or file id).
3198 ****************************************************************************/
3200 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3201 unsigned int tran_call,
3202 char **pparams, int total_params, char **ppdata, int total_data,
3203 unsigned int max_data_bytes)
3205 char *params = *pparams;
3206 char *pdata = *ppdata;
3210 SMB_OFF_T file_size=0;
3211 SMB_BIG_UINT allocation_size=0;
3212 unsigned int data_size = 0;
3213 unsigned int param_size = 2;
3214 SMB_STRUCT_STAT sbuf;
3215 pstring fname, dos_fname;
3220 BOOL delete_pending = False;
3222 time_t create_time, mtime, atime;
3223 struct timespec create_time_ts, mtime_ts, atime_ts;
3224 files_struct *fsp = NULL;
3225 TALLOC_CTX *data_ctx = NULL;
3226 struct ea_list *ea_list = NULL;
3227 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3228 char *lock_data = NULL;
3231 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3235 if (tran_call == TRANSACT2_QFILEINFO) {
3236 if (total_params < 4) {
3237 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3240 fsp = file_fsp(params,0);
3241 info_level = SVAL(params,2);
3243 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3245 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3246 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3249 if(fsp && (fsp->fake_file_handle)) {
3251 * This is actually for the QUOTA_FAKE_FILE --metze
3254 pstrcpy(fname, fsp->fsp_name);
3255 /* We know this name is ok, it's already passed the checks. */
3257 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3259 * This is actually a QFILEINFO on a directory
3260 * handle (returned from an NT SMB). NT5.0 seems
3261 * to do this call. JRA.
3263 /* We know this name is ok, it's already passed the checks. */
3264 pstrcpy(fname, fsp->fsp_name);
3266 if (INFO_LEVEL_IS_UNIX(info_level)) {
3267 /* Always do lstat for UNIX calls. */
3268 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3269 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3270 return UNIXERROR(ERRDOS,ERRbadpath);
3272 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3273 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3274 return UNIXERROR(ERRDOS,ERRbadpath);
3277 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3280 * Original code - this is an open file.
3282 CHECK_FSP(fsp,conn);
3284 pstrcpy(fname, fsp->fsp_name);
3285 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3286 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3287 return(UNIXERROR(ERRDOS,ERRbadfid));
3289 pos = fsp->fh->position_information;
3290 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3291 access_mask = fsp->access_mask;
3294 NTSTATUS status = NT_STATUS_OK;
3297 if (total_params < 7) {
3298 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3301 info_level = SVAL(params,0);
3303 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3305 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3306 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3309 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 return ERROR_NT(status);
3314 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3315 if (!NT_STATUS_IS_OK(status)) {
3316 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3317 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3319 return ERROR_NT(status);
3322 status = unix_convert(conn, fname, False, NULL, &sbuf);
3323 if (!NT_STATUS_IS_OK(status)) {
3324 return ERROR_NT(status);
3326 status = check_name(conn, fname);
3327 if (!NT_STATUS_IS_OK(status)) {
3328 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3329 return ERROR_NT(status);
3332 if (INFO_LEVEL_IS_UNIX(info_level)) {
3333 /* Always do lstat for UNIX calls. */
3334 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3335 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3336 return UNIXERROR(ERRDOS,ERRbadpath);
3338 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3339 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3340 return UNIXERROR(ERRDOS,ERRbadpath);
3343 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3344 if (delete_pending) {
3345 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3349 nlink = sbuf.st_nlink;
3351 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3352 /* NTFS does not seem to count ".." */
3356 if ((nlink > 0) && delete_pending) {
3360 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3361 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3364 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3365 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3367 p = strrchr_m(fname,'/');
3373 mode = dos_mode(conn,fname,&sbuf);
3375 mode = FILE_ATTRIBUTE_NORMAL;
3377 fullpathname = fname;
3379 file_size = get_file_size(sbuf);
3381 /* Pull out any data sent here before we realloc. */
3382 switch (info_level) {
3383 case SMB_INFO_QUERY_EAS_FROM_LIST:
3385 /* Pull any EA list from the data portion. */
3388 if (total_data < 4) {
3389 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3391 ea_size = IVAL(pdata,0);
3393 if (total_data > 0 && ea_size != total_data) {
3394 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3395 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3396 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3399 if (!lp_ea_support(SNUM(conn))) {
3400 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3403 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3404 return ERROR_NT(NT_STATUS_NO_MEMORY);
3407 /* Pull out the list of names. */
3408 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3410 talloc_destroy(data_ctx);
3411 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3416 case SMB_QUERY_POSIX_LOCK:
3418 if (fsp == NULL || fsp->fh->fd == -1) {
3419 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3422 if (total_data != POSIX_LOCK_DATA_SIZE) {
3423 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3426 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3427 return ERROR_NT(NT_STATUS_NO_MEMORY);
3430 /* Copy the lock range data. */
3431 lock_data = (char *)talloc_memdup(
3432 data_ctx, pdata, total_data);
3434 talloc_destroy(data_ctx);
3435 return ERROR_NT(NT_STATUS_NO_MEMORY);
3442 *pparams = (char *)SMB_REALLOC(*pparams,2);
3443 if (*pparams == NULL) {
3444 talloc_destroy(data_ctx);
3445 return ERROR_NT(NT_STATUS_NO_MEMORY);
3449 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3450 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3451 if (*ppdata == NULL ) {
3452 talloc_destroy(data_ctx);
3453 return ERROR_NT(NT_STATUS_NO_MEMORY);
3457 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3458 mtime_ts = get_mtimespec(&sbuf);
3459 atime_ts = get_atimespec(&sbuf);
3461 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3464 if (!null_timespec(fsp->pending_modtime)) {
3465 /* the pending modtime overrides the current modtime */
3466 mtime_ts = fsp->pending_modtime;
3469 /* Do we have this path open ? */
3470 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3471 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3472 /* the pending modtime overrides the current modtime */
3473 mtime_ts = fsp1->pending_modtime;
3475 if (fsp1 && fsp1->initial_allocation_size) {
3476 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3480 if (lp_dos_filetime_resolution(SNUM(conn))) {
3481 dos_filetime_timespec(&create_time_ts);
3482 dos_filetime_timespec(&mtime_ts);
3483 dos_filetime_timespec(&atime_ts);
3486 create_time = convert_timespec_to_time_t(create_time_ts);
3487 mtime = convert_timespec_to_time_t(mtime_ts);
3488 atime = convert_timespec_to_time_t(atime_ts);
3490 /* NT expects the name to be in an exact form of the *full*
3491 filename. See the trans2 torture test */
3492 if (strequal(base_name,".")) {
3493 pstrcpy(dos_fname, "\\");
3495 pstr_sprintf(dos_fname, "\\%s", fname);
3496 string_replace(dos_fname, '/', '\\');
3499 switch (info_level) {
3500 case SMB_INFO_STANDARD:
3501 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3503 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3504 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3505 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3506 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3507 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3508 SSVAL(pdata,l1_attrFile,mode);
3511 case SMB_INFO_QUERY_EA_SIZE:
3513 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3514 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3516 srv_put_dos_date2(pdata,0,create_time);
3517 srv_put_dos_date2(pdata,4,atime);
3518 srv_put_dos_date2(pdata,8,mtime); /* write time */
3519 SIVAL(pdata,12,(uint32)file_size);
3520 SIVAL(pdata,16,(uint32)allocation_size);
3521 SSVAL(pdata,20,mode);
3522 SIVAL(pdata,22,ea_size);
3526 case SMB_INFO_IS_NAME_VALID:
3527 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3528 if (tran_call == TRANSACT2_QFILEINFO) {
3529 /* os/2 needs this ? really ?*/
3530 return ERROR_DOS(ERRDOS,ERRbadfunc);
3536 case SMB_INFO_QUERY_EAS_FROM_LIST:
3538 size_t total_ea_len = 0;
3539 struct ea_list *ea_file_list = NULL;
3541 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3543 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3544 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3546 if (!ea_list || (total_ea_len > data_size)) {
3547 talloc_destroy(data_ctx);
3549 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3553 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3554 talloc_destroy(data_ctx);
3558 case SMB_INFO_QUERY_ALL_EAS:
3560 /* We have data_size bytes to put EA's into. */
3561 size_t total_ea_len = 0;
3563 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3565 data_ctx = talloc_init("ea_ctx");
3567 return ERROR_NT(NT_STATUS_NO_MEMORY);
3570 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3571 if (!ea_list || (total_ea_len > data_size)) {
3572 talloc_destroy(data_ctx);
3574 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3578 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3579 talloc_destroy(data_ctx);
3583 case SMB_FILE_BASIC_INFORMATION:
3584 case SMB_QUERY_FILE_BASIC_INFO:
3586 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3587 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3588 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3590 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3594 put_long_date_timespec(pdata,create_time_ts);
3595 put_long_date_timespec(pdata+8,atime_ts);
3596 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3597 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3598 SIVAL(pdata,32,mode);
3600 DEBUG(5,("SMB_QFBI - "));
3601 DEBUG(5,("create: %s ", ctime(&create_time)));
3602 DEBUG(5,("access: %s ", ctime(&atime)));
3603 DEBUG(5,("write: %s ", ctime(&mtime)));
3604 DEBUG(5,("change: %s ", ctime(&mtime)));
3605 DEBUG(5,("mode: %x\n", mode));
3608 case SMB_FILE_STANDARD_INFORMATION:
3609 case SMB_QUERY_FILE_STANDARD_INFO:
3611 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3613 SOFF_T(pdata,0,allocation_size);
3614 SOFF_T(pdata,8,file_size);
3615 SIVAL(pdata,16,nlink);
3616 SCVAL(pdata,20,delete_pending?1:0);
3617 SCVAL(pdata,21,(mode&aDIR)?1:0);
3618 SSVAL(pdata,22,0); /* Padding. */
3621 case SMB_FILE_EA_INFORMATION:
3622 case SMB_QUERY_FILE_EA_INFO:
3624 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3625 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3627 SIVAL(pdata,0,ea_size);
3631 /* Get the 8.3 name - used if NT SMB was negotiated. */
3632 case SMB_QUERY_FILE_ALT_NAME_INFO:
3633 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3637 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3638 pstrcpy(short_name,base_name);
3639 /* Mangle if not already 8.3 */
3640 if(!mangle_is_8_3(short_name, True, conn->params)) {
3641 mangle_map(short_name,True,True,conn->params);
3643 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3644 data_size = 4 + len;
3649 case SMB_QUERY_FILE_NAME_INFO:
3651 this must be *exactly* right for ACLs on mapped drives to work
3653 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3654 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3655 data_size = 4 + len;
3659 case SMB_FILE_ALLOCATION_INFORMATION:
3660 case SMB_QUERY_FILE_ALLOCATION_INFO:
3661 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3663 SOFF_T(pdata,0,allocation_size);
3666 case SMB_FILE_END_OF_FILE_INFORMATION:
3667 case SMB_QUERY_FILE_END_OF_FILEINFO:
3668 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3670 SOFF_T(pdata,0,file_size);
3673 case SMB_QUERY_FILE_ALL_INFO:
3674 case SMB_FILE_ALL_INFORMATION:
3676 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3677 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3678 put_long_date_timespec(pdata,create_time_ts);
3679 put_long_date_timespec(pdata+8,atime_ts);
3680 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3681 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3682 SIVAL(pdata,32,mode);
3683 SIVAL(pdata,36,0); /* padding. */
3685 SOFF_T(pdata,0,allocation_size);
3686 SOFF_T(pdata,8,file_size);
3687 SIVAL(pdata,16,nlink);
3688 SCVAL(pdata,20,delete_pending);
3689 SCVAL(pdata,21,(mode&aDIR)?1:0);
3692 SIVAL(pdata,0,ea_size);
3693 pdata += 4; /* EA info */
3694 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3697 data_size = PTR_DIFF(pdata,(*ppdata));
3700 case SMB_FILE_INTERNAL_INFORMATION:
3701 /* This should be an index number - looks like
3704 I think this causes us to fail the IFSKIT
3705 BasicFileInformationTest. -tpot */
3707 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3708 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3709 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3713 case SMB_FILE_ACCESS_INFORMATION:
3714 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3715 SIVAL(pdata,0,access_mask);
3719 case SMB_FILE_NAME_INFORMATION:
3720 /* Pathname with leading '\'. */
3723 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3724 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3725 SIVAL(pdata,0,byte_len);
3726 data_size = 4 + byte_len;
3730 case SMB_FILE_DISPOSITION_INFORMATION:
3731 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3733 SCVAL(pdata,0,delete_pending);
3736 case SMB_FILE_POSITION_INFORMATION:
3737 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3739 SOFF_T(pdata,0,pos);
3742 case SMB_FILE_MODE_INFORMATION:
3743 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3744 SIVAL(pdata,0,mode);
3748 case SMB_FILE_ALIGNMENT_INFORMATION:
3749 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3750 SIVAL(pdata,0,0); /* No alignment needed. */
3756 * NT4 server just returns "invalid query" to this - if we try to answer
3757 * it then NTws gets a BSOD! (tridge).
3758 * W2K seems to want this. JRA.
3760 case SMB_QUERY_FILE_STREAM_INFO:
3762 case SMB_FILE_STREAM_INFORMATION:
3763 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3767 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3768 SIVAL(pdata,0,0); /* ??? */
3769 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3770 SOFF_T(pdata,8,file_size);
3771 SIVAL(pdata,16,allocation_size);
3772 SIVAL(pdata,20,0); /* ??? */
3773 data_size = 24 + byte_len;
3777 case SMB_QUERY_COMPRESSION_INFO:
3778 case SMB_FILE_COMPRESSION_INFORMATION:
3779 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3780 SOFF_T(pdata,0,file_size);
3781 SIVAL(pdata,8,0); /* ??? */
3782 SIVAL(pdata,12,0); /* ??? */
3786 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3787 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3788 put_long_date_timespec(pdata,create_time_ts);
3789 put_long_date_timespec(pdata+8,atime_ts);
3790 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3791 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3792 SIVAL(pdata,32,allocation_size);
3793 SOFF_T(pdata,40,file_size);
3794 SIVAL(pdata,48,mode);
3795 SIVAL(pdata,52,0); /* ??? */
3799 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3800 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3801 SIVAL(pdata,0,mode);
3807 * CIFS UNIX Extensions.
3810 case SMB_QUERY_FILE_UNIX_BASIC:
3812 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3813 data_size = PTR_DIFF(pdata,(*ppdata));
3817 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3819 for (i=0; i<100; i++)
3820 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3826 case SMB_QUERY_FILE_UNIX_INFO2:
3828 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3829 data_size = PTR_DIFF(pdata,(*ppdata));
3833 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3835 for (i=0; i<100; i++)
3836 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3842 case SMB_QUERY_FILE_UNIX_LINK:
3846 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3848 if(!S_ISLNK(sbuf.st_mode))
3849 return(UNIXERROR(ERRSRV,ERRbadlink));
3851 return(UNIXERROR(ERRDOS,ERRbadlink));
3853 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3855 return(UNIXERROR(ERRDOS,ERRnoaccess));
3857 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3859 data_size = PTR_DIFF(pdata,(*ppdata));
3864 #if defined(HAVE_POSIX_ACLS)
3865 case SMB_QUERY_POSIX_ACL:
3867 SMB_ACL_T file_acl = NULL;
3868 SMB_ACL_T def_acl = NULL;
3869 uint16 num_file_acls = 0;
3870 uint16 num_def_acls = 0;
3872 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3873 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3875 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3878 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3879 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3881 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3884 if (S_ISDIR(sbuf.st_mode)) {
3885 if (fsp && fsp->is_directory) {
3886 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3888 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3890 def_acl = free_empty_sys_acl(conn, def_acl);
3893 num_file_acls = count_acl_entries(conn, file_acl);
3894 num_def_acls = count_acl_entries(conn, def_acl);
3896 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3897 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3899 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3900 SMB_POSIX_ACL_HEADER_SIZE) ));
3902 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3905 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3907 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3910 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3911 SSVAL(pdata,2,num_file_acls);
3912 SSVAL(pdata,4,num_def_acls);
3913 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3915 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3918 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3920 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3922 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3924 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3927 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3929 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3933 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3936 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3938 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3944 case SMB_QUERY_POSIX_LOCK:
3946 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3948 SMB_BIG_UINT offset;
3950 enum brl_type lock_type;
3952 if (total_data != POSIX_LOCK_DATA_SIZE) {
3953 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3956 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3957 case POSIX_LOCK_TYPE_READ:
3958 lock_type = READ_LOCK;
3960 case POSIX_LOCK_TYPE_WRITE:
3961 lock_type = WRITE_LOCK;
3963 case POSIX_LOCK_TYPE_UNLOCK:
3965 /* There's no point in asking for an unlock... */
3966 talloc_destroy(data_ctx);
3967 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3970 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3971 #if defined(HAVE_LONGLONG)
3972 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3973 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3974 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3975 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3976 #else /* HAVE_LONGLONG */
3977 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3978 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3979 #endif /* HAVE_LONGLONG */
3981 status = query_lock(fsp,
3988 if (ERROR_WAS_LOCK_DENIED(status)) {
3989 /* Here we need to report who has it locked... */
3990 data_size = POSIX_LOCK_DATA_SIZE;
3992 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3993 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3994 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3995 #if defined(HAVE_LONGLONG)
3996 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3997 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3998 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3999 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4000 #else /* HAVE_LONGLONG */
4001 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4002 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4003 #endif /* HAVE_LONGLONG */
4005 } else if (NT_STATUS_IS_OK(status)) {
4006 /* For success we just return a copy of what we sent
4007 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4008 data_size = POSIX_LOCK_DATA_SIZE;
4009 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4010 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4012 return ERROR_NT(status);
4018 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4021 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4026 /****************************************************************************
4027 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4029 ****************************************************************************/
4031 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4033 SMB_STRUCT_STAT sbuf1, sbuf2;
4034 pstring last_component_oldname;
4035 pstring last_component_newname;
4036 NTSTATUS status = NT_STATUS_OK;
4041 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4042 if (!NT_STATUS_IS_OK(status)) {
4046 status = check_name(conn, oldname);
4047 if (!NT_STATUS_IS_OK(status)) {
4051 /* source must already exist. */
4052 if (!VALID_STAT(sbuf1)) {
4053 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4056 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4057 if (!NT_STATUS_IS_OK(status)) {
4061 status = check_name(conn, newname);
4062 if (!NT_STATUS_IS_OK(status)) {
4066 /* Disallow if newname already exists. */
4067 if (VALID_STAT(sbuf2)) {
4068 return NT_STATUS_OBJECT_NAME_COLLISION;
4071 /* No links from a directory. */
4072 if (S_ISDIR(sbuf1.st_mode)) {
4073 return NT_STATUS_FILE_IS_A_DIRECTORY;
4076 /* Ensure this is within the share. */
4077 status = reduce_name(conn, oldname);
4078 if (!NT_STATUS_IS_OK(status)) {
4082 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4084 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4085 status = map_nt_error_from_unix(errno);
4086 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4087 nt_errstr(status), newname, oldname));
4093 /****************************************************************************
4094 Deal with setting the time from any of the setfilepathinfo functions.
4095 ****************************************************************************/
4097 static NTSTATUS smb_set_file_time(connection_struct *conn,
4100 const SMB_STRUCT_STAT *psbuf,
4101 struct timespec ts[2])
4104 FILE_NOTIFY_CHANGE_LAST_ACCESS
4105 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4108 if (!VALID_STAT(*psbuf)) {
4109 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4112 /* get some defaults (no modifications) if any info is zero or -1. */
4113 if (null_timespec(ts[0])) {
4114 ts[0] = get_atimespec(psbuf);
4115 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4118 if (null_timespec(ts[1])) {
4119 ts[1] = get_mtimespec(psbuf);
4120 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4123 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4124 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4127 * Try and set the times of this file if
4128 * they are different from the current values.
4132 struct timespec mts = get_mtimespec(psbuf);
4133 struct timespec ats = get_atimespec(psbuf);
4134 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4135 return NT_STATUS_OK;
4141 * This was a setfileinfo on an open file.
4142 * NT does this a lot. We also need to
4143 * set the time here, as it can be read by
4144 * FindFirst/FindNext and with the patch for bug #2045
4145 * in smbd/fileio.c it ensures that this timestamp is
4146 * kept sticky even after a write. We save the request
4147 * away and will set it on file close and after a write. JRA.
4150 if (!null_timespec(ts[1])) {
4151 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4152 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4153 fsp_set_pending_modtime(fsp, ts[1]);
4157 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4159 if(file_ntimes(conn, fname, ts)!=0) {
4160 return map_nt_error_from_unix(errno);
4163 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4165 return NT_STATUS_OK;
4168 /****************************************************************************
4169 Deal with setting the dosmode from any of the setfilepathinfo functions.
4170 ****************************************************************************/
4172 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4174 SMB_STRUCT_STAT *psbuf,
4177 if (!VALID_STAT(*psbuf)) {
4178 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4182 if (S_ISDIR(psbuf->st_mode)) {
4189 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4191 /* check the mode isn't different, before changing it */
4192 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4194 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4195 fname, (unsigned int)dosmode ));
4197 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4198 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4199 fname, strerror(errno)));
4200 return map_nt_error_from_unix(errno);
4203 return NT_STATUS_OK;
4206 /****************************************************************************
4207 Deal with setting the size from any of the setfilepathinfo functions.
4208 ****************************************************************************/
4210 static NTSTATUS smb_set_file_size(connection_struct *conn,
4213 SMB_STRUCT_STAT *psbuf,
4216 NTSTATUS status = NT_STATUS_OK;
4217 files_struct *new_fsp = NULL;
4219 if (!VALID_STAT(*psbuf)) {
4220 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4223 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4225 if (size == get_file_size(*psbuf)) {
4226 return NT_STATUS_OK;
4229 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4230 fname, (double)size ));
4232 if (fsp && fsp->fh->fd != -1) {
4233 /* Handle based call. */
4234 if (vfs_set_filelen(fsp, size) == -1) {
4235 return map_nt_error_from_unix(errno);
4237 return NT_STATUS_OK;
4240 status = open_file_ntcreate(conn, fname, psbuf,
4242 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4245 FILE_ATTRIBUTE_NORMAL,
4246 FORCE_OPLOCK_BREAK_TO_NONE,
4249 if (!NT_STATUS_IS_OK(status)) {
4250 /* NB. We check for open_was_deferred in the caller. */
4254 if (vfs_set_filelen(new_fsp, size) == -1) {
4255 status = map_nt_error_from_unix(errno);
4256 close_file(new_fsp,NORMAL_CLOSE);
4260 close_file(new_fsp,NORMAL_CLOSE);
4261 return NT_STATUS_OK;
4264 /****************************************************************************
4265 Deal with SMB_INFO_SET_EA.
4266 ****************************************************************************/
4268 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4274 struct ea_list *ea_list = NULL;
4275 TALLOC_CTX *ctx = NULL;
4276 NTSTATUS status = NT_STATUS_OK;
4278 if (total_data < 10) {
4280 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4281 length. They seem to have no effect. Bug #3212. JRA */
4283 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4284 /* We're done. We only get EA info in this call. */
4285 return NT_STATUS_OK;
4288 return NT_STATUS_INVALID_PARAMETER;
4291 if (IVAL(pdata,0) > total_data) {
4292 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4293 IVAL(pdata,0), (unsigned int)total_data));
4294 return NT_STATUS_INVALID_PARAMETER;
4297 ctx = talloc_init("SMB_INFO_SET_EA");
4299 return NT_STATUS_NO_MEMORY;
4301 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4303 talloc_destroy(ctx);
4304 return NT_STATUS_INVALID_PARAMETER;
4306 status = set_ea(conn, fsp, fname, ea_list);
4307 talloc_destroy(ctx);
4312 /****************************************************************************
4313 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4314 ****************************************************************************/
4316 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4321 SMB_STRUCT_STAT *psbuf)
4323 NTSTATUS status = NT_STATUS_OK;
4324 BOOL delete_on_close;
4327 if (total_data < 1) {
4328 return NT_STATUS_INVALID_PARAMETER;
4332 return NT_STATUS_INVALID_HANDLE;
4335 delete_on_close = (CVAL(pdata,0) ? True : False);
4336 dosmode = dos_mode(conn, fname, psbuf);
4338 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4339 "delete_on_close = %u\n",
4341 (unsigned int)dosmode,
4342 (unsigned int)delete_on_close ));
4344 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4346 if (!NT_STATUS_IS_OK(status)) {
4350 /* The set is across all open files on this dev/inode pair. */
4351 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4352 return NT_STATUS_ACCESS_DENIED;
4354 return NT_STATUS_OK;
4357 /****************************************************************************
4358 Deal with SMB_FILE_POSITION_INFORMATION.
4359 ****************************************************************************/
4361 static NTSTATUS smb_file_position_information(connection_struct *conn,
4366 SMB_BIG_UINT position_information;
4368 if (total_data < 8) {
4369 return NT_STATUS_INVALID_PARAMETER;
4373 /* Ignore on pathname based set. */
4374 return NT_STATUS_OK;
4377 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4378 #ifdef LARGE_SMB_OFF_T
4379 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4380 #else /* LARGE_SMB_OFF_T */
4381 if (IVAL(pdata,4) != 0) {
4382 /* more than 32 bits? */
4383 return NT_STATUS_INVALID_PARAMETER;
4385 #endif /* LARGE_SMB_OFF_T */
4387 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4388 fsp->fsp_name, (double)position_information ));
4389 fsp->fh->position_information = position_information;
4390 return NT_STATUS_OK;
4393 /****************************************************************************
4394 Deal with SMB_FILE_MODE_INFORMATION.
4395 ****************************************************************************/
4397 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4403 if (total_data < 4) {
4404 return NT_STATUS_INVALID_PARAMETER;
4406 mode = IVAL(pdata,0);
4407 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4408 return NT_STATUS_INVALID_PARAMETER;
4410 return NT_STATUS_OK;
4413 /****************************************************************************
4414 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4415 ****************************************************************************/
4417 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4423 pstring link_target;
4424 const char *newname = fname;
4425 NTSTATUS status = NT_STATUS_OK;
4427 /* Set a symbolic link. */
4428 /* Don't allow this if follow links is false. */
4430 if (total_data == 0) {
4431 return NT_STATUS_INVALID_PARAMETER;
4434 if (!lp_symlinks(SNUM(conn))) {
4435 return NT_STATUS_ACCESS_DENIED;
4438 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4440 /* !widelinks forces the target path to be within the share. */
4441 /* This means we can interpret the target as a pathname. */
4442 if (!lp_widelinks(SNUM(conn))) {
4444 char *last_dirp = NULL;
4446 if (*link_target == '/') {
4447 /* No absolute paths allowed. */
4448 return NT_STATUS_ACCESS_DENIED;
4450 pstrcpy(rel_name, newname);
4451 last_dirp = strrchr_m(rel_name, '/');
4453 last_dirp[1] = '\0';
4455 pstrcpy(rel_name, "./");
4457 pstrcat(rel_name, link_target);
4459 status = check_name(conn, rel_name);
4460 if (!NT_STATUS_IS_OK(status)) {
4465 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4466 newname, link_target ));
4468 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4469 return map_nt_error_from_unix(errno);
4472 return NT_STATUS_OK;
4475 /****************************************************************************
4476 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4477 ****************************************************************************/
4479 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4487 NTSTATUS status = NT_STATUS_OK;
4489 /* Set a hard link. */
4490 if (total_data == 0) {
4491 return NT_STATUS_INVALID_PARAMETER;
4494 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4495 if (!NT_STATUS_IS_OK(status)) {
4499 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4500 if (!NT_STATUS_IS_OK(status)) {
4504 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4507 return hardlink_internals(conn, oldname, fname);
4510 /****************************************************************************
4511 Deal with SMB_FILE_RENAME_INFORMATION.
4512 ****************************************************************************/
4514 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4523 /* uint32 root_fid; */ /* Not used */
4527 BOOL dest_has_wcard = False;
4528 NTSTATUS status = NT_STATUS_OK;
4531 if (total_data < 13) {
4532 return NT_STATUS_INVALID_PARAMETER;
4535 overwrite = (CVAL(pdata,0) ? True : False);
4536 /* root_fid = IVAL(pdata,4); */
4537 len = IVAL(pdata,8);
4539 if (len > (total_data - 12) || (len == 0)) {
4540 return NT_STATUS_INVALID_PARAMETER;
4543 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4544 if (!NT_STATUS_IS_OK(status)) {
4548 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4549 if (!NT_STATUS_IS_OK(status)) {
4553 /* Check the new name has no '/' characters. */
4554 if (strchr_m(newname, '/')) {
4555 return NT_STATUS_NOT_SUPPORTED;
4558 /* Create the base directory. */
4559 pstrcpy(base_name, fname);
4560 p = strrchr_m(base_name, '/');
4564 /* Append the new name. */
4565 pstrcat(base_name, "/");
4566 pstrcat(base_name, newname);
4569 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4570 fsp->fnum, fsp->fsp_name, base_name ));
4571 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4573 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4575 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4581 /****************************************************************************
4582 Deal with SMB_SET_POSIX_ACL.
4583 ****************************************************************************/
4585 #if defined(HAVE_POSIX_ACLS)
4586 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4591 SMB_STRUCT_STAT *psbuf)
4593 uint16 posix_acl_version;
4594 uint16 num_file_acls;
4595 uint16 num_def_acls;
4596 BOOL valid_file_acls = True;
4597 BOOL valid_def_acls = True;
4599 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4600 return NT_STATUS_INVALID_PARAMETER;
4602 posix_acl_version = SVAL(pdata,0);
4603 num_file_acls = SVAL(pdata,2);
4604 num_def_acls = SVAL(pdata,4);
4606 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4607 valid_file_acls = False;
4611 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4612 valid_def_acls = False;
4616 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4617 return NT_STATUS_INVALID_PARAMETER;
4620 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4621 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4622 return NT_STATUS_INVALID_PARAMETER;
4625 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4626 fname ? fname : fsp->fsp_name,
4627 (unsigned int)num_file_acls,
4628 (unsigned int)num_def_acls));
4630 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4631 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4632 return map_nt_error_from_unix(errno);
4635 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4636 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4637 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4638 return map_nt_error_from_unix(errno);
4640 return NT_STATUS_OK;
4644 /****************************************************************************
4645 Deal with SMB_SET_POSIX_LOCK.
4646 ****************************************************************************/
4648 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4656 SMB_BIG_UINT offset;
4658 BOOL blocking_lock = False;
4659 enum brl_type lock_type;
4660 NTSTATUS status = NT_STATUS_OK;
4662 if (fsp == NULL || fsp->fh->fd == -1) {
4663 return NT_STATUS_INVALID_HANDLE;
4666 if (total_data != POSIX_LOCK_DATA_SIZE) {
4667 return NT_STATUS_INVALID_PARAMETER;
4670 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4671 case POSIX_LOCK_TYPE_READ:
4672 lock_type = READ_LOCK;
4674 case POSIX_LOCK_TYPE_WRITE:
4675 /* Return the right POSIX-mappable error code for files opened read-only. */
4676 if (!fsp->can_write) {
4677 return NT_STATUS_INVALID_HANDLE;
4679 lock_type = WRITE_LOCK;
4681 case POSIX_LOCK_TYPE_UNLOCK:
4682 lock_type = UNLOCK_LOCK;
4685 return NT_STATUS_INVALID_PARAMETER;
4688 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4689 blocking_lock = False;
4690 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4691 blocking_lock = True;
4693 return NT_STATUS_INVALID_PARAMETER;
4696 if (!lp_blocking_locks(SNUM(conn))) {
4697 blocking_lock = False;
4700 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4701 #if defined(HAVE_LONGLONG)
4702 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4703 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4704 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4705 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4706 #else /* HAVE_LONGLONG */
4707 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4708 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4709 #endif /* HAVE_LONGLONG */
4711 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4712 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4714 (unsigned int)lock_type,
4715 (unsigned int)lock_pid,
4719 if (lock_type == UNLOCK_LOCK) {
4720 status = do_unlock(fsp,
4726 struct byte_range_lock *br_lck = do_lock(fsp,
4735 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4737 * A blocking lock was requested. Package up
4738 * this smb into a queued request and push it
4739 * onto the blocking lock queue.
4741 if(push_blocking_lock_request(br_lck,
4744 -1, /* infinite timeout. */
4751 TALLOC_FREE(br_lck);
4755 TALLOC_FREE(br_lck);
4761 /****************************************************************************
4762 Deal with SMB_INFO_STANDARD.
4763 ****************************************************************************/
4765 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4770 const SMB_STRUCT_STAT *psbuf)
4772 struct timespec ts[2];
4774 if (total_data < 12) {
4775 return NT_STATUS_INVALID_PARAMETER;
4779 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4781 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4783 DEBUG(10,("smb_set_info_standard: file %s\n",
4784 fname ? fname : fsp->fsp_name ));
4786 return smb_set_file_time(conn,
4793 /****************************************************************************
4794 Deal with SMB_SET_FILE_BASIC_INFO.
4795 ****************************************************************************/
4797 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4802 SMB_STRUCT_STAT *psbuf)
4804 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4805 struct timespec write_time;
4806 struct timespec changed_time;
4808 struct timespec ts[2];
4809 NTSTATUS status = NT_STATUS_OK;
4811 if (total_data < 36) {
4812 return NT_STATUS_INVALID_PARAMETER;
4815 /* Set the attributes */
4816 dosmode = IVAL(pdata,32);
4817 status = smb_set_file_dosmode(conn,
4821 if (!NT_STATUS_IS_OK(status)) {
4825 /* Ignore create time at offset pdata. */
4828 ts[0] = interpret_long_date(pdata+8);
4830 write_time = interpret_long_date(pdata+16);
4831 changed_time = interpret_long_date(pdata+24);
4834 ts[1] = timespec_min(&write_time, &changed_time);
4836 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4840 /* Prefer a defined time to an undefined one. */
4841 if (null_timespec(ts[1])) {
4842 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4845 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4846 fname ? fname : fsp->fsp_name ));
4848 return smb_set_file_time(conn,
4855 /****************************************************************************
4856 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4857 ****************************************************************************/
4859 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4864 SMB_STRUCT_STAT *psbuf)
4866 SMB_BIG_UINT allocation_size = 0;
4867 NTSTATUS status = NT_STATUS_OK;
4868 files_struct *new_fsp = NULL;
4870 if (!VALID_STAT(*psbuf)) {
4871 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4874 if (total_data < 8) {
4875 return NT_STATUS_INVALID_PARAMETER;
4878 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4879 #ifdef LARGE_SMB_OFF_T
4880 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4881 #else /* LARGE_SMB_OFF_T */
4882 if (IVAL(pdata,4) != 0) {
4883 /* more than 32 bits? */
4884 return NT_STATUS_INVALID_PARAMETER;
4886 #endif /* LARGE_SMB_OFF_T */
4888 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4889 fname, (double)allocation_size ));
4891 if (allocation_size) {
4892 allocation_size = smb_roundup(conn, allocation_size);
4895 if(allocation_size == get_file_size(*psbuf)) {
4896 return NT_STATUS_OK;
4899 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4900 fname, (double)allocation_size ));
4902 if (fsp && fsp->fh->fd != -1) {
4903 /* Open file handle. */
4904 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4905 return map_nt_error_from_unix(errno);
4907 return NT_STATUS_OK;
4910 /* Pathname or stat or directory file. */
4912 status = open_file_ntcreate(conn, fname, psbuf,
4914 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4917 FILE_ATTRIBUTE_NORMAL,
4918 FORCE_OPLOCK_BREAK_TO_NONE,
4921 if (!NT_STATUS_IS_OK(status)) {
4922 /* NB. We check for open_was_deferred in the caller. */
4925 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4926 status = map_nt_error_from_unix(errno);
4927 close_file(new_fsp,NORMAL_CLOSE);
4931 close_file(new_fsp,NORMAL_CLOSE);
4932 return NT_STATUS_OK;
4935 /****************************************************************************
4936 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4937 ****************************************************************************/
4939 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4944 SMB_STRUCT_STAT *psbuf)
4948 if (total_data < 8) {
4949 return NT_STATUS_INVALID_PARAMETER;
4952 size = IVAL(pdata,0);
4953 #ifdef LARGE_SMB_OFF_T
4954 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4955 #else /* LARGE_SMB_OFF_T */
4956 if (IVAL(pdata,4) != 0) {
4957 /* more than 32 bits? */
4958 return NT_STATUS_INVALID_PARAMETER;
4960 #endif /* LARGE_SMB_OFF_T */
4961 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4962 "file %s to %.0f\n", fname, (double)size ));
4964 return smb_set_file_size(conn,
4971 /****************************************************************************
4972 Allow a UNIX info mknod.
4973 ****************************************************************************/
4975 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4979 SMB_STRUCT_STAT *psbuf)
4981 uint32 file_type = IVAL(pdata,56);
4982 #if defined(HAVE_MAKEDEV)
4983 uint32 dev_major = IVAL(pdata,60);
4984 uint32 dev_minor = IVAL(pdata,68);
4986 SMB_DEV_T dev = (SMB_DEV_T)0;
4987 uint32 raw_unixmode = IVAL(pdata,84);
4991 if (total_data < 100) {
4992 return NT_STATUS_INVALID_PARAMETER;
4995 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4996 if (!NT_STATUS_IS_OK(status)) {
5000 #if defined(HAVE_MAKEDEV)
5001 dev = makedev(dev_major, dev_minor);
5004 switch (file_type) {
5005 #if defined(S_IFIFO)
5006 case UNIX_TYPE_FIFO:
5007 unixmode |= S_IFIFO;
5010 #if defined(S_IFSOCK)
5011 case UNIX_TYPE_SOCKET:
5012 unixmode |= S_IFSOCK;
5015 #if defined(S_IFCHR)
5016 case UNIX_TYPE_CHARDEV:
5017 unixmode |= S_IFCHR;
5020 #if defined(S_IFBLK)
5021 case UNIX_TYPE_BLKDEV:
5022 unixmode |= S_IFBLK;
5026 return NT_STATUS_INVALID_PARAMETER;
5029 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5030 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5032 /* Ok - do the mknod. */
5033 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5034 return map_nt_error_from_unix(errno);
5037 /* If any of the other "set" calls fail we
5038 * don't want to end up with a half-constructed mknod.
5041 if (lp_inherit_perms(SNUM(conn))) {
5043 conn, parent_dirname(fname),
5047 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5048 status = map_nt_error_from_unix(errno);
5049 SMB_VFS_UNLINK(conn,fname);
5052 return NT_STATUS_OK;
5055 /****************************************************************************
5056 Deal with SMB_SET_FILE_UNIX_BASIC.
5057 ****************************************************************************/
5059 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5064 SMB_STRUCT_STAT *psbuf)
5066 struct timespec ts[2];
5067 uint32 raw_unixmode;
5070 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5071 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5072 NTSTATUS status = NT_STATUS_OK;
5073 BOOL delete_on_fail = False;
5074 enum perm_type ptype;
5076 if (total_data < 100) {
5077 return NT_STATUS_INVALID_PARAMETER;
5080 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5081 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5082 size=IVAL(pdata,0); /* first 8 Bytes are size */
5083 #ifdef LARGE_SMB_OFF_T
5084 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5085 #else /* LARGE_SMB_OFF_T */
5086 if (IVAL(pdata,4) != 0) {
5087 /* more than 32 bits? */
5088 return NT_STATUS_INVALID_PARAMETER;
5090 #endif /* LARGE_SMB_OFF_T */
5093 ts[0] = interpret_long_date(pdata+24); /* access_time */
5094 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5095 set_owner = (uid_t)IVAL(pdata,40);
5096 set_grp = (gid_t)IVAL(pdata,48);
5097 raw_unixmode = IVAL(pdata,84);
5099 if (VALID_STAT(*psbuf)) {
5100 if (S_ISDIR(psbuf->st_mode)) {
5101 ptype = PERM_EXISTING_DIR;
5103 ptype = PERM_EXISTING_FILE;
5106 ptype = PERM_NEW_FILE;
5109 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5110 if (!NT_STATUS_IS_OK(status)) {
5114 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5115 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5116 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5118 if (!VALID_STAT(*psbuf)) {
5120 * The only valid use of this is to create character and block
5121 * devices, and named pipes. This is deprecated (IMHO) and
5122 * a new info level should be used for mknod. JRA.
5125 status = smb_unix_mknod(conn,
5130 if (!NT_STATUS_IS_OK(status)) {
5134 /* Ensure we don't try and change anything else. */
5135 raw_unixmode = SMB_MODE_NO_CHANGE;
5136 size = get_file_size(*psbuf);
5137 ts[0] = get_atimespec(psbuf);
5138 ts[1] = get_mtimespec(psbuf);
5140 * We continue here as we might want to change the
5143 delete_on_fail = True;
5147 /* Horrible backwards compatibility hack as an old server bug
5148 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5152 size = get_file_size(*psbuf);
5157 * Deal with the UNIX specific mode set.
5160 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5161 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5162 (unsigned int)unixmode, fname ));
5163 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5164 return map_nt_error_from_unix(errno);
5169 * Deal with the UNIX specific uid set.
5172 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5173 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5174 (unsigned int)set_owner, fname ));
5175 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5176 status = map_nt_error_from_unix(errno);
5177 if (delete_on_fail) {
5178 SMB_VFS_UNLINK(conn,fname);
5185 * Deal with the UNIX specific gid set.
5188 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5189 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5190 (unsigned int)set_owner, fname ));
5191 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5192 status = map_nt_error_from_unix(errno);
5193 if (delete_on_fail) {
5194 SMB_VFS_UNLINK(conn,fname);
5200 /* Deal with any size changes. */
5202 status = smb_set_file_size(conn,
5207 if (!NT_STATUS_IS_OK(status)) {
5211 /* Deal with any time changes. */
5213 return smb_set_file_time(conn,
5220 /****************************************************************************
5221 Deal with SMB_SET_FILE_UNIX_INFO2.
5222 ****************************************************************************/
5224 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5229 SMB_STRUCT_STAT *psbuf)
5235 if (total_data < 116) {
5236 return NT_STATUS_INVALID_PARAMETER;
5239 /* Start by setting all the fields that are common between UNIX_BASIC
5242 status = smb_set_file_unix_basic(conn, pdata, total_data,
5244 if (!NT_STATUS_IS_OK(status)) {
5248 smb_fflags = IVAL(pdata, 108);
5249 smb_fmask = IVAL(pdata, 112);
5251 /* NB: We should only attempt to alter the file flags if the client
5252 * sends a non-zero mask.
5254 if (smb_fmask != 0) {
5255 int stat_fflags = 0;
5257 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5259 /* Client asked to alter a flag we don't understand. */
5260 return NT_STATUS_INVALID_PARAMETER;
5263 if (fsp && fsp->fh->fd != -1) {
5264 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5265 return NT_STATUS_NOT_SUPPORTED;
5267 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5268 return map_nt_error_from_unix(errno);
5273 /* XXX: need to add support for changing the create_time here. You
5274 * can do this for paths on Darwin with setattrlist(2). The right way
5275 * to hook this up is probably by extending the VFS utimes interface.
5278 return NT_STATUS_OK;
5281 /****************************************************************************
5282 Create a directory with POSIX semantics.
5283 ****************************************************************************/
5285 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5289 SMB_STRUCT_STAT *psbuf,
5290 int *pdata_return_size)
5292 NTSTATUS status = NT_STATUS_OK;
5293 uint32 raw_unixmode = 0;
5294 uint32 mod_unixmode = 0;
5295 mode_t unixmode = (mode_t)0;
5296 files_struct *fsp = NULL;
5297 uint16 info_level_return = 0;
5299 char *pdata = *ppdata;
5301 if (total_data < 18) {
5302 return NT_STATUS_INVALID_PARAMETER;
5305 raw_unixmode = IVAL(pdata,8);
5306 /* Next 4 bytes are not yet defined. */
5308 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5309 if (!NT_STATUS_IS_OK(status)) {
5313 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5315 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5316 fname, (unsigned int)unixmode ));
5318 status = open_directory(conn,
5321 FILE_READ_ATTRIBUTES, /* Just a stat open */
5322 FILE_SHARE_NONE, /* Ignored for stat opens */
5329 if (NT_STATUS_IS_OK(status)) {
5330 close_file(fsp, NORMAL_CLOSE);
5333 info_level_return = SVAL(pdata,16);
5335 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5336 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5337 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5338 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5340 *pdata_return_size = 12;
5343 /* Realloc the data size */
5344 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5345 if (*ppdata == NULL) {
5346 *pdata_return_size = 0;
5347 return NT_STATUS_NO_MEMORY;
5350 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5351 SSVAL(pdata,2,0); /* No fnum. */
5352 SIVAL(pdata,4,info); /* Was directory created. */
5354 switch (info_level_return) {
5355 case SMB_QUERY_FILE_UNIX_BASIC:
5356 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5357 SSVAL(pdata,10,0); /* Padding. */
5358 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5360 case SMB_QUERY_FILE_UNIX_INFO2:
5361 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5362 SSVAL(pdata,10,0); /* Padding. */
5363 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5366 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5367 SSVAL(pdata,10,0); /* Padding. */
5374 /****************************************************************************
5375 Open/Create a file with POSIX semantics.
5376 ****************************************************************************/
5378 static NTSTATUS smb_posix_open(connection_struct *conn,
5382 SMB_STRUCT_STAT *psbuf,
5383 int *pdata_return_size)
5385 BOOL extended_oplock_granted = False;
5386 char *pdata = *ppdata;
5388 uint32 wire_open_mode = 0;
5389 uint32 raw_unixmode = 0;
5390 uint32 mod_unixmode = 0;
5391 uint32 create_disp = 0;
5392 uint32 access_mask = 0;
5393 uint32 create_options = 0;
5394 NTSTATUS status = NT_STATUS_OK;
5395 mode_t unixmode = (mode_t)0;
5396 files_struct *fsp = NULL;
5397 int oplock_request = 0;
5399 uint16 info_level_return = 0;
5401 if (total_data < 18) {
5402 return NT_STATUS_INVALID_PARAMETER;
5405 flags = IVAL(pdata,0);
5406 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5407 if (oplock_request) {
5408 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5411 wire_open_mode = IVAL(pdata,4);
5413 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5414 return smb_posix_mkdir(conn,
5422 switch (wire_open_mode & SMB_ACCMODE) {
5424 access_mask = FILE_READ_DATA;
5427 access_mask = FILE_WRITE_DATA;
5430 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5433 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5434 (unsigned int)wire_open_mode ));
5435 return NT_STATUS_INVALID_PARAMETER;
5438 wire_open_mode &= ~SMB_ACCMODE;
5440 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5441 create_disp = FILE_CREATE;
5442 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5443 create_disp = FILE_OVERWRITE_IF;
5444 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5445 create_disp = FILE_OPEN_IF;
5447 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5448 (unsigned int)wire_open_mode ));
5449 return NT_STATUS_INVALID_PARAMETER;
5452 raw_unixmode = IVAL(pdata,8);
5453 /* Next 4 bytes are not yet defined. */
5455 status = unix_perms_from_wire(conn,
5458 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5461 if (!NT_STATUS_IS_OK(status)) {
5465 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5467 if (wire_open_mode & SMB_O_SYNC) {
5468 create_options |= FILE_WRITE_THROUGH;
5470 if (wire_open_mode & SMB_O_APPEND) {
5471 access_mask |= FILE_APPEND_DATA;
5473 if (wire_open_mode & SMB_O_DIRECT) {
5474 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5477 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5479 (unsigned int)wire_open_mode,
5480 (unsigned int)unixmode ));
5482 status = open_file_ntcreate(conn,
5486 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5488 0, /* no create options yet. */
5494 if (!NT_STATUS_IS_OK(status)) {
5498 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5499 extended_oplock_granted = True;
5502 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5503 extended_oplock_granted = True;
5506 info_level_return = SVAL(pdata,16);
5508 /* Allocate the correct return size. */
5510 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5511 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5512 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5513 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5515 *pdata_return_size = 12;
5518 /* Realloc the data size */
5519 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5520 if (*ppdata == NULL) {
5521 close_file(fsp,ERROR_CLOSE);
5522 *pdata_return_size = 0;
5523 return NT_STATUS_NO_MEMORY;
5526 if (extended_oplock_granted) {
5527 if (flags & REQUEST_BATCH_OPLOCK) {
5528 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5530 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5532 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5533 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5535 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5538 SSVAL(pdata,2,fsp->fnum);
5539 SIVAL(pdata,4,info); /* Was file created etc. */
5541 switch (info_level_return) {
5542 case SMB_QUERY_FILE_UNIX_BASIC:
5543 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5544 SSVAL(pdata,10,0); /* padding. */
5545 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5547 case SMB_QUERY_FILE_UNIX_INFO2:
5548 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5549 SSVAL(pdata,10,0); /* padding. */
5550 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5553 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5554 SSVAL(pdata,10,0); /* padding. */
5557 return NT_STATUS_OK;
5560 /****************************************************************************
5561 Delete a file with POSIX semantics.
5562 ****************************************************************************/
5564 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5568 SMB_STRUCT_STAT *psbuf)
5570 NTSTATUS status = NT_STATUS_OK;
5571 files_struct *fsp = NULL;
5575 if (total_data < 2) {
5576 return NT_STATUS_INVALID_PARAMETER;
5579 flags = SVAL(pdata,0);
5581 if (!VALID_STAT(*psbuf)) {
5582 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5585 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5586 !VALID_STAT_OF_DIR(*psbuf)) {
5587 return NT_STATUS_NOT_A_DIRECTORY;
5590 DEBUG(10,("smb_posix_unlink: %s %s\n",
5591 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5594 if (VALID_STAT_OF_DIR(*psbuf)) {
5595 status = open_directory(conn,
5599 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5601 FILE_DELETE_ON_CLOSE,
5602 FILE_FLAG_POSIX_SEMANTICS|0777,
5608 status = open_file_ntcreate(conn,
5612 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5615 FILE_FLAG_POSIX_SEMANTICS|0777,
5616 0, /* No oplock, but break existing ones. */
5620 * For file opens we must set the delete on close
5624 if (!NT_STATUS_IS_OK(status)) {
5628 status = smb_set_file_disposition_info(conn,
5636 if (!NT_STATUS_IS_OK(status)) {
5639 return close_file(fsp, NORMAL_CLOSE);
5642 /****************************************************************************
5643 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5644 ****************************************************************************/
5646 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5647 unsigned int tran_call,
5648 char **pparams, int total_params, char **ppdata, int total_data,
5649 unsigned int max_data_bytes)
5651 char *params = *pparams;
5652 char *pdata = *ppdata;
5654 SMB_STRUCT_STAT sbuf;
5656 files_struct *fsp = NULL;
5657 NTSTATUS status = NT_STATUS_OK;
5658 int data_return_size = 0;
5661 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5666 if (tran_call == TRANSACT2_SETFILEINFO) {
5667 if (total_params < 4) {
5668 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5671 fsp = file_fsp(params,0);
5672 info_level = SVAL(params,2);
5674 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5676 * This is actually a SETFILEINFO on a directory
5677 * handle (returned from an NT SMB). NT5.0 seems
5678 * to do this call. JRA.
5680 pstrcpy(fname, fsp->fsp_name);
5681 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5682 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5683 return UNIXERROR(ERRDOS,ERRbadpath);
5685 } else if (fsp && fsp->print_file) {
5687 * Doing a DELETE_ON_CLOSE should cancel a print job.
5689 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5690 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5692 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5695 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5698 return (UNIXERROR(ERRDOS,ERRbadpath));
5701 * Original code - this is an open file.
5703 CHECK_FSP(fsp,conn);
5705 pstrcpy(fname, fsp->fsp_name);
5707 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5708 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5709 return(UNIXERROR(ERRDOS,ERRbadfid));
5714 if (total_params < 7) {
5715 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5718 info_level = SVAL(params,0);
5719 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5720 if (!NT_STATUS_IS_OK(status)) {
5721 return ERROR_NT(status);
5724 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5725 if (!NT_STATUS_IS_OK(status)) {
5726 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5727 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5729 return ERROR_NT(status);
5732 status = unix_convert(conn, fname, False, NULL, &sbuf);
5733 if (!NT_STATUS_IS_OK(status)) {
5734 return ERROR_NT(status);
5737 status = check_name(conn, fname);
5738 if (!NT_STATUS_IS_OK(status)) {
5739 return ERROR_NT(status);
5743 * For CIFS UNIX extensions the target name may not exist.
5746 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5747 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5748 return UNIXERROR(ERRDOS,ERRbadpath);
5752 if (!CAN_WRITE(conn)) {
5753 return ERROR_DOS(ERRSRV,ERRaccess);
5756 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5757 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5760 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5761 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5763 /* Realloc the parameter size */
5764 *pparams = (char *)SMB_REALLOC(*pparams,2);
5765 if (*pparams == NULL) {
5766 return ERROR_NT(NT_STATUS_NO_MEMORY);
5772 if (fsp && !null_timespec(fsp->pending_modtime)) {
5773 /* the pending modtime overrides the current modtime */
5774 set_mtimespec(&sbuf, fsp->pending_modtime);
5777 switch (info_level) {
5779 case SMB_INFO_STANDARD:
5781 status = smb_set_info_standard(conn,
5790 case SMB_INFO_SET_EA:
5792 status = smb_info_set_ea(conn,
5800 case SMB_SET_FILE_BASIC_INFO:
5801 case SMB_FILE_BASIC_INFORMATION:
5803 status = smb_set_file_basic_info(conn,
5812 case SMB_FILE_ALLOCATION_INFORMATION:
5813 case SMB_SET_FILE_ALLOCATION_INFO:
5815 status = smb_set_file_allocation_info(conn,
5824 case SMB_FILE_END_OF_FILE_INFORMATION:
5825 case SMB_SET_FILE_END_OF_FILE_INFO:
5827 status = smb_set_file_end_of_file_info(conn,
5836 case SMB_FILE_DISPOSITION_INFORMATION:
5837 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5840 /* JRA - We used to just ignore this on a path ?
5841 * Shouldn't this be invalid level on a pathname
5844 if (tran_call != TRANSACT2_SETFILEINFO) {
5845 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5848 status = smb_set_file_disposition_info(conn,
5857 case SMB_FILE_POSITION_INFORMATION:
5859 status = smb_file_position_information(conn,
5866 /* From tridge Samba4 :
5867 * MODE_INFORMATION in setfileinfo (I have no
5868 * idea what "mode information" on a file is - it takes a value of 0,
5869 * 2, 4 or 6. What could it be?).
5872 case SMB_FILE_MODE_INFORMATION:
5874 status = smb_file_mode_information(conn,
5881 * CIFS UNIX extensions.
5884 case SMB_SET_FILE_UNIX_BASIC:
5886 status = smb_set_file_unix_basic(conn,
5895 case SMB_SET_FILE_UNIX_INFO2:
5897 status = smb_set_file_unix_info2(conn,
5906 case SMB_SET_FILE_UNIX_LINK:
5908 if (tran_call != TRANSACT2_SETPATHINFO) {
5909 /* We must have a pathname for this. */
5910 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5912 status = smb_set_file_unix_link(conn,
5920 case SMB_SET_FILE_UNIX_HLINK:
5922 if (tran_call != TRANSACT2_SETPATHINFO) {
5923 /* We must have a pathname for this. */
5924 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5926 status = smb_set_file_unix_hlink(conn,
5935 case SMB_FILE_RENAME_INFORMATION:
5937 status = smb_file_rename_information(conn,
5947 #if defined(HAVE_POSIX_ACLS)
5948 case SMB_SET_POSIX_ACL:
5950 status = smb_set_posix_acl(conn,
5960 case SMB_SET_POSIX_LOCK:
5962 if (tran_call != TRANSACT2_SETFILEINFO) {
5963 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5965 status = smb_set_posix_lock(conn,
5974 case SMB_POSIX_PATH_OPEN:
5976 if (tran_call != TRANSACT2_SETPATHINFO) {
5977 /* We must have a pathname for this. */
5978 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5981 status = smb_posix_open(conn,
5990 case SMB_POSIX_PATH_UNLINK:
5992 if (tran_call != TRANSACT2_SETPATHINFO) {
5993 /* We must have a pathname for this. */
5994 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5997 status = smb_posix_unlink(conn,
6006 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6010 if (!NT_STATUS_IS_OK(status)) {
6011 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6012 /* We have re-scheduled this call. */
6015 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6016 /* We have re-scheduled this call. */
6019 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6020 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6022 return ERROR_NT(status);
6026 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6031 /****************************************************************************
6032 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6033 ****************************************************************************/
6035 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6036 char **pparams, int total_params, char **ppdata, int total_data,
6037 unsigned int max_data_bytes)
6039 char *params = *pparams;
6040 char *pdata = *ppdata;
6042 SMB_STRUCT_STAT sbuf;
6043 NTSTATUS status = NT_STATUS_OK;
6044 struct ea_list *ea_list = NULL;
6046 if (!CAN_WRITE(conn))
6047 return ERROR_DOS(ERRSRV,ERRaccess);
6049 if (total_params < 5) {
6050 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6053 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6054 if (!NT_STATUS_IS_OK(status)) {
6055 return ERROR_NT(status);
6058 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6060 status = unix_convert(conn, directory, False, NULL, &sbuf);
6061 if (!NT_STATUS_IS_OK(status)) {
6062 return ERROR_NT(status);
6065 status = check_name(conn, directory);
6066 if (!NT_STATUS_IS_OK(status)) {
6067 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6068 return ERROR_NT(status);
6071 /* Any data in this call is an EA list. */
6072 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6073 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6077 * OS/2 workplace shell seems to send SET_EA requests of "null"
6078 * length (4 bytes containing IVAL 4).
6079 * They seem to have no effect. Bug #3212. JRA.
6082 if (total_data != 4) {
6083 if (total_data < 10) {
6084 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6087 if (IVAL(pdata,0) > total_data) {
6088 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6089 IVAL(pdata,0), (unsigned int)total_data));
6090 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6093 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6096 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6098 } else if (IVAL(pdata,0) != 4) {
6099 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6102 status = create_directory(conn, directory);
6104 if (!NT_STATUS_IS_OK(status)) {
6105 return ERROR_NT(status);
6108 /* Try and set any given EA. */
6110 status = set_ea(conn, NULL, directory, ea_list);
6111 if (!NT_STATUS_IS_OK(status)) {
6112 return ERROR_NT(status);
6116 /* Realloc the parameter and data sizes */
6117 *pparams = (char *)SMB_REALLOC(*pparams,2);
6118 if(*pparams == NULL) {
6119 return ERROR_NT(NT_STATUS_NO_MEMORY);
6125 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6130 /****************************************************************************
6131 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6132 We don't actually do this - we just send a null response.
6133 ****************************************************************************/
6135 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6136 char **pparams, int total_params, char **ppdata, int total_data,
6137 unsigned int max_data_bytes)
6139 static uint16 fnf_handle = 257;
6140 char *params = *pparams;
6143 if (total_params < 6) {
6144 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6147 info_level = SVAL(params,4);
6148 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6150 switch (info_level) {
6155 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6158 /* Realloc the parameter and data sizes */
6159 *pparams = (char *)SMB_REALLOC(*pparams,6);
6160 if (*pparams == NULL) {
6161 return ERROR_NT(NT_STATUS_NO_MEMORY);
6165 SSVAL(params,0,fnf_handle);
6166 SSVAL(params,2,0); /* No changes */
6167 SSVAL(params,4,0); /* No EA errors */
6174 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6179 /****************************************************************************
6180 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6181 changes). Currently this does nothing.
6182 ****************************************************************************/
6184 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6185 char **pparams, int total_params, char **ppdata, int total_data,
6186 unsigned int max_data_bytes)
6188 char *params = *pparams;
6190 DEBUG(3,("call_trans2findnotifynext\n"));
6192 /* Realloc the parameter and data sizes */
6193 *pparams = (char *)SMB_REALLOC(*pparams,4);
6194 if (*pparams == NULL) {
6195 return ERROR_NT(NT_STATUS_NO_MEMORY);
6199 SSVAL(params,0,0); /* No changes */
6200 SSVAL(params,2,0); /* No EA errors */
6202 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6207 /****************************************************************************
6208 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6209 ****************************************************************************/
6211 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6212 char **pparams, int total_params, char **ppdata, int total_data,
6213 unsigned int max_data_bytes)
6215 char *params = *pparams;
6218 int max_referral_level;
6219 NTSTATUS status = NT_STATUS_OK;
6221 DEBUG(10,("call_trans2getdfsreferral\n"));
6223 if (total_params < 3) {
6224 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6227 max_referral_level = SVAL(params,0);
6229 if(!lp_host_msdfs())
6230 return ERROR_DOS(ERRDOS,ERRbadfunc);
6232 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6233 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6234 return ERROR_NT(status);
6236 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6237 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6242 #define LMCAT_SPL 0x53
6243 #define LMFUNC_GETJOBID 0x60
6245 /****************************************************************************
6246 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6247 ****************************************************************************/
6249 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6250 char **pparams, int total_params, char **ppdata, int total_data,
6251 unsigned int max_data_bytes)
6253 char *pdata = *ppdata;
6254 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6256 /* check for an invalid fid before proceeding */
6259 return(ERROR_DOS(ERRDOS,ERRbadfid));
6261 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6262 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6263 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6264 if (*ppdata == NULL) {
6265 return ERROR_NT(NT_STATUS_NO_MEMORY);
6269 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6270 CAN ACCEPT THIS IN UNICODE. JRA. */
6272 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6273 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6274 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6275 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6278 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6279 return ERROR_DOS(ERRSRV,ERRerror);
6283 /****************************************************************************
6284 Reply to a SMBfindclose (stop trans2 directory search).
6285 ****************************************************************************/
6287 int reply_findclose(connection_struct *conn,
6288 char *inbuf,char *outbuf,int length,int bufsize)
6291 int dptr_num=SVALS(inbuf,smb_vwv0);
6292 START_PROFILE(SMBfindclose);
6294 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6296 dptr_close(&dptr_num);
6298 outsize = set_message(outbuf,0,0,False);
6300 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6302 END_PROFILE(SMBfindclose);
6306 /****************************************************************************
6307 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6308 ****************************************************************************/
6310 int reply_findnclose(connection_struct *conn,
6311 char *inbuf,char *outbuf,int length,int bufsize)
6315 START_PROFILE(SMBfindnclose);
6317 dptr_num = SVAL(inbuf,smb_vwv0);
6319 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6321 /* We never give out valid handles for a
6322 findnotifyfirst - so any dptr_num is ok here.
6325 outsize = set_message(outbuf,0,0,False);
6327 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6329 END_PROFILE(SMBfindnclose);
6333 int handle_trans2(connection_struct *conn,
6334 struct trans_state *state,
6335 char *inbuf, char *outbuf, int size, int bufsize)
6339 if (Protocol >= PROTOCOL_NT1) {
6340 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6343 /* Now we must call the relevant TRANS2 function */
6344 switch(state->call) {
6345 case TRANSACT2_OPEN:
6347 START_PROFILE(Trans2_open);
6348 outsize = call_trans2open(
6349 conn, inbuf, outbuf, bufsize,
6350 &state->param, state->total_param,
6351 &state->data, state->total_data,
6352 state->max_data_return);
6353 END_PROFILE(Trans2_open);
6357 case TRANSACT2_FINDFIRST:
6359 START_PROFILE(Trans2_findfirst);
6360 outsize = call_trans2findfirst(
6361 conn, inbuf, outbuf, bufsize,
6362 &state->param, state->total_param,
6363 &state->data, state->total_data,
6364 state->max_data_return);
6365 END_PROFILE(Trans2_findfirst);
6369 case TRANSACT2_FINDNEXT:
6371 START_PROFILE(Trans2_findnext);
6372 outsize = call_trans2findnext(
6373 conn, inbuf, outbuf, size, bufsize,
6374 &state->param, state->total_param,
6375 &state->data, state->total_data,
6376 state->max_data_return);
6377 END_PROFILE(Trans2_findnext);
6381 case TRANSACT2_QFSINFO:
6383 START_PROFILE(Trans2_qfsinfo);
6384 outsize = call_trans2qfsinfo(
6385 conn, inbuf, outbuf, size, bufsize,
6386 &state->param, state->total_param,
6387 &state->data, state->total_data,
6388 state->max_data_return);
6389 END_PROFILE(Trans2_qfsinfo);
6393 case TRANSACT2_SETFSINFO:
6395 START_PROFILE(Trans2_setfsinfo);
6396 outsize = call_trans2setfsinfo(
6397 conn, inbuf, outbuf, size, bufsize,
6398 &state->param, state->total_param,
6399 &state->data, state->total_data,
6400 state->max_data_return);
6401 END_PROFILE(Trans2_setfsinfo);
6405 case TRANSACT2_QPATHINFO:
6406 case TRANSACT2_QFILEINFO:
6408 START_PROFILE(Trans2_qpathinfo);
6409 outsize = call_trans2qfilepathinfo(
6410 conn, inbuf, outbuf, size, bufsize, state->call,
6411 &state->param, state->total_param,
6412 &state->data, state->total_data,
6413 state->max_data_return);
6414 END_PROFILE(Trans2_qpathinfo);
6418 case TRANSACT2_SETPATHINFO:
6419 case TRANSACT2_SETFILEINFO:
6421 START_PROFILE(Trans2_setpathinfo);
6422 outsize = call_trans2setfilepathinfo(
6423 conn, inbuf, outbuf, size, bufsize, state->call,
6424 &state->param, state->total_param,
6425 &state->data, state->total_data,
6426 state->max_data_return);
6427 END_PROFILE(Trans2_setpathinfo);
6431 case TRANSACT2_FINDNOTIFYFIRST:
6433 START_PROFILE(Trans2_findnotifyfirst);
6434 outsize = call_trans2findnotifyfirst(
6435 conn, inbuf, outbuf, size, bufsize,
6436 &state->param, state->total_param,
6437 &state->data, state->total_data,
6438 state->max_data_return);
6439 END_PROFILE(Trans2_findnotifyfirst);
6443 case TRANSACT2_FINDNOTIFYNEXT:
6445 START_PROFILE(Trans2_findnotifynext);
6446 outsize = call_trans2findnotifynext(
6447 conn, inbuf, outbuf, size, bufsize,
6448 &state->param, state->total_param,
6449 &state->data, state->total_data,
6450 state->max_data_return);
6451 END_PROFILE(Trans2_findnotifynext);
6455 case TRANSACT2_MKDIR:
6457 START_PROFILE(Trans2_mkdir);
6458 outsize = call_trans2mkdir(
6459 conn, inbuf, outbuf, size, bufsize,
6460 &state->param, state->total_param,
6461 &state->data, state->total_data,
6462 state->max_data_return);
6463 END_PROFILE(Trans2_mkdir);
6467 case TRANSACT2_GET_DFS_REFERRAL:
6469 START_PROFILE(Trans2_get_dfs_referral);
6470 outsize = call_trans2getdfsreferral(
6471 conn, inbuf, outbuf, size, bufsize,
6472 &state->param, state->total_param,
6473 &state->data, state->total_data,
6474 state->max_data_return);
6475 END_PROFILE(Trans2_get_dfs_referral);
6479 case TRANSACT2_IOCTL:
6481 START_PROFILE(Trans2_ioctl);
6482 outsize = call_trans2ioctl(
6483 conn, inbuf, outbuf, size, bufsize,
6484 &state->param, state->total_param,
6485 &state->data, state->total_data,
6486 state->max_data_return);
6487 END_PROFILE(Trans2_ioctl);
6492 /* Error in request */
6493 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6494 outsize = ERROR_DOS(ERRSRV,ERRerror);
6500 /****************************************************************************
6501 Reply to a SMBtrans2.
6502 ****************************************************************************/
6504 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6505 int size, int bufsize)
6508 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6509 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6510 unsigned int psoff = SVAL(inbuf, smb_psoff);
6511 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6512 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6513 struct trans_state *state;
6516 START_PROFILE(SMBtrans2);
6518 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6519 if (!NT_STATUS_IS_OK(result)) {
6520 DEBUG(2, ("Got invalid trans2 request: %s\n",
6521 nt_errstr(result)));
6522 END_PROFILE(SMBtrans2);
6523 return ERROR_NT(result);
6526 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6527 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6528 END_PROFILE(SMBtrans2);
6529 return ERROR_DOS(ERRSRV,ERRaccess);
6532 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6533 DEBUG(0, ("talloc failed\n"));
6534 END_PROFILE(SMBtrans2);
6535 return ERROR_NT(NT_STATUS_NO_MEMORY);
6538 state->cmd = SMBtrans2;
6540 state->mid = SVAL(inbuf, smb_mid);
6541 state->vuid = SVAL(inbuf, smb_uid);
6542 state->setup_count = SVAL(inbuf, smb_suwcnt);
6543 state->setup = NULL;
6544 state->total_param = SVAL(inbuf, smb_tpscnt);
6545 state->param = NULL;
6546 state->total_data = SVAL(inbuf, smb_tdscnt);
6548 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6549 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6550 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6551 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6552 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6554 state->call = tran_call;
6556 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6557 is so as a sanity check */
6558 if (state->setup_count != 1) {
6560 * Need to have rc=0 for ioctl to get job id for OS/2.
6561 * Network printing will fail if function is not successful.
6562 * Similar function in reply.c will be used if protocol
6563 * is LANMAN1.0 instead of LM1.2X002.
6564 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6565 * outbuf doesn't have to be set(only job id is used).
6567 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6568 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6569 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6570 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6572 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6573 DEBUG(2,("Transaction is %d\n",tran_call));
6575 END_PROFILE(SMBtrans2);
6576 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6580 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6583 if (state->total_data) {
6584 /* Can't use talloc here, the core routines do realloc on the
6585 * params and data. */
6586 state->data = (char *)SMB_MALLOC(state->total_data);
6587 if (state->data == NULL) {
6588 DEBUG(0,("reply_trans2: data malloc fail for %u "
6589 "bytes !\n", (unsigned int)state->total_data));
6591 END_PROFILE(SMBtrans2);
6592 return(ERROR_DOS(ERRDOS,ERRnomem));
6594 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6596 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6597 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6600 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6603 if (state->total_param) {
6604 /* Can't use talloc here, the core routines do realloc on the
6605 * params and data. */
6606 state->param = (char *)SMB_MALLOC(state->total_param);
6607 if (state->param == NULL) {
6608 DEBUG(0,("reply_trans: param malloc fail for %u "
6609 "bytes !\n", (unsigned int)state->total_param));
6610 SAFE_FREE(state->data);
6612 END_PROFILE(SMBtrans2);
6613 return(ERROR_DOS(ERRDOS,ERRnomem));
6615 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6617 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6618 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6621 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6624 state->received_data = dscnt;
6625 state->received_param = pscnt;
6627 if ((state->received_param == state->total_param) &&
6628 (state->received_data == state->total_data)) {
6630 outsize = handle_trans2(conn, state, inbuf, outbuf,
6632 SAFE_FREE(state->data);
6633 SAFE_FREE(state->param);
6635 END_PROFILE(SMBtrans2);
6639 DLIST_ADD(conn->pending_trans, state);
6641 /* We need to send an interim response then receive the rest
6642 of the parameter/data bytes */
6643 outsize = set_message(outbuf,0,0,False);
6645 END_PROFILE(SMBtrans2);
6650 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6651 SAFE_FREE(state->data);
6652 SAFE_FREE(state->param);
6654 END_PROFILE(SMBtrans2);
6655 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6659 /****************************************************************************
6660 Reply to a SMBtranss2
6661 ****************************************************************************/
6663 int reply_transs2(connection_struct *conn,
6664 char *inbuf,char *outbuf,int size,int bufsize)
6667 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6668 struct trans_state *state;
6670 START_PROFILE(SMBtranss2);
6674 for (state = conn->pending_trans; state != NULL;
6675 state = state->next) {
6676 if (state->mid == SVAL(inbuf,smb_mid)) {
6681 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6682 END_PROFILE(SMBtranss2);
6683 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6686 /* Revise state->total_param and state->total_data in case they have
6687 changed downwards */
6689 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6690 state->total_param = SVAL(inbuf, smb_tpscnt);
6691 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6692 state->total_data = SVAL(inbuf, smb_tdscnt);
6694 pcnt = SVAL(inbuf, smb_spscnt);
6695 poff = SVAL(inbuf, smb_spsoff);
6696 pdisp = SVAL(inbuf, smb_spsdisp);
6698 dcnt = SVAL(inbuf, smb_sdscnt);
6699 doff = SVAL(inbuf, smb_sdsoff);
6700 ddisp = SVAL(inbuf, smb_sdsdisp);
6702 state->received_param += pcnt;
6703 state->received_data += dcnt;
6705 if ((state->received_data > state->total_data) ||
6706 (state->received_param > state->total_param))
6710 if (pdisp+pcnt > state->total_param)
6712 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6714 if (pdisp > state->total_param)
6716 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6717 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6719 if (state->param + pdisp < state->param)
6722 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6727 if (ddisp+dcnt > state->total_data)
6729 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6731 if (ddisp > state->total_data)
6733 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6734 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6736 if (state->data + ddisp < state->data)
6739 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6743 if ((state->received_param < state->total_param) ||
6744 (state->received_data < state->total_data)) {
6745 END_PROFILE(SMBtranss2);
6749 /* construct_reply_common has done us the favor to pre-fill the
6750 * command field with SMBtranss2 which is wrong :-)
6752 SCVAL(outbuf,smb_com,SMBtrans2);
6754 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6756 DLIST_REMOVE(conn->pending_trans, state);
6757 SAFE_FREE(state->data);
6758 SAFE_FREE(state->param);
6762 END_PROFILE(SMBtranss2);
6763 return(ERROR_DOS(ERRSRV,ERRnosupport));
6766 END_PROFILE(SMBtranss2);
6771 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6772 DLIST_REMOVE(conn->pending_trans, state);
6773 SAFE_FREE(state->data);
6774 SAFE_FREE(state->param);
6776 END_PROFILE(SMBtranss2);
6777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);