2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct *conn,
41 const SMB_STRUCT_STAT *psbuf);
43 static char *store_file_unix_basic_info2(connection_struct *conn,
46 const SMB_STRUCT_STAT *psbuf);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
55 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type = get_remote_arch();
59 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60 val = SMB_ROUNDUP(val,rval);
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
68 ********************************************************************/
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
74 if(S_ISDIR(sbuf->st_mode)) {
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
81 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
84 if (fsp && fsp->initial_allocation_size)
85 ret = MAX(ret,fsp->initial_allocation_size);
87 return smb_roundup(conn, ret);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120 const char *fname, char *ea_name, struct ea_struct *pea)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size = 256;
129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 if (fsp && fsp->fh->fd != -1) {
135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150 dump_data(10, val, sizeret);
153 if (strnequal(ea_name, "user.", 5)) {
154 pea->name = &ea_name[5];
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168 const char *fname, size_t *pea_total_len)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size = 1024;
176 struct ea_list *ea_list_head = NULL;
180 if (!lp_ea_support(SNUM(conn))) {
184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
191 if (fsp && fsp->fh->fd != -1) {
192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
197 if (sizeret == -1 && errno == ERANGE) {
198 ea_namelist_size *= 2;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211 struct ea_list *listp;
213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
216 listp = TALLOC_P(mem_ctx, struct ea_list);
220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
226 push_ascii_fstring(dos_ea_name, listp->ea.name);
227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len, dos_ea_name,
230 (unsigned int)listp->ea.value.length ));
232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
234 /* Add on 4 for total length. */
235 if (*pea_total_len) {
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250 connection_struct *conn, struct ea_list *ea_list)
252 unsigned int ret_data_size = 4;
255 SMB_ASSERT(total_data_size >= 4);
257 if (!lp_ea_support(SNUM(conn))) {
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
270 if (ea_list->ea.value.length > 65535) {
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290 SIVAL(pdata,0,ret_data_size);
291 return ret_data_size;
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
296 size_t total_ea_len = 0;
297 TALLOC_CTX *mem_ctx = NULL;
299 if (!lp_ea_support(SNUM(conn))) {
302 mem_ctx = talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304 talloc_destroy(mem_ctx);
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
318 for (; ea_list; ea_list = ea_list->next) {
319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name[5], ea_list->ea.name));
322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
326 talloc_destroy(mem_ctx);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
335 if (!lp_ea_support(SNUM(conn))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED;
339 for (;ea_list; ea_list = ea_list->next) {
341 fstring unix_ea_name;
343 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name, ea_list->ea.name);
346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
350 if (samba_private_attr_name(unix_ea_name)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352 return NT_STATUS_ACCESS_DENIED;
355 if (ea_list->ea.value.length == 0) {
356 /* Remove the attribute. */
357 if (fsp && (fsp->fh->fd != -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name, fsp->fsp_name));
360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name, fname));
364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
367 /* Removing a non existent attribute always succeeds. */
368 if (ret == -1 && errno == ENOATTR) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
375 if (fsp && (fsp->fh->fd != -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name, fsp->fsp_name));
378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name, fname));
383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
390 if (errno == ENOTSUP) {
391 return NT_STATUS_EAS_NOT_SUPPORTED;
394 return map_nt_error_from_unix(errno);
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
406 struct ea_list *ea_list_head = NULL;
409 while (offset + 2 < data_size) {
410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411 unsigned int namelen = CVAL(pdata,offset);
413 offset++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417 (offset > data_size) || (namelen > data_size) ||
418 (offset + namelen >= data_size)) {
421 /* Ensure the name is null terminated. */
422 if (pdata[offset + namelen] != '\0') {
425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
430 offset += (namelen + 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
446 unsigned int namelen;
456 eal->ea.flags = CVAL(pdata,0);
457 namelen = CVAL(pdata,1);
458 val_len = SVAL(pdata,2);
460 if (4 + namelen + 1 + val_len > data_size) {
464 /* Ensure the name is null terminated. */
465 if (pdata[namelen + 4] != '\0') {
468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474 if (!eal->ea.value.data) {
478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal->ea.value.data[val_len] = '\0';
482 /* But don't count the null. */
483 eal->ea.value.length--;
486 *pbytes_used = 4 + namelen + 1 + val_len;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
501 struct ea_list *ea_list_head = NULL;
503 size_t bytes_used = 0;
505 while (offset < data_size) {
506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513 offset += bytes_used;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list *ealist)
526 struct ea_list *listp;
529 for (listp = ealist; listp; listp = listp->next) {
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 /* Add on 4 for total length. */
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
549 struct ea_list *nlistp, *flistp;
551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552 for (flistp = file_list; flistp; flistp = flistp->next) {
553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
559 /* Copy the data from this entry. */
560 nlistp->ea.flags = flistp->ea.flags;
561 nlistp->ea.value = flistp->ea.value;
564 nlistp->ea.flags = 0;
565 ZERO_STRUCT(nlistp->ea.value);
569 *total_ea_len = ea_list_size(name_list);
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(char *outbuf,
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
738 /****************************************************************************
739 Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
742 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
743 char **pparams, int total_params, char **ppdata, int total_data,
744 unsigned int max_data_bytes)
746 char *params = *pparams;
747 char *pdata = *ppdata;
752 BOOL return_additional_info;
763 SMB_STRUCT_STAT sbuf;
766 struct ea_list *ea_list = NULL;
771 uint32 create_disposition;
772 uint32 create_options = 0;
775 * Ensure we have enough parameters to perform the operation.
778 if (total_params < 29) {
779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
782 flags = SVAL(params, 0);
783 deny_mode = SVAL(params, 2);
784 open_attr = SVAL(params,6);
785 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
786 if (oplock_request) {
787 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
791 return_additional_info = BITSETW(params,0);
792 open_sattr = SVAL(params, 4);
793 open_time = make_unix_date3(params+8);
795 open_ofun = SVAL(params,12);
796 open_size = IVAL(params,14);
800 return(ERROR_DOS(ERRSRV,ERRaccess));
803 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
809 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
810 (unsigned int)open_ofun, open_size));
812 /* XXXX we need to handle passed times, sattr and flags */
814 status = unix_convert(conn, fname, False, NULL, &sbuf);
815 if (!NT_STATUS_IS_OK(status)) {
816 return ERROR_NT(status);
819 status = check_name(conn, fname);
820 if (!NT_STATUS_IS_OK(status)) {
821 return ERROR_NT(status);
824 if (open_ofun == 0) {
825 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
828 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
833 return ERROR_DOS(ERRDOS, ERRbadaccess);
836 /* Any data in this call is an EA list. */
837 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
838 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
841 if (total_data != 4) {
842 if (total_data < 10) {
843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 if (IVAL(pdata,0) > total_data) {
847 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
848 IVAL(pdata,0), (unsigned int)total_data));
849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
852 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
857 } else if (IVAL(pdata,0) != 4) {
858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
861 status = open_file_ntcreate(conn,fname,&sbuf,
870 if (!NT_STATUS_IS_OK(status)) {
871 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
872 /* We have re-scheduled this call. */
875 return ERROR_OPEN(status);
878 size = get_file_size(sbuf);
879 fattr = dos_mode(conn,fname,&sbuf);
880 mtime = sbuf.st_mtime;
883 close_file(fsp,ERROR_CLOSE);
884 return(ERROR_DOS(ERRDOS,ERRnoaccess));
887 /* Save the requested allocation size. */
888 /* Allocate space for the file if a size hint is supplied */
889 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
890 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
891 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
892 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
893 if (fsp->is_directory) {
894 close_file(fsp,ERROR_CLOSE);
895 /* Can't set allocation size on a directory. */
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
898 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
899 close_file(fsp,ERROR_CLOSE);
900 return ERROR_NT(NT_STATUS_DISK_FULL);
903 /* Adjust size here to return the right size in the reply.
904 Windows does it this way. */
905 size = fsp->initial_allocation_size;
907 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
911 if (ea_list && smb_action == FILE_WAS_CREATED) {
912 status = set_ea(conn, fsp, fname, ea_list);
913 if (!NT_STATUS_IS_OK(status)) {
914 close_file(fsp,ERROR_CLOSE);
915 return ERROR_NT(status);
919 /* Realloc the size of parameters and data we will return */
920 *pparams = (char *)SMB_REALLOC(*pparams, 30);
921 if(*pparams == NULL ) {
922 return ERROR_NT(NT_STATUS_NO_MEMORY);
926 SSVAL(params,0,fsp->fnum);
927 SSVAL(params,2,fattr);
928 srv_put_dos_date2(params,4, mtime);
929 SIVAL(params,8, (uint32)size);
930 SSVAL(params,12,deny_mode);
931 SSVAL(params,14,0); /* open_type - file or directory. */
932 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
934 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
935 smb_action |= EXTENDED_OPLOCK_GRANTED;
938 SSVAL(params,18,smb_action);
941 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
943 SIVAL(params,20,inode);
944 SSVAL(params,24,0); /* Padding. */
946 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
947 SIVAL(params, 26, ea_size);
949 SIVAL(params, 26, 0);
952 /* Send the required number of replies */
953 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
958 /*********************************************************
959 Routine to check if a given string matches exactly.
960 as a special case a mask of "." does NOT match. That
961 is required for correct wildcard semantics
962 Case can be significant or not.
963 **********************************************************/
965 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
967 if (mask[0] == '.' && mask[1] == 0)
969 if (conn->case_sensitive)
970 return strcmp(str,mask)==0;
971 if (StrCaseCmp(str,mask) != 0) {
974 if (dptr_has_wild(conn->dirptr)) {
980 /****************************************************************************
981 Return the filetype for UNIX extensions.
982 ****************************************************************************/
984 static uint32 unix_filetype(mode_t mode)
987 return UNIX_TYPE_FILE;
988 else if(S_ISDIR(mode))
989 return UNIX_TYPE_DIR;
991 else if(S_ISLNK(mode))
992 return UNIX_TYPE_SYMLINK;
995 else if(S_ISCHR(mode))
996 return UNIX_TYPE_CHARDEV;
999 else if(S_ISBLK(mode))
1000 return UNIX_TYPE_BLKDEV;
1003 else if(S_ISFIFO(mode))
1004 return UNIX_TYPE_FIFO;
1007 else if(S_ISSOCK(mode))
1008 return UNIX_TYPE_SOCKET;
1011 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1012 return UNIX_TYPE_UNKNOWN;
1015 /****************************************************************************
1016 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1017 ****************************************************************************/
1019 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1021 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1022 SMB_STRUCT_STAT *psbuf,
1024 enum perm_type ptype,
1029 if (perms == SMB_MODE_NO_CHANGE) {
1030 if (!VALID_STAT(*psbuf)) {
1031 return NT_STATUS_INVALID_PARAMETER;
1033 *ret_perms = psbuf->st_mode;
1034 return NT_STATUS_OK;
1038 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1039 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1040 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1041 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1042 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1043 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1044 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1045 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1046 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1048 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1051 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1054 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1059 /* Apply mode mask */
1060 ret &= lp_create_mask(SNUM(conn));
1061 /* Add in force bits */
1062 ret |= lp_force_create_mode(SNUM(conn));
1065 ret &= lp_dir_mask(SNUM(conn));
1066 /* Add in force bits */
1067 ret |= lp_force_dir_mode(SNUM(conn));
1069 case PERM_EXISTING_FILE:
1070 /* Apply mode mask */
1071 ret &= lp_security_mask(SNUM(conn));
1072 /* Add in force bits */
1073 ret |= lp_force_security_mode(SNUM(conn));
1075 case PERM_EXISTING_DIR:
1076 /* Apply mode mask */
1077 ret &= lp_dir_security_mask(SNUM(conn));
1078 /* Add in force bits */
1079 ret |= lp_force_dir_security_mode(SNUM(conn));
1084 return NT_STATUS_OK;
1087 /****************************************************************************
1088 Get a level dependent lanman2 dir entry.
1089 ****************************************************************************/
1091 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1092 void *inbuf, char *outbuf,
1093 char *path_mask,uint32 dirtype,int info_level,
1094 int requires_resume_key,
1095 BOOL dont_descend,char **ppdata,
1096 char *base_data, int space_remaining,
1097 BOOL *out_of_space, BOOL *got_exact_match,
1098 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1102 SMB_STRUCT_STAT sbuf;
1106 char *p, *q, *pdata = *ppdata;
1110 SMB_OFF_T file_size = 0;
1111 SMB_BIG_UINT allocation_size = 0;
1113 struct timespec mdate_ts, adate_ts, create_date_ts;
1114 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1116 char *last_entry_ptr;
1118 uint32 nt_extmode; /* Used for NT connections instead of mode */
1119 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1120 BOOL check_mangled_names = lp_manglednames(conn->params);
1123 *out_of_space = False;
1124 *got_exact_match = False;
1126 ZERO_STRUCT(mdate_ts);
1127 ZERO_STRUCT(adate_ts);
1128 ZERO_STRUCT(create_date_ts);
1133 p = strrchr_m(path_mask,'/');
1136 pstrcpy(mask,"*.*");
1140 pstrcpy(mask, path_mask);
1145 BOOL ms_dfs_link = False;
1147 /* Needed if we run out of space */
1148 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1149 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1152 * Due to bugs in NT client redirectors we are not using
1153 * resume keys any more - set them to zero.
1154 * Check out the related comments in findfirst/findnext.
1160 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1161 (long)conn->dirptr,curr_dirpos));
1166 pstrcpy(fname,dname);
1168 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1169 got_match = mask_match(fname, mask, conn->case_sensitive);
1171 if(!got_match && check_mangled_names &&
1172 !mangle_is_8_3(fname, False, conn->params)) {
1175 * It turns out that NT matches wildcards against
1176 * both long *and* short names. This may explain some
1177 * of the wildcard wierdness from old DOS clients
1178 * that some people have been seeing.... JRA.
1182 pstrcpy( newname, fname);
1183 mangle_map( newname, True, False, conn->params);
1184 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1185 got_match = mask_match(newname, mask, conn->case_sensitive);
1189 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1190 if (dont_descend && !isdots)
1193 pstrcpy(pathreal,conn->dirpath);
1195 pstrcat(pathreal,"/");
1196 pstrcat(pathreal,dname);
1198 if (INFO_LEVEL_IS_UNIX(info_level)) {
1199 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1200 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1201 pathreal,strerror(errno)));
1204 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1205 pstring link_target;
1207 /* Needed to show the msdfs symlinks as
1210 if(lp_host_msdfs() &&
1211 lp_msdfs_root(SNUM(conn)) &&
1212 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1213 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1216 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1220 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1221 pathreal,strerror(errno)));
1227 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1229 mode = dos_mode(conn,pathreal,&sbuf);
1232 if (!dir_check_ftype(conn,mode,dirtype)) {
1233 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1238 file_size = get_file_size(sbuf);
1239 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1241 mdate_ts = get_mtimespec(&sbuf);
1242 adate_ts = get_atimespec(&sbuf);
1243 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1245 if (lp_dos_filetime_resolution(SNUM(conn))) {
1246 dos_filetime_timespec(&create_date_ts);
1247 dos_filetime_timespec(&mdate_ts);
1248 dos_filetime_timespec(&adate_ts);
1251 create_date = convert_timespec_to_time_t(create_date_ts);
1252 mdate = convert_timespec_to_time_t(mdate_ts);
1253 adate = convert_timespec_to_time_t(adate_ts);
1255 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1259 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1263 mangle_map(fname,False,True,conn->params);
1268 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1270 switch (info_level) {
1271 case SMB_FIND_INFO_STANDARD:
1272 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1273 if(requires_resume_key) {
1277 srv_put_dos_date2(p,0,create_date);
1278 srv_put_dos_date2(p,4,adate);
1279 srv_put_dos_date2(p,8,mdate);
1280 SIVAL(p,12,(uint32)file_size);
1281 SIVAL(p,16,(uint32)allocation_size);
1285 p += align_string(outbuf, p, 0);
1286 len = srvstr_push(outbuf, p, fname, space_remaining - (p - pdata), STR_TERMINATE);
1287 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1289 SCVAL(nameptr, -1, len - 2);
1291 SCVAL(nameptr, -1, 0);
1295 SCVAL(nameptr, -1, len - 1);
1297 SCVAL(nameptr, -1, 0);
1303 case SMB_FIND_EA_SIZE:
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1305 if(requires_resume_key) {
1309 srv_put_dos_date2(p,0,create_date);
1310 srv_put_dos_date2(p,4,adate);
1311 srv_put_dos_date2(p,8,mdate);
1312 SIVAL(p,12,(uint32)file_size);
1313 SIVAL(p,16,(uint32)allocation_size);
1316 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1317 SIVAL(p,22,ea_size); /* Extended attributes */
1321 len = srvstr_push(outbuf, p, fname, space_remaining - (p - pdata), STR_TERMINATE | STR_NOALIGN);
1322 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1335 SCVAL(nameptr,0,len);
1337 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1340 case SMB_FIND_EA_LIST:
1342 struct ea_list *file_list = NULL;
1345 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1349 if(requires_resume_key) {
1353 srv_put_dos_date2(p,0,create_date);
1354 srv_put_dos_date2(p,4,adate);
1355 srv_put_dos_date2(p,8,mdate);
1356 SIVAL(p,12,(uint32)file_size);
1357 SIVAL(p,16,(uint32)allocation_size);
1359 p += 22; /* p now points to the EA area. */
1361 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1362 name_list = ea_list_union(name_list, file_list, &ea_len);
1364 /* We need to determine if this entry will fit in the space available. */
1365 /* Max string size is 255 bytes. */
1366 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1367 /* Move the dirptr back to prev_dirpos */
1368 dptr_SeekDir(conn->dirptr, prev_dirpos);
1369 *out_of_space = True;
1370 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1371 return False; /* Not finished - just out of space */
1374 /* Push the ea_data followed by the name. */
1375 p += fill_ea_buffer(ea_ctx, p, space_remaining - (p - pdata), conn, name_list);
1377 len = srvstr_push(outbuf, p + 1, fname, space_remaining - (p - pdata), STR_TERMINATE | STR_NOALIGN);
1378 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1391 SCVAL(nameptr,0,len);
1393 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1397 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1398 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1399 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1401 SIVAL(p,0,reskey); p += 4;
1402 put_long_date_timespec(p,create_date_ts); p += 8;
1403 put_long_date_timespec(p,adate_ts); p += 8;
1404 put_long_date_timespec(p,mdate_ts); p += 8;
1405 put_long_date_timespec(p,mdate_ts); p += 8;
1406 SOFF_T(p,0,file_size); p += 8;
1407 SOFF_T(p,0,allocation_size); p += 8;
1408 SIVAL(p,0,nt_extmode); p += 4;
1409 q = p; p += 4; /* q is placeholder for name length. */
1411 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1412 SIVAL(p,0,ea_size); /* Extended attributes */
1415 /* Clear the short name buffer. This is
1416 * IMPORTANT as not doing so will trigger
1417 * a Win2k client bug. JRA.
1419 if (!was_8_3 && check_mangled_names) {
1420 pstring mangled_name;
1421 pstrcpy(mangled_name, fname);
1422 mangle_map(mangled_name,True,True,
1424 mangled_name[12] = 0;
1425 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1427 memset(p + 2 + len,'\0',24 - len);
1434 len = srvstr_push(outbuf, p, fname, space_remaining - (p - pdata), STR_TERMINATE_ASCII);
1437 SIVAL(p,0,0); /* Ensure any padding is null. */
1438 len = PTR_DIFF(p, pdata);
1439 len = (len + 3) & ~3;
1444 case SMB_FIND_FILE_DIRECTORY_INFO:
1445 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1447 SIVAL(p,0,reskey); p += 4;
1448 put_long_date_timespec(p,create_date_ts); p += 8;
1449 put_long_date_timespec(p,adate_ts); p += 8;
1450 put_long_date_timespec(p,mdate_ts); p += 8;
1451 put_long_date_timespec(p,mdate_ts); p += 8;
1452 SOFF_T(p,0,file_size); p += 8;
1453 SOFF_T(p,0,allocation_size); p += 8;
1454 SIVAL(p,0,nt_extmode); p += 4;
1455 len = srvstr_push(outbuf, p + 4, fname, space_remaining - (p - pdata), STR_TERMINATE_ASCII);
1458 SIVAL(p,0,0); /* Ensure any padding is null. */
1459 len = PTR_DIFF(p, pdata);
1460 len = (len + 3) & ~3;
1465 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1466 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1468 SIVAL(p,0,reskey); p += 4;
1469 put_long_date_timespec(p,create_date_ts); p += 8;
1470 put_long_date_timespec(p,adate_ts); p += 8;
1471 put_long_date_timespec(p,mdate_ts); p += 8;
1472 put_long_date_timespec(p,mdate_ts); p += 8;
1473 SOFF_T(p,0,file_size); p += 8;
1474 SOFF_T(p,0,allocation_size); p += 8;
1475 SIVAL(p,0,nt_extmode); p += 4;
1476 q = p; p += 4; /* q is placeholder for name length. */
1478 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1479 SIVAL(p,0,ea_size); /* Extended attributes */
1482 len = srvstr_push(outbuf, p, fname, space_remaining - (p - pdata), STR_TERMINATE_ASCII);
1486 SIVAL(p,0,0); /* Ensure any padding is null. */
1487 len = PTR_DIFF(p, pdata);
1488 len = (len + 3) & ~3;
1493 case SMB_FIND_FILE_NAMES_INFO:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1496 SIVAL(p,0,reskey); p += 4;
1498 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1499 acl on a dir (tridge) */
1500 len = srvstr_push(outbuf, p, fname, space_remaining - (p - pdata), STR_TERMINATE_ASCII);
1503 SIVAL(p,0,0); /* Ensure any padding is null. */
1504 len = PTR_DIFF(p, pdata);
1505 len = (len + 3) & ~3;
1510 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1511 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1513 SIVAL(p,0,reskey); p += 4;
1514 put_long_date_timespec(p,create_date_ts); p += 8;
1515 put_long_date_timespec(p,adate_ts); p += 8;
1516 put_long_date_timespec(p,mdate_ts); p += 8;
1517 put_long_date_timespec(p,mdate_ts); p += 8;
1518 SOFF_T(p,0,file_size); p += 8;
1519 SOFF_T(p,0,allocation_size); p += 8;
1520 SIVAL(p,0,nt_extmode); p += 4;
1521 q = p; p += 4; /* q is placeholder for name length. */
1523 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1524 SIVAL(p,0,ea_size); /* Extended attributes */
1527 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1528 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1529 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1530 len = srvstr_push(outbuf, p, fname, space_remaining - (p - pdata), STR_TERMINATE_ASCII);
1533 SIVAL(p,0,0); /* Ensure any padding is null. */
1534 len = PTR_DIFF(p, pdata);
1535 len = (len + 3) & ~3;
1540 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1541 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1542 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1544 SIVAL(p,0,reskey); p += 4;
1545 put_long_date_timespec(p,create_date_ts); p += 8;
1546 put_long_date_timespec(p,adate_ts); p += 8;
1547 put_long_date_timespec(p,mdate_ts); p += 8;
1548 put_long_date_timespec(p,mdate_ts); p += 8;
1549 SOFF_T(p,0,file_size); p += 8;
1550 SOFF_T(p,0,allocation_size); p += 8;
1551 SIVAL(p,0,nt_extmode); p += 4;
1552 q = p; p += 4; /* q is placeholder for name length */
1554 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1555 SIVAL(p,0,ea_size); /* Extended attributes */
1558 /* Clear the short name buffer. This is
1559 * IMPORTANT as not doing so will trigger
1560 * a Win2k client bug. JRA.
1562 if (!was_8_3 && check_mangled_names) {
1563 pstring mangled_name;
1564 pstrcpy(mangled_name, fname);
1565 mangle_map(mangled_name,True,True,
1567 mangled_name[12] = 0;
1568 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1571 memset(p + 2 + len,'\0',24 - len);
1578 SSVAL(p,0,0); p += 2; /* Reserved ? */
1579 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1580 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1581 len = srvstr_push(outbuf, p, fname, space_remaining - (p - pdata), STR_TERMINATE_ASCII);
1584 SIVAL(p,0,0); /* Ensure any padding is null. */
1585 len = PTR_DIFF(p, pdata);
1586 len = (len + 3) & ~3;
1591 /* CIFS UNIX Extension. */
1593 case SMB_FIND_FILE_UNIX:
1594 case SMB_FIND_FILE_UNIX_INFO2:
1596 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1598 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1600 if (info_level == SMB_FIND_FILE_UNIX) {
1601 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1602 p = store_file_unix_basic(conn, p,
1604 len = srvstr_push(outbuf, p, fname, space_remaining - (p - pdata), STR_TERMINATE);
1606 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1607 p = store_file_unix_basic_info2(conn, p,
1611 len = srvstr_push(outbuf, p, fname, space_remaining - (p - pdata), 0);
1612 SIVAL(nameptr, 0, len);
1616 SIVAL(p,0,0); /* Ensure any padding is null. */
1618 len = PTR_DIFF(p, pdata);
1619 len = (len + 3) & ~3;
1620 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1622 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1631 if (PTR_DIFF(p,pdata) > space_remaining) {
1632 /* Move the dirptr back to prev_dirpos */
1633 dptr_SeekDir(conn->dirptr, prev_dirpos);
1634 *out_of_space = True;
1635 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1636 return False; /* Not finished - just out of space */
1639 /* Setup the last entry pointer, as an offset from base_data */
1640 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1641 /* Advance the data pointer to the next slot */
1647 /****************************************************************************
1648 Reply to a TRANS2_FINDFIRST.
1649 ****************************************************************************/
1651 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1652 char **pparams, int total_params, char **ppdata, int total_data,
1653 unsigned int max_data_bytes)
1655 /* We must be careful here that we don't return more than the
1656 allowed number of data bytes. If this means returning fewer than
1657 maxentries then so be it. We assume that the redirector has
1658 enough room for the fixed number of parameter bytes it has
1660 char *params = *pparams;
1661 char *pdata = *ppdata;
1664 uint16 findfirst_flags;
1665 BOOL close_after_first;
1667 BOOL requires_resume_key;
1672 int last_entry_off=0;
1676 BOOL finished = False;
1677 BOOL dont_descend = False;
1678 BOOL out_of_space = False;
1679 int space_remaining;
1680 BOOL mask_contains_wcard = False;
1681 SMB_STRUCT_STAT sbuf;
1682 TALLOC_CTX *ea_ctx = NULL;
1683 struct ea_list *ea_list = NULL;
1684 NTSTATUS ntstatus = NT_STATUS_OK;
1686 if (total_params < 13) {
1687 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1690 dirtype = SVAL(params,0);
1691 maxentries = SVAL(params,2);
1692 findfirst_flags = SVAL(params,4);
1693 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1694 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1695 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1696 info_level = SVAL(params,6);
1698 *directory = *mask = 0;
1700 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1701 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1702 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1703 info_level, max_data_bytes));
1706 /* W2K3 seems to treat zero as 1. */
1710 switch (info_level) {
1711 case SMB_FIND_INFO_STANDARD:
1712 case SMB_FIND_EA_SIZE:
1713 case SMB_FIND_EA_LIST:
1714 case SMB_FIND_FILE_DIRECTORY_INFO:
1715 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1716 case SMB_FIND_FILE_NAMES_INFO:
1717 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1718 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1719 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1721 case SMB_FIND_FILE_UNIX:
1722 case SMB_FIND_FILE_UNIX_INFO2:
1723 if (!lp_unix_extensions()) {
1724 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1728 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1731 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1732 if (!NT_STATUS_IS_OK(ntstatus)) {
1733 return ERROR_NT(ntstatus);
1736 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1737 if (!NT_STATUS_IS_OK(ntstatus)) {
1738 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1739 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1741 return ERROR_NT(ntstatus);
1744 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1745 if (!NT_STATUS_IS_OK(ntstatus)) {
1746 return ERROR_NT(ntstatus);
1748 ntstatus = check_name(conn, directory);
1749 if (!NT_STATUS_IS_OK(ntstatus)) {
1750 return ERROR_NT(ntstatus);
1753 p = strrchr_m(directory,'/');
1755 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1756 if((directory[0] == '.') && (directory[1] == '\0')) {
1758 mask_contains_wcard = True;
1760 pstrcpy(mask,directory);
1762 pstrcpy(directory,"./");
1768 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1770 if (info_level == SMB_FIND_EA_LIST) {
1773 if (total_data < 4) {
1774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1777 ea_size = IVAL(pdata,0);
1778 if (ea_size != total_data) {
1779 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1780 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1781 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1784 if (!lp_ea_support(SNUM(conn))) {
1785 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1788 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1789 return ERROR_NT(NT_STATUS_NO_MEMORY);
1792 /* Pull out the list of names. */
1793 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1795 talloc_destroy(ea_ctx);
1796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1800 *ppdata = (char *)SMB_REALLOC(
1801 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1802 if(*ppdata == NULL ) {
1803 talloc_destroy(ea_ctx);
1804 return ERROR_NT(NT_STATUS_NO_MEMORY);
1808 /* Realloc the params space */
1809 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1810 if (*pparams == NULL) {
1811 talloc_destroy(ea_ctx);
1812 return ERROR_NT(NT_STATUS_NO_MEMORY);
1816 /* Save the wildcard match and attribs we are using on this directory -
1817 needed as lanman2 assumes these are being saved between calls */
1819 ntstatus = dptr_create(conn,
1823 SVAL(inbuf,smb_pid),
1825 mask_contains_wcard,
1829 if (!NT_STATUS_IS_OK(ntstatus)) {
1830 talloc_destroy(ea_ctx);
1831 return ERROR_NT(ntstatus);
1834 dptr_num = dptr_dnum(conn->dirptr);
1835 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1837 /* We don't need to check for VOL here as this is returned by
1838 a different TRANS2 call. */
1840 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1841 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1842 dont_descend = True;
1845 space_remaining = max_data_bytes;
1846 out_of_space = False;
1848 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1849 BOOL got_exact_match = False;
1851 /* this is a heuristic to avoid seeking the dirptr except when
1852 absolutely necessary. It allows for a filename of about 40 chars */
1853 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1854 out_of_space = True;
1857 finished = !get_lanman2_dir_entry(conn,
1859 mask,dirtype,info_level,
1860 requires_resume_key,dont_descend,
1861 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1862 &last_entry_off, ea_list, ea_ctx);
1865 if (finished && out_of_space)
1868 if (!finished && !out_of_space)
1872 * As an optimisation if we know we aren't looking
1873 * for a wildcard name (ie. the name matches the wildcard exactly)
1874 * then we can finish on any (first) match.
1875 * This speeds up large directory searches. JRA.
1881 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1884 talloc_destroy(ea_ctx);
1886 /* Check if we can close the dirptr */
1887 if(close_after_first || (finished && close_if_end)) {
1888 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1889 dptr_close(&dptr_num);
1893 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1894 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1895 * the protocol level is less than NT1. Tested with smbclient. JRA.
1896 * This should fix the OS/2 client bug #2335.
1899 if(numentries == 0) {
1900 dptr_close(&dptr_num);
1901 if (Protocol < PROTOCOL_NT1) {
1902 return ERROR_DOS(ERRDOS,ERRnofiles);
1904 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1908 /* At this point pdata points to numentries directory entries. */
1910 /* Set up the return parameter block */
1911 SSVAL(params,0,dptr_num);
1912 SSVAL(params,2,numentries);
1913 SSVAL(params,4,finished);
1914 SSVAL(params,6,0); /* Never an EA error */
1915 SSVAL(params,8,last_entry_off);
1917 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1919 if ((! *directory) && dptr_path(dptr_num))
1920 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1922 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1923 smb_fn_name(CVAL(inbuf,smb_com)),
1924 mask, directory, dirtype, numentries ) );
1927 * Force a name mangle here to ensure that the
1928 * mask as an 8.3 name is top of the mangled cache.
1929 * The reasons for this are subtle. Don't remove
1930 * this code unless you know what you are doing
1931 * (see PR#13758). JRA.
1934 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1935 mangle_map(mask, True, True, conn->params);
1940 /****************************************************************************
1941 Reply to a TRANS2_FINDNEXT.
1942 ****************************************************************************/
1944 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1945 char **pparams, int total_params, char **ppdata, int total_data,
1946 unsigned int max_data_bytes)
1948 /* We must be careful here that we don't return more than the
1949 allowed number of data bytes. If this means returning fewer than
1950 maxentries then so be it. We assume that the redirector has
1951 enough room for the fixed number of parameter bytes it has
1953 char *params = *pparams;
1954 char *pdata = *ppdata;
1959 uint16 findnext_flags;
1960 BOOL close_after_request;
1962 BOOL requires_resume_key;
1964 BOOL mask_contains_wcard = False;
1965 pstring resume_name;
1971 int i, last_entry_off=0;
1972 BOOL finished = False;
1973 BOOL dont_descend = False;
1974 BOOL out_of_space = False;
1975 int space_remaining;
1976 TALLOC_CTX *ea_ctx = NULL;
1977 struct ea_list *ea_list = NULL;
1978 NTSTATUS ntstatus = NT_STATUS_OK;
1980 if (total_params < 13) {
1981 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1984 dptr_num = SVAL(params,0);
1985 maxentries = SVAL(params,2);
1986 info_level = SVAL(params,4);
1987 resume_key = IVAL(params,6);
1988 findnext_flags = SVAL(params,10);
1989 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1990 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1991 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1992 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1994 *mask = *directory = *resume_name = 0;
1996 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1997 if (!NT_STATUS_IS_OK(ntstatus)) {
1998 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1999 complain (it thinks we're asking for the directory above the shared
2000 path or an invalid name). Catch this as the resume name is only compared, never used in
2001 a file access. JRA. */
2002 srvstr_pull(inbuf, resume_name, params+12,
2003 sizeof(resume_name), total_params - 12,
2006 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2007 return ERROR_NT(ntstatus);
2011 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2012 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2013 resume_key = %d resume name = %s continue=%d level = %d\n",
2014 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2015 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2018 /* W2K3 seems to treat zero as 1. */
2022 switch (info_level) {
2023 case SMB_FIND_INFO_STANDARD:
2024 case SMB_FIND_EA_SIZE:
2025 case SMB_FIND_EA_LIST:
2026 case SMB_FIND_FILE_DIRECTORY_INFO:
2027 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2028 case SMB_FIND_FILE_NAMES_INFO:
2029 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2030 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2031 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2033 case SMB_FIND_FILE_UNIX:
2034 case SMB_FIND_FILE_UNIX_INFO2:
2035 if (!lp_unix_extensions()) {
2036 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2040 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2043 if (info_level == SMB_FIND_EA_LIST) {
2046 if (total_data < 4) {
2047 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2050 ea_size = IVAL(pdata,0);
2051 if (ea_size != total_data) {
2052 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2053 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2054 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2057 if (!lp_ea_support(SNUM(conn))) {
2058 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2061 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2062 return ERROR_NT(NT_STATUS_NO_MEMORY);
2065 /* Pull out the list of names. */
2066 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2068 talloc_destroy(ea_ctx);
2069 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2073 *ppdata = (char *)SMB_REALLOC(
2074 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2075 if(*ppdata == NULL) {
2076 talloc_destroy(ea_ctx);
2077 return ERROR_NT(NT_STATUS_NO_MEMORY);
2082 /* Realloc the params space */
2083 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2084 if(*pparams == NULL ) {
2085 talloc_destroy(ea_ctx);
2086 return ERROR_NT(NT_STATUS_NO_MEMORY);
2091 /* Check that the dptr is valid */
2092 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2093 talloc_destroy(ea_ctx);
2094 return ERROR_DOS(ERRDOS,ERRnofiles);
2097 string_set(&conn->dirpath,dptr_path(dptr_num));
2099 /* Get the wildcard mask from the dptr */
2100 if((p = dptr_wcard(dptr_num))== NULL) {
2101 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2102 talloc_destroy(ea_ctx);
2103 return ERROR_DOS(ERRDOS,ERRnofiles);
2107 pstrcpy(directory,conn->dirpath);
2109 /* Get the attr mask from the dptr */
2110 dirtype = dptr_attr(dptr_num);
2112 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2113 dptr_num, mask, dirtype,
2115 dptr_TellDir(conn->dirptr)));
2117 /* We don't need to check for VOL here as this is returned by
2118 a different TRANS2 call. */
2120 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2121 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2122 dont_descend = True;
2125 space_remaining = max_data_bytes;
2126 out_of_space = False;
2129 * Seek to the correct position. We no longer use the resume key but
2130 * depend on the last file name instead.
2133 if(*resume_name && !continue_bit) {
2136 long current_pos = 0;
2138 * Remember, mangle_map is called by
2139 * get_lanman2_dir_entry(), so the resume name
2140 * could be mangled. Ensure we check the unmangled name.
2143 if (mangle_is_mangled(resume_name, conn->params)) {
2144 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2149 * Fix for NT redirector problem triggered by resume key indexes
2150 * changing between directory scans. We now return a resume key of 0
2151 * and instead look for the filename to continue from (also given
2152 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2153 * findfirst/findnext (as is usual) then the directory pointer
2154 * should already be at the correct place.
2157 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2158 } /* end if resume_name && !continue_bit */
2160 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2161 BOOL got_exact_match = False;
2163 /* this is a heuristic to avoid seeking the dirptr except when
2164 absolutely necessary. It allows for a filename of about 40 chars */
2165 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2166 out_of_space = True;
2169 finished = !get_lanman2_dir_entry(conn,
2171 mask,dirtype,info_level,
2172 requires_resume_key,dont_descend,
2173 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2174 &last_entry_off, ea_list, ea_ctx);
2177 if (finished && out_of_space)
2180 if (!finished && !out_of_space)
2184 * As an optimisation if we know we aren't looking
2185 * for a wildcard name (ie. the name matches the wildcard exactly)
2186 * then we can finish on any (first) match.
2187 * This speeds up large directory searches. JRA.
2193 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2196 talloc_destroy(ea_ctx);
2198 /* Check if we can close the dirptr */
2199 if(close_after_request || (finished && close_if_end)) {
2200 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2201 dptr_close(&dptr_num); /* This frees up the saved mask */
2204 /* Set up the return parameter block */
2205 SSVAL(params,0,numentries);
2206 SSVAL(params,2,finished);
2207 SSVAL(params,4,0); /* Never an EA error */
2208 SSVAL(params,6,last_entry_off);
2210 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2212 if ((! *directory) && dptr_path(dptr_num))
2213 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2215 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2216 smb_fn_name(CVAL(inbuf,smb_com)),
2217 mask, directory, dirtype, numentries ) );
2222 /****************************************************************************
2223 Reply to a TRANS2_QFSINFO (query filesystem info).
2224 ****************************************************************************/
2226 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2227 char **pparams, int total_params, char **ppdata, int total_data,
2228 unsigned int max_data_bytes)
2231 char *params = *pparams;
2235 const char *vname = volume_label(SNUM(conn));
2236 int snum = SNUM(conn);
2237 char *fstype = lp_fstype(SNUM(conn));
2240 if (total_params < 2) {
2241 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2244 info_level = SVAL(params,0);
2246 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2248 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2249 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2250 return ERROR_DOS(ERRSRV,ERRinvdevice);
2253 *ppdata = (char *)SMB_REALLOC(
2254 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2255 if (*ppdata == NULL ) {
2256 return ERROR_NT(NT_STATUS_NO_MEMORY);
2260 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2262 switch (info_level) {
2263 case SMB_INFO_ALLOCATION:
2265 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2267 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2268 return(UNIXERROR(ERRHRD,ERRgeneral));
2271 block_size = lp_block_size(snum);
2272 if (bsize < block_size) {
2273 SMB_BIG_UINT factor = block_size/bsize;
2278 if (bsize > block_size) {
2279 SMB_BIG_UINT factor = bsize/block_size;
2284 bytes_per_sector = 512;
2285 sectors_per_unit = bsize/bytes_per_sector;
2287 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2288 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2289 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2291 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2292 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2293 SIVAL(pdata,l1_cUnit,dsize);
2294 SIVAL(pdata,l1_cUnitAvail,dfree);
2295 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2299 case SMB_INFO_VOLUME:
2300 /* Return volume name */
2302 * Add volume serial number - hash of a combination of
2303 * the called hostname and the service name.
2305 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2307 * Win2k3 and previous mess this up by sending a name length
2308 * one byte short. I believe only older clients (OS/2 Win9x) use
2309 * this call so try fixing this by adding a terminating null to
2310 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2312 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, max_data_bytes - l2_vol_szVolLabel, STR_NOALIGN|STR_TERMINATE);
2313 SCVAL(pdata,l2_vol_cch,len);
2314 data_len = l2_vol_szVolLabel + len;
2315 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2316 (unsigned)st.st_ctime, len, vname));
2319 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2320 case SMB_FS_ATTRIBUTE_INFORMATION:
2323 #if defined(HAVE_SYS_QUOTAS)
2324 quota_flag = FILE_VOLUME_QUOTAS;
2327 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2328 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2329 quota_flag); /* FS ATTRIBUTES */
2331 SIVAL(pdata,4,255); /* Max filename component length */
2332 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2333 and will think we can't do long filenames */
2334 len = srvstr_push(outbuf, pdata+12, fstype, max_data_bytes - 12, STR_UNICODE);
2336 data_len = 12 + len;
2339 case SMB_QUERY_FS_LABEL_INFO:
2340 case SMB_FS_LABEL_INFORMATION:
2341 len = srvstr_push(outbuf, pdata+4, vname, max_data_bytes - 4, 0);
2346 case SMB_QUERY_FS_VOLUME_INFO:
2347 case SMB_FS_VOLUME_INFORMATION:
2350 * Add volume serial number - hash of a combination of
2351 * the called hostname and the service name.
2353 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2354 (str_checksum(get_local_machine_name())<<16));
2356 /* Max label len is 32 characters. */
2357 len = srvstr_push(outbuf, pdata+18, vname, max_data_bytes - 18, STR_UNICODE);
2358 SIVAL(pdata,12,len);
2361 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2362 (int)strlen(vname),vname, lp_servicename(snum)));
2365 case SMB_QUERY_FS_SIZE_INFO:
2366 case SMB_FS_SIZE_INFORMATION:
2368 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2370 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2371 return(UNIXERROR(ERRHRD,ERRgeneral));
2373 block_size = lp_block_size(snum);
2374 if (bsize < block_size) {
2375 SMB_BIG_UINT factor = block_size/bsize;
2380 if (bsize > block_size) {
2381 SMB_BIG_UINT factor = bsize/block_size;
2386 bytes_per_sector = 512;
2387 sectors_per_unit = bsize/bytes_per_sector;
2388 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2389 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2390 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2391 SBIG_UINT(pdata,0,dsize);
2392 SBIG_UINT(pdata,8,dfree);
2393 SIVAL(pdata,16,sectors_per_unit);
2394 SIVAL(pdata,20,bytes_per_sector);
2398 case SMB_FS_FULL_SIZE_INFORMATION:
2400 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2402 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2403 return(UNIXERROR(ERRHRD,ERRgeneral));
2405 block_size = lp_block_size(snum);
2406 if (bsize < block_size) {
2407 SMB_BIG_UINT factor = block_size/bsize;
2412 if (bsize > block_size) {
2413 SMB_BIG_UINT factor = bsize/block_size;
2418 bytes_per_sector = 512;
2419 sectors_per_unit = bsize/bytes_per_sector;
2420 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2421 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2422 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2423 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2424 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2425 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2426 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2427 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2431 case SMB_QUERY_FS_DEVICE_INFO:
2432 case SMB_FS_DEVICE_INFORMATION:
2434 SIVAL(pdata,0,0); /* dev type */
2435 SIVAL(pdata,4,0); /* characteristics */
2438 #ifdef HAVE_SYS_QUOTAS
2439 case SMB_FS_QUOTA_INFORMATION:
2441 * what we have to send --metze:
2443 * Unknown1: 24 NULL bytes
2444 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2445 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2446 * Quota Flags: 2 byte :
2447 * Unknown3: 6 NULL bytes
2451 * details for Quota Flags:
2453 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2454 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2455 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2456 * 0x0001 Enable Quotas: enable quota for this fs
2460 /* we need to fake up a fsp here,
2461 * because its not send in this call
2464 SMB_NTQUOTA_STRUCT quotas;
2467 ZERO_STRUCT(quotas);
2473 if (current_user.ut.uid != 0) {
2474 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2475 lp_servicename(SNUM(conn)),conn->user));
2476 return ERROR_DOS(ERRDOS,ERRnoaccess);
2479 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2480 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2481 return ERROR_DOS(ERRSRV,ERRerror);
2486 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2488 /* Unknown1 24 NULL bytes*/
2489 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2490 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2491 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2493 /* Default Soft Quota 8 bytes */
2494 SBIG_UINT(pdata,24,quotas.softlim);
2496 /* Default Hard Quota 8 bytes */
2497 SBIG_UINT(pdata,32,quotas.hardlim);
2499 /* Quota flag 2 bytes */
2500 SSVAL(pdata,40,quotas.qflags);
2502 /* Unknown3 6 NULL bytes */
2508 #endif /* HAVE_SYS_QUOTAS */
2509 case SMB_FS_OBJECTID_INFORMATION:
2514 * Query the version and capabilities of the CIFS UNIX extensions
2518 case SMB_QUERY_CIFS_UNIX_INFO:
2519 if (!lp_unix_extensions()) {
2520 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2523 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2524 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2525 /* We have POSIX ACLs, pathname and locking capability. */
2526 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2527 CIFS_UNIX_POSIX_ACLS_CAP|
2528 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2529 CIFS_UNIX_FCNTL_LOCKS_CAP|
2530 CIFS_UNIX_EXTATTR_CAP|
2531 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2534 case SMB_QUERY_POSIX_FS_INFO:
2537 vfs_statvfs_struct svfs;
2539 if (!lp_unix_extensions()) {
2540 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2543 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2547 SIVAL(pdata,0,svfs.OptimalTransferSize);
2548 SIVAL(pdata,4,svfs.BlockSize);
2549 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2550 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2551 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2552 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2553 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2554 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2555 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2557 } else if (rc == EOPNOTSUPP) {
2558 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2559 #endif /* EOPNOTSUPP */
2561 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2562 return ERROR_DOS(ERRSRV,ERRerror);
2567 case SMB_QUERY_POSIX_WHOAMI:
2573 if (!lp_unix_extensions()) {
2574 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2577 if (max_data_bytes < 40) {
2578 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2581 /* We ARE guest if global_sid_Builtin_Guests is
2582 * in our list of SIDs.
2584 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2585 current_user.nt_user_token)) {
2586 flags |= SMB_WHOAMI_GUEST;
2589 /* We are NOT guest if global_sid_Authenticated_Users
2590 * is in our list of SIDs.
2592 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2593 current_user.nt_user_token)) {
2594 flags &= ~SMB_WHOAMI_GUEST;
2597 /* NOTE: 8 bytes for UID/GID, irrespective of native
2598 * platform size. This matches
2599 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2601 data_len = 4 /* flags */
2608 + 4 /* pad/reserved */
2609 + (current_user.ut.ngroups * 8)
2611 + (current_user.nt_user_token->num_sids *
2615 SIVAL(pdata, 0, flags);
2616 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2617 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2618 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2621 if (data_len >= max_data_bytes) {
2622 /* Potential overflow, skip the GIDs and SIDs. */
2624 SIVAL(pdata, 24, 0); /* num_groups */
2625 SIVAL(pdata, 28, 0); /* num_sids */
2626 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2627 SIVAL(pdata, 36, 0); /* reserved */
2633 SIVAL(pdata, 24, current_user.ut.ngroups);
2635 current_user.nt_user_token->num_sids);
2637 /* We walk the SID list twice, but this call is fairly
2638 * infrequent, and I don't expect that it's performance
2639 * sensitive -- jpeach
2641 for (i = 0, sid_bytes = 0;
2642 i < current_user.nt_user_token->num_sids; ++i) {
2644 sid_size(¤t_user.nt_user_token->user_sids[i]);
2647 /* SID list byte count */
2648 SIVAL(pdata, 32, sid_bytes);
2650 /* 4 bytes pad/reserved - must be zero */
2651 SIVAL(pdata, 36, 0);
2655 for (i = 0; i < current_user.ut.ngroups; ++i) {
2656 SBIG_UINT(pdata, data_len,
2657 (SMB_BIG_UINT)current_user.ut.groups[i]);
2663 i < current_user.nt_user_token->num_sids; ++i) {
2665 sid_size(¤t_user.nt_user_token->user_sids[i]);
2667 sid_linearize(pdata + data_len, sid_len,
2668 ¤t_user.nt_user_token->user_sids[i]);
2669 data_len += sid_len;
2675 case SMB_MAC_QUERY_FS_INFO:
2677 * Thursby MAC extension... ONLY on NTFS filesystems
2678 * once we do streams then we don't need this
2680 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2682 SIVAL(pdata,84,0x100); /* Don't support mac... */
2687 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2691 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2693 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2698 /****************************************************************************
2699 Reply to a TRANS2_SETFSINFO (set filesystem info).
2700 ****************************************************************************/
2702 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2703 char **pparams, int total_params, char **ppdata, int total_data,
2704 unsigned int max_data_bytes)
2706 char *pdata = *ppdata;
2707 char *params = *pparams;
2711 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2714 if (total_params < 4) {
2715 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2717 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2720 info_level = SVAL(params,2);
2722 switch(info_level) {
2723 case SMB_SET_CIFS_UNIX_INFO:
2725 uint16 client_unix_major;
2726 uint16 client_unix_minor;
2727 uint32 client_unix_cap_low;
2728 uint32 client_unix_cap_high;
2730 if (!lp_unix_extensions()) {
2731 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2734 /* There should be 12 bytes of capabilities set. */
2735 if (total_data < 8) {
2736 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2738 client_unix_major = SVAL(pdata,0);
2739 client_unix_minor = SVAL(pdata,2);
2740 client_unix_cap_low = IVAL(pdata,4);
2741 client_unix_cap_high = IVAL(pdata,8);
2742 /* Just print these values for now. */
2743 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2744 cap_low = 0x%x, cap_high = 0x%x\n",
2745 (unsigned int)client_unix_major,
2746 (unsigned int)client_unix_minor,
2747 (unsigned int)client_unix_cap_low,
2748 (unsigned int)client_unix_cap_high ));
2750 /* Here is where we must switch to posix pathname processing... */
2751 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2752 lp_set_posix_pathnames();
2753 mangle_change_to_posix();
2756 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2757 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2758 /* Client that knows how to do posix locks,
2759 * but not posix open/mkdir operations. Set a
2760 * default type for read/write checks. */
2762 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2767 case SMB_FS_QUOTA_INFORMATION:
2769 files_struct *fsp = NULL;
2770 SMB_NTQUOTA_STRUCT quotas;
2772 ZERO_STRUCT(quotas);
2775 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2776 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2777 lp_servicename(SNUM(conn)),conn->user));
2778 return ERROR_DOS(ERRSRV,ERRaccess);
2781 /* note: normaly there're 48 bytes,
2782 * but we didn't use the last 6 bytes for now
2785 fsp = file_fsp(params,0);
2786 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2787 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2788 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2791 if (total_data < 42) {
2792 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2794 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2797 /* unknown_1 24 NULL bytes in pdata*/
2799 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2800 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2801 #ifdef LARGE_SMB_OFF_T
2802 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2803 #else /* LARGE_SMB_OFF_T */
2804 if ((IVAL(pdata,28) != 0)&&
2805 ((quotas.softlim != 0xFFFFFFFF)||
2806 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2807 /* more than 32 bits? */
2808 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2810 #endif /* LARGE_SMB_OFF_T */
2812 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2813 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2814 #ifdef LARGE_SMB_OFF_T
2815 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2816 #else /* LARGE_SMB_OFF_T */
2817 if ((IVAL(pdata,36) != 0)&&
2818 ((quotas.hardlim != 0xFFFFFFFF)||
2819 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2820 /* more than 32 bits? */
2821 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2823 #endif /* LARGE_SMB_OFF_T */
2825 /* quota_flags 2 bytes **/
2826 quotas.qflags = SVAL(pdata,40);
2828 /* unknown_2 6 NULL bytes follow*/
2830 /* now set the quotas */
2831 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2832 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2833 return ERROR_DOS(ERRSRV,ERRerror);
2839 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2841 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2846 * sending this reply works fine,
2847 * but I'm not sure it's the same
2848 * like windows do...
2851 outsize = set_message(outbuf,10,0,True);
2856 #if defined(HAVE_POSIX_ACLS)
2857 /****************************************************************************
2858 Utility function to count the number of entries in a POSIX acl.
2859 ****************************************************************************/
2861 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2863 unsigned int ace_count = 0;
2864 int entry_id = SMB_ACL_FIRST_ENTRY;
2865 SMB_ACL_ENTRY_T entry;
2867 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2869 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2870 entry_id = SMB_ACL_NEXT_ENTRY;
2877 /****************************************************************************
2878 Utility function to marshall a POSIX acl into wire format.
2879 ****************************************************************************/
2881 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2883 int entry_id = SMB_ACL_FIRST_ENTRY;
2884 SMB_ACL_ENTRY_T entry;
2886 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2887 SMB_ACL_TAG_T tagtype;
2888 SMB_ACL_PERMSET_T permset;
2889 unsigned char perms = 0;
2890 unsigned int own_grp;
2893 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2894 entry_id = SMB_ACL_NEXT_ENTRY;
2897 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2898 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2902 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2903 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2907 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2908 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2909 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2911 SCVAL(pdata,1,perms);
2914 case SMB_ACL_USER_OBJ:
2915 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2916 own_grp = (unsigned int)pst->st_uid;
2917 SIVAL(pdata,2,own_grp);
2922 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2924 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2926 own_grp = (unsigned int)*puid;
2927 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2928 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2929 SIVAL(pdata,2,own_grp);
2933 case SMB_ACL_GROUP_OBJ:
2934 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2935 own_grp = (unsigned int)pst->st_gid;
2936 SIVAL(pdata,2,own_grp);
2941 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2943 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2945 own_grp = (unsigned int)*pgid;
2946 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2947 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2948 SIVAL(pdata,2,own_grp);
2953 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2954 SIVAL(pdata,2,0xFFFFFFFF);
2955 SIVAL(pdata,6,0xFFFFFFFF);
2958 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2959 SIVAL(pdata,2,0xFFFFFFFF);
2960 SIVAL(pdata,6,0xFFFFFFFF);
2963 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2966 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2973 /****************************************************************************
2974 Store the FILE_UNIX_BASIC info.
2975 ****************************************************************************/
2977 static char *store_file_unix_basic(connection_struct *conn,
2980 const SMB_STRUCT_STAT *psbuf)
2982 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2983 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
2985 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
2988 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2991 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
2992 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
2993 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
2996 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3000 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3004 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3007 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3011 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3015 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3018 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3022 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3029 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3030 * the chflags(2) (or equivalent) flags.
3032 * XXX: this really should be behind the VFS interface. To do this, we would
3033 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3034 * Each VFS module could then implement it's own mapping as appropriate for the
3035 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3037 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3041 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3045 { UF_IMMUTABLE, EXT_IMMUTABLE },
3049 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3053 { UF_HIDDEN, EXT_HIDDEN },
3056 /* Do not remove. We need to guarantee that this array has at least one
3057 * entry to build on HP-UX.
3063 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3064 uint32 *smb_fflags, uint32 *smb_fmask)
3066 #ifdef HAVE_STAT_ST_FLAGS
3069 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3070 *smb_fmask |= info2_flags_map[i].smb_fflag;
3071 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3072 *smb_fflags |= info2_flags_map[i].smb_fflag;
3075 #endif /* HAVE_STAT_ST_FLAGS */
3078 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3079 const uint32 smb_fflags,
3080 const uint32 smb_fmask,
3083 #ifdef HAVE_STAT_ST_FLAGS
3084 uint32 max_fmask = 0;
3087 *stat_fflags = psbuf->st_flags;
3089 /* For each flags requested in smb_fmask, check the state of the
3090 * corresponding flag in smb_fflags and set or clear the matching
3094 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3095 max_fmask |= info2_flags_map[i].smb_fflag;
3096 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3097 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3098 *stat_fflags |= info2_flags_map[i].stat_fflag;
3100 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3105 /* If smb_fmask is asking to set any bits that are not supported by
3106 * our flag mappings, we should fail.
3108 if ((smb_fmask & max_fmask) != smb_fmask) {
3115 #endif /* HAVE_STAT_ST_FLAGS */
3119 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3120 * of file flags and birth (create) time.
3122 static char *store_file_unix_basic_info2(connection_struct *conn,
3125 const SMB_STRUCT_STAT *psbuf)
3127 uint32 file_flags = 0;
3128 uint32 flags_mask = 0;
3130 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3132 /* Create (birth) time 64 bit */
3133 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3136 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3137 SIVAL(pdata, 0, file_flags); /* flags */
3138 SIVAL(pdata, 4, flags_mask); /* mask */
3144 /****************************************************************************
3145 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3146 file name or file id).
3147 ****************************************************************************/
3149 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3150 unsigned int tran_call,
3151 char **pparams, int total_params, char **ppdata, int total_data,
3152 unsigned int max_data_bytes)
3154 char *params = *pparams;
3155 char *pdata = *ppdata;
3159 SMB_OFF_T file_size=0;
3160 SMB_BIG_UINT allocation_size=0;
3161 unsigned int data_size = 0;
3162 unsigned int param_size = 2;
3163 SMB_STRUCT_STAT sbuf;
3164 pstring fname, dos_fname;
3169 BOOL delete_pending = False;
3171 time_t create_time, mtime, atime;
3172 struct timespec create_time_ts, mtime_ts, atime_ts;
3173 files_struct *fsp = NULL;
3174 TALLOC_CTX *data_ctx = NULL;
3175 struct ea_list *ea_list = NULL;
3176 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3177 char *lock_data = NULL;
3180 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3184 if (tran_call == TRANSACT2_QFILEINFO) {
3185 if (total_params < 4) {
3186 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3189 fsp = file_fsp(params,0);
3190 info_level = SVAL(params,2);
3192 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3194 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3195 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3198 if(fsp && (fsp->fake_file_handle)) {
3200 * This is actually for the QUOTA_FAKE_FILE --metze
3203 pstrcpy(fname, fsp->fsp_name);
3204 /* We know this name is ok, it's already passed the checks. */
3206 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3208 * This is actually a QFILEINFO on a directory
3209 * handle (returned from an NT SMB). NT5.0 seems
3210 * to do this call. JRA.
3212 /* We know this name is ok, it's already passed the checks. */
3213 pstrcpy(fname, fsp->fsp_name);
3215 if (INFO_LEVEL_IS_UNIX(info_level)) {
3216 /* Always do lstat for UNIX calls. */
3217 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3218 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3219 return UNIXERROR(ERRDOS,ERRbadpath);
3221 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3222 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3223 return UNIXERROR(ERRDOS,ERRbadpath);
3226 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3229 * Original code - this is an open file.
3231 CHECK_FSP(fsp,conn);
3233 pstrcpy(fname, fsp->fsp_name);
3234 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3235 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3236 return(UNIXERROR(ERRDOS,ERRbadfid));
3238 pos = fsp->fh->position_information;
3239 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3240 access_mask = fsp->access_mask;
3243 NTSTATUS status = NT_STATUS_OK;
3246 if (total_params < 7) {
3247 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3250 info_level = SVAL(params,0);
3252 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3254 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3255 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3258 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3259 if (!NT_STATUS_IS_OK(status)) {
3260 return ERROR_NT(status);
3263 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3264 if (!NT_STATUS_IS_OK(status)) {
3265 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3266 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3268 return ERROR_NT(status);
3271 status = unix_convert(conn, fname, False, NULL, &sbuf);
3272 if (!NT_STATUS_IS_OK(status)) {
3273 return ERROR_NT(status);
3275 status = check_name(conn, fname);
3276 if (!NT_STATUS_IS_OK(status)) {
3277 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3278 return ERROR_NT(status);
3281 if (INFO_LEVEL_IS_UNIX(info_level)) {
3282 /* Always do lstat for UNIX calls. */
3283 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3284 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3285 return UNIXERROR(ERRDOS,ERRbadpath);
3287 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3288 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3289 return UNIXERROR(ERRDOS,ERRbadpath);
3292 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3293 if (delete_pending) {
3294 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3298 nlink = sbuf.st_nlink;
3300 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3301 /* NTFS does not seem to count ".." */
3305 if ((nlink > 0) && delete_pending) {
3309 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3310 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3313 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3314 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3316 p = strrchr_m(fname,'/');
3322 mode = dos_mode(conn,fname,&sbuf);
3324 mode = FILE_ATTRIBUTE_NORMAL;
3326 fullpathname = fname;
3328 file_size = get_file_size(sbuf);
3330 /* Pull out any data sent here before we realloc. */
3331 switch (info_level) {
3332 case SMB_INFO_QUERY_EAS_FROM_LIST:
3334 /* Pull any EA list from the data portion. */
3337 if (total_data < 4) {
3338 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3340 ea_size = IVAL(pdata,0);
3342 if (total_data > 0 && ea_size != total_data) {
3343 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3344 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3345 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3348 if (!lp_ea_support(SNUM(conn))) {
3349 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3352 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3353 return ERROR_NT(NT_STATUS_NO_MEMORY);
3356 /* Pull out the list of names. */
3357 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3359 talloc_destroy(data_ctx);
3360 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3365 case SMB_QUERY_POSIX_LOCK:
3367 if (fsp == NULL || fsp->fh->fd == -1) {
3368 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3371 if (total_data != POSIX_LOCK_DATA_SIZE) {
3372 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3375 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3376 return ERROR_NT(NT_STATUS_NO_MEMORY);
3379 /* Copy the lock range data. */
3380 lock_data = (char *)TALLOC_MEMDUP(
3381 data_ctx, pdata, total_data);
3383 talloc_destroy(data_ctx);
3384 return ERROR_NT(NT_STATUS_NO_MEMORY);
3391 *pparams = (char *)SMB_REALLOC(*pparams,2);
3392 if (*pparams == NULL) {
3393 talloc_destroy(data_ctx);
3394 return ERROR_NT(NT_STATUS_NO_MEMORY);
3398 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3399 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3400 if (*ppdata == NULL ) {
3401 talloc_destroy(data_ctx);
3402 return ERROR_NT(NT_STATUS_NO_MEMORY);
3406 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3407 mtime_ts = get_mtimespec(&sbuf);
3408 atime_ts = get_atimespec(&sbuf);
3410 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3413 if (!null_timespec(fsp->pending_modtime)) {
3414 /* the pending modtime overrides the current modtime */
3415 mtime_ts = fsp->pending_modtime;
3418 /* Do we have this path open ? */
3419 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3420 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3421 /* the pending modtime overrides the current modtime */
3422 mtime_ts = fsp1->pending_modtime;
3424 if (fsp1 && fsp1->initial_allocation_size) {
3425 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3429 if (lp_dos_filetime_resolution(SNUM(conn))) {
3430 dos_filetime_timespec(&create_time_ts);
3431 dos_filetime_timespec(&mtime_ts);
3432 dos_filetime_timespec(&atime_ts);
3435 create_time = convert_timespec_to_time_t(create_time_ts);
3436 mtime = convert_timespec_to_time_t(mtime_ts);
3437 atime = convert_timespec_to_time_t(atime_ts);
3439 /* NT expects the name to be in an exact form of the *full*
3440 filename. See the trans2 torture test */
3441 if (strequal(base_name,".")) {
3442 pstrcpy(dos_fname, "\\");
3444 pstr_sprintf(dos_fname, "\\%s", fname);
3445 string_replace(dos_fname, '/', '\\');
3448 switch (info_level) {
3449 case SMB_INFO_STANDARD:
3450 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3452 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3453 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3454 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3455 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3456 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3457 SSVAL(pdata,l1_attrFile,mode);
3460 case SMB_INFO_QUERY_EA_SIZE:
3462 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3463 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3465 srv_put_dos_date2(pdata,0,create_time);
3466 srv_put_dos_date2(pdata,4,atime);
3467 srv_put_dos_date2(pdata,8,mtime); /* write time */
3468 SIVAL(pdata,12,(uint32)file_size);
3469 SIVAL(pdata,16,(uint32)allocation_size);
3470 SSVAL(pdata,20,mode);
3471 SIVAL(pdata,22,ea_size);
3475 case SMB_INFO_IS_NAME_VALID:
3476 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3477 if (tran_call == TRANSACT2_QFILEINFO) {
3478 /* os/2 needs this ? really ?*/
3479 return ERROR_DOS(ERRDOS,ERRbadfunc);
3485 case SMB_INFO_QUERY_EAS_FROM_LIST:
3487 size_t total_ea_len = 0;
3488 struct ea_list *ea_file_list = NULL;
3490 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3492 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3493 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3495 if (!ea_list || (total_ea_len > data_size)) {
3496 talloc_destroy(data_ctx);
3498 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3502 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3503 talloc_destroy(data_ctx);
3507 case SMB_INFO_QUERY_ALL_EAS:
3509 /* We have data_size bytes to put EA's into. */
3510 size_t total_ea_len = 0;
3512 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3514 data_ctx = talloc_init("ea_ctx");
3516 return ERROR_NT(NT_STATUS_NO_MEMORY);
3519 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3520 if (!ea_list || (total_ea_len > data_size)) {
3521 talloc_destroy(data_ctx);
3523 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3527 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3528 talloc_destroy(data_ctx);
3532 case SMB_FILE_BASIC_INFORMATION:
3533 case SMB_QUERY_FILE_BASIC_INFO:
3535 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3536 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3537 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3539 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3543 put_long_date_timespec(pdata,create_time_ts);
3544 put_long_date_timespec(pdata+8,atime_ts);
3545 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3546 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3547 SIVAL(pdata,32,mode);
3549 DEBUG(5,("SMB_QFBI - "));
3550 DEBUG(5,("create: %s ", ctime(&create_time)));
3551 DEBUG(5,("access: %s ", ctime(&atime)));
3552 DEBUG(5,("write: %s ", ctime(&mtime)));
3553 DEBUG(5,("change: %s ", ctime(&mtime)));
3554 DEBUG(5,("mode: %x\n", mode));
3557 case SMB_FILE_STANDARD_INFORMATION:
3558 case SMB_QUERY_FILE_STANDARD_INFO:
3560 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3562 SOFF_T(pdata,0,allocation_size);
3563 SOFF_T(pdata,8,file_size);
3564 SIVAL(pdata,16,nlink);
3565 SCVAL(pdata,20,delete_pending?1:0);
3566 SCVAL(pdata,21,(mode&aDIR)?1:0);
3567 SSVAL(pdata,22,0); /* Padding. */
3570 case SMB_FILE_EA_INFORMATION:
3571 case SMB_QUERY_FILE_EA_INFO:
3573 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3574 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3576 SIVAL(pdata,0,ea_size);
3580 /* Get the 8.3 name - used if NT SMB was negotiated. */
3581 case SMB_QUERY_FILE_ALT_NAME_INFO:
3582 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3586 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3587 pstrcpy(short_name,base_name);
3588 /* Mangle if not already 8.3 */
3589 if(!mangle_is_8_3(short_name, True, conn->params)) {
3590 mangle_map(short_name,True,True,conn->params);
3592 len = srvstr_push(outbuf, pdata+4, short_name, max_data_bytes - 4, STR_UNICODE);
3593 data_size = 4 + len;
3598 case SMB_QUERY_FILE_NAME_INFO:
3600 this must be *exactly* right for ACLs on mapped drives to work
3602 len = srvstr_push(outbuf, pdata+4, dos_fname, max_data_bytes - 4, STR_UNICODE);
3603 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3604 data_size = 4 + len;
3608 case SMB_FILE_ALLOCATION_INFORMATION:
3609 case SMB_QUERY_FILE_ALLOCATION_INFO:
3610 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3612 SOFF_T(pdata,0,allocation_size);
3615 case SMB_FILE_END_OF_FILE_INFORMATION:
3616 case SMB_QUERY_FILE_END_OF_FILEINFO:
3617 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3619 SOFF_T(pdata,0,file_size);
3622 case SMB_QUERY_FILE_ALL_INFO:
3623 case SMB_FILE_ALL_INFORMATION:
3625 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3626 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3627 put_long_date_timespec(pdata,create_time_ts);
3628 put_long_date_timespec(pdata+8,atime_ts);
3629 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3630 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3631 SIVAL(pdata,32,mode);
3632 SIVAL(pdata,36,0); /* padding. */
3634 SOFF_T(pdata,0,allocation_size);
3635 SOFF_T(pdata,8,file_size);
3636 SIVAL(pdata,16,nlink);
3637 SCVAL(pdata,20,delete_pending);
3638 SCVAL(pdata,21,(mode&aDIR)?1:0);
3641 SIVAL(pdata,0,ea_size);
3642 pdata += 4; /* EA info */
3643 len = srvstr_push(outbuf, pdata+4, dos_fname, max_data_bytes - (pdata+4 - *ppdata), STR_UNICODE);
3646 data_size = PTR_DIFF(pdata,(*ppdata));
3649 case SMB_FILE_INTERNAL_INFORMATION:
3650 /* This should be an index number - looks like
3653 I think this causes us to fail the IFSKIT
3654 BasicFileInformationTest. -tpot */
3656 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3657 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3658 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3662 case SMB_FILE_ACCESS_INFORMATION:
3663 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3664 SIVAL(pdata,0,access_mask);
3668 case SMB_FILE_NAME_INFORMATION:
3669 /* Pathname with leading '\'. */
3672 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3673 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3674 SIVAL(pdata,0,byte_len);
3675 data_size = 4 + byte_len;
3679 case SMB_FILE_DISPOSITION_INFORMATION:
3680 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3682 SCVAL(pdata,0,delete_pending);
3685 case SMB_FILE_POSITION_INFORMATION:
3686 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3688 SOFF_T(pdata,0,pos);
3691 case SMB_FILE_MODE_INFORMATION:
3692 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3693 SIVAL(pdata,0,mode);
3697 case SMB_FILE_ALIGNMENT_INFORMATION:
3698 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3699 SIVAL(pdata,0,0); /* No alignment needed. */
3705 * NT4 server just returns "invalid query" to this - if we try to answer
3706 * it then NTws gets a BSOD! (tridge).
3707 * W2K seems to want this. JRA.
3709 case SMB_QUERY_FILE_STREAM_INFO:
3711 case SMB_FILE_STREAM_INFORMATION:
3712 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3716 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3717 SIVAL(pdata,0,0); /* ??? */
3718 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3719 SOFF_T(pdata,8,file_size);
3720 SOFF_T(pdata,16,allocation_size);
3721 data_size = 24 + byte_len;
3725 case SMB_QUERY_COMPRESSION_INFO:
3726 case SMB_FILE_COMPRESSION_INFORMATION:
3727 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3728 SOFF_T(pdata,0,file_size);
3729 SIVAL(pdata,8,0); /* ??? */
3730 SIVAL(pdata,12,0); /* ??? */
3734 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3735 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3736 put_long_date_timespec(pdata,create_time_ts);
3737 put_long_date_timespec(pdata+8,atime_ts);
3738 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3739 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3740 SOFF_T(pdata,32,allocation_size);
3741 SOFF_T(pdata,40,file_size);
3742 SIVAL(pdata,48,mode);
3743 SIVAL(pdata,52,0); /* ??? */
3747 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3748 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3749 SIVAL(pdata,0,mode);
3755 * CIFS UNIX Extensions.
3758 case SMB_QUERY_FILE_UNIX_BASIC:
3760 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3761 data_size = PTR_DIFF(pdata,(*ppdata));
3765 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3767 for (i=0; i<100; i++)
3768 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3774 case SMB_QUERY_FILE_UNIX_INFO2:
3776 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3777 data_size = PTR_DIFF(pdata,(*ppdata));
3781 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3783 for (i=0; i<100; i++)
3784 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3790 case SMB_QUERY_FILE_UNIX_LINK:
3794 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3796 if(!S_ISLNK(sbuf.st_mode))
3797 return(UNIXERROR(ERRSRV,ERRbadlink));
3799 return(UNIXERROR(ERRDOS,ERRbadlink));
3801 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3803 return(UNIXERROR(ERRDOS,ERRnoaccess));
3805 len = srvstr_push(outbuf, pdata, buffer, max_data_bytes, STR_TERMINATE);
3807 data_size = PTR_DIFF(pdata,(*ppdata));
3812 #if defined(HAVE_POSIX_ACLS)
3813 case SMB_QUERY_POSIX_ACL:
3815 SMB_ACL_T file_acl = NULL;
3816 SMB_ACL_T def_acl = NULL;
3817 uint16 num_file_acls = 0;
3818 uint16 num_def_acls = 0;
3820 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3821 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3823 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3826 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3827 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3829 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3832 if (S_ISDIR(sbuf.st_mode)) {
3833 if (fsp && fsp->is_directory) {
3834 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3836 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3838 def_acl = free_empty_sys_acl(conn, def_acl);
3841 num_file_acls = count_acl_entries(conn, file_acl);
3842 num_def_acls = count_acl_entries(conn, def_acl);
3844 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3845 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3847 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3848 SMB_POSIX_ACL_HEADER_SIZE) ));
3850 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3853 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3855 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3858 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3859 SSVAL(pdata,2,num_file_acls);
3860 SSVAL(pdata,4,num_def_acls);
3861 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3863 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3866 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3868 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3870 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3872 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3875 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3877 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3881 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3884 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3886 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3892 case SMB_QUERY_POSIX_LOCK:
3894 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3896 SMB_BIG_UINT offset;
3898 enum brl_type lock_type;
3900 if (total_data != POSIX_LOCK_DATA_SIZE) {
3901 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3904 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3905 case POSIX_LOCK_TYPE_READ:
3906 lock_type = READ_LOCK;
3908 case POSIX_LOCK_TYPE_WRITE:
3909 lock_type = WRITE_LOCK;
3911 case POSIX_LOCK_TYPE_UNLOCK:
3913 /* There's no point in asking for an unlock... */
3914 talloc_destroy(data_ctx);
3915 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3918 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3919 #if defined(HAVE_LONGLONG)
3920 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3921 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3922 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3923 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3924 #else /* HAVE_LONGLONG */
3925 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3926 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3927 #endif /* HAVE_LONGLONG */
3929 status = query_lock(fsp,
3936 if (ERROR_WAS_LOCK_DENIED(status)) {
3937 /* Here we need to report who has it locked... */
3938 data_size = POSIX_LOCK_DATA_SIZE;
3940 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3941 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3942 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3943 #if defined(HAVE_LONGLONG)
3944 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3945 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3946 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3947 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3948 #else /* HAVE_LONGLONG */
3949 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3950 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3951 #endif /* HAVE_LONGLONG */
3953 } else if (NT_STATUS_IS_OK(status)) {
3954 /* For success we just return a copy of what we sent
3955 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3956 data_size = POSIX_LOCK_DATA_SIZE;
3957 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3958 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3960 return ERROR_NT(status);
3966 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3969 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3974 /****************************************************************************
3975 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3977 ****************************************************************************/
3979 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3981 SMB_STRUCT_STAT sbuf1, sbuf2;
3982 pstring last_component_oldname;
3983 pstring last_component_newname;
3984 NTSTATUS status = NT_STATUS_OK;
3989 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3990 if (!NT_STATUS_IS_OK(status)) {
3994 status = check_name(conn, oldname);
3995 if (!NT_STATUS_IS_OK(status)) {
3999 /* source must already exist. */
4000 if (!VALID_STAT(sbuf1)) {
4001 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4004 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4005 if (!NT_STATUS_IS_OK(status)) {
4009 status = check_name(conn, newname);
4010 if (!NT_STATUS_IS_OK(status)) {
4014 /* Disallow if newname already exists. */
4015 if (VALID_STAT(sbuf2)) {
4016 return NT_STATUS_OBJECT_NAME_COLLISION;
4019 /* No links from a directory. */
4020 if (S_ISDIR(sbuf1.st_mode)) {
4021 return NT_STATUS_FILE_IS_A_DIRECTORY;
4024 /* Ensure this is within the share. */
4025 status = reduce_name(conn, oldname);
4026 if (!NT_STATUS_IS_OK(status)) {
4030 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4032 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4033 status = map_nt_error_from_unix(errno);
4034 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4035 nt_errstr(status), newname, oldname));
4041 /****************************************************************************
4042 Deal with setting the time from any of the setfilepathinfo functions.
4043 ****************************************************************************/
4045 static NTSTATUS smb_set_file_time(connection_struct *conn,
4048 const SMB_STRUCT_STAT *psbuf,
4049 struct timespec ts[2])
4052 FILE_NOTIFY_CHANGE_LAST_ACCESS
4053 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4056 if (!VALID_STAT(*psbuf)) {
4057 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4060 /* get some defaults (no modifications) if any info is zero or -1. */
4061 if (null_timespec(ts[0])) {
4062 ts[0] = get_atimespec(psbuf);
4063 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4066 if (null_timespec(ts[1])) {
4067 ts[1] = get_mtimespec(psbuf);
4068 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4071 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4072 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4075 * Try and set the times of this file if
4076 * they are different from the current values.
4080 struct timespec mts = get_mtimespec(psbuf);
4081 struct timespec ats = get_atimespec(psbuf);
4082 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4083 return NT_STATUS_OK;
4089 * This was a setfileinfo on an open file.
4090 * NT does this a lot. We also need to
4091 * set the time here, as it can be read by
4092 * FindFirst/FindNext and with the patch for bug #2045
4093 * in smbd/fileio.c it ensures that this timestamp is
4094 * kept sticky even after a write. We save the request
4095 * away and will set it on file close and after a write. JRA.
4098 if (!null_timespec(ts[1])) {
4099 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4100 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4101 fsp_set_pending_modtime(fsp, ts[1]);
4105 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4107 if(file_ntimes(conn, fname, ts)!=0) {
4108 return map_nt_error_from_unix(errno);
4111 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4113 return NT_STATUS_OK;
4116 /****************************************************************************
4117 Deal with setting the dosmode from any of the setfilepathinfo functions.
4118 ****************************************************************************/
4120 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4122 SMB_STRUCT_STAT *psbuf,
4125 if (!VALID_STAT(*psbuf)) {
4126 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4130 if (S_ISDIR(psbuf->st_mode)) {
4137 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4139 /* check the mode isn't different, before changing it */
4140 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4142 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4143 fname, (unsigned int)dosmode ));
4145 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4146 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4147 fname, strerror(errno)));
4148 return map_nt_error_from_unix(errno);
4151 return NT_STATUS_OK;
4154 /****************************************************************************
4155 Deal with setting the size from any of the setfilepathinfo functions.
4156 ****************************************************************************/
4158 static NTSTATUS smb_set_file_size(connection_struct *conn,
4161 SMB_STRUCT_STAT *psbuf,
4164 NTSTATUS status = NT_STATUS_OK;
4165 files_struct *new_fsp = NULL;
4167 if (!VALID_STAT(*psbuf)) {
4168 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4171 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4173 if (size == get_file_size(*psbuf)) {
4174 return NT_STATUS_OK;
4177 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4178 fname, (double)size ));
4180 if (fsp && fsp->fh->fd != -1) {
4181 /* Handle based call. */
4182 if (vfs_set_filelen(fsp, size) == -1) {
4183 return map_nt_error_from_unix(errno);
4185 return NT_STATUS_OK;
4188 status = open_file_ntcreate(conn, fname, psbuf,
4190 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4193 FILE_ATTRIBUTE_NORMAL,
4194 FORCE_OPLOCK_BREAK_TO_NONE,
4197 if (!NT_STATUS_IS_OK(status)) {
4198 /* NB. We check for open_was_deferred in the caller. */
4202 if (vfs_set_filelen(new_fsp, size) == -1) {
4203 status = map_nt_error_from_unix(errno);
4204 close_file(new_fsp,NORMAL_CLOSE);
4208 close_file(new_fsp,NORMAL_CLOSE);
4209 return NT_STATUS_OK;
4212 /****************************************************************************
4213 Deal with SMB_INFO_SET_EA.
4214 ****************************************************************************/
4216 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4222 struct ea_list *ea_list = NULL;
4223 TALLOC_CTX *ctx = NULL;
4224 NTSTATUS status = NT_STATUS_OK;
4226 if (total_data < 10) {
4228 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4229 length. They seem to have no effect. Bug #3212. JRA */
4231 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4232 /* We're done. We only get EA info in this call. */
4233 return NT_STATUS_OK;
4236 return NT_STATUS_INVALID_PARAMETER;
4239 if (IVAL(pdata,0) > total_data) {
4240 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4241 IVAL(pdata,0), (unsigned int)total_data));
4242 return NT_STATUS_INVALID_PARAMETER;
4245 ctx = talloc_init("SMB_INFO_SET_EA");
4247 return NT_STATUS_NO_MEMORY;
4249 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4251 talloc_destroy(ctx);
4252 return NT_STATUS_INVALID_PARAMETER;
4254 status = set_ea(conn, fsp, fname, ea_list);
4255 talloc_destroy(ctx);
4260 /****************************************************************************
4261 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4262 ****************************************************************************/
4264 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4269 SMB_STRUCT_STAT *psbuf)
4271 NTSTATUS status = NT_STATUS_OK;
4272 BOOL delete_on_close;
4275 if (total_data < 1) {
4276 return NT_STATUS_INVALID_PARAMETER;
4280 return NT_STATUS_INVALID_HANDLE;
4283 delete_on_close = (CVAL(pdata,0) ? True : False);
4284 dosmode = dos_mode(conn, fname, psbuf);
4286 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4287 "delete_on_close = %u\n",
4289 (unsigned int)dosmode,
4290 (unsigned int)delete_on_close ));
4292 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4294 if (!NT_STATUS_IS_OK(status)) {
4298 /* The set is across all open files on this dev/inode pair. */
4299 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4300 return NT_STATUS_ACCESS_DENIED;
4302 return NT_STATUS_OK;
4305 /****************************************************************************
4306 Deal with SMB_FILE_POSITION_INFORMATION.
4307 ****************************************************************************/
4309 static NTSTATUS smb_file_position_information(connection_struct *conn,
4314 SMB_BIG_UINT position_information;
4316 if (total_data < 8) {
4317 return NT_STATUS_INVALID_PARAMETER;
4321 /* Ignore on pathname based set. */
4322 return NT_STATUS_OK;
4325 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4326 #ifdef LARGE_SMB_OFF_T
4327 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4328 #else /* LARGE_SMB_OFF_T */
4329 if (IVAL(pdata,4) != 0) {
4330 /* more than 32 bits? */
4331 return NT_STATUS_INVALID_PARAMETER;
4333 #endif /* LARGE_SMB_OFF_T */
4335 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4336 fsp->fsp_name, (double)position_information ));
4337 fsp->fh->position_information = position_information;
4338 return NT_STATUS_OK;
4341 /****************************************************************************
4342 Deal with SMB_FILE_MODE_INFORMATION.
4343 ****************************************************************************/
4345 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4351 if (total_data < 4) {
4352 return NT_STATUS_INVALID_PARAMETER;
4354 mode = IVAL(pdata,0);
4355 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4356 return NT_STATUS_INVALID_PARAMETER;
4358 return NT_STATUS_OK;
4361 /****************************************************************************
4362 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4363 ****************************************************************************/
4365 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4371 pstring link_target;
4372 const char *newname = fname;
4373 NTSTATUS status = NT_STATUS_OK;
4375 /* Set a symbolic link. */
4376 /* Don't allow this if follow links is false. */
4378 if (total_data == 0) {
4379 return NT_STATUS_INVALID_PARAMETER;
4382 if (!lp_symlinks(SNUM(conn))) {
4383 return NT_STATUS_ACCESS_DENIED;
4386 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4388 /* !widelinks forces the target path to be within the share. */
4389 /* This means we can interpret the target as a pathname. */
4390 if (!lp_widelinks(SNUM(conn))) {
4392 char *last_dirp = NULL;
4394 if (*link_target == '/') {
4395 /* No absolute paths allowed. */
4396 return NT_STATUS_ACCESS_DENIED;
4398 pstrcpy(rel_name, newname);
4399 last_dirp = strrchr_m(rel_name, '/');
4401 last_dirp[1] = '\0';
4403 pstrcpy(rel_name, "./");
4405 pstrcat(rel_name, link_target);
4407 status = check_name(conn, rel_name);
4408 if (!NT_STATUS_IS_OK(status)) {
4413 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4414 newname, link_target ));
4416 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4417 return map_nt_error_from_unix(errno);
4420 return NT_STATUS_OK;
4423 /****************************************************************************
4424 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4425 ****************************************************************************/
4427 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4435 NTSTATUS status = NT_STATUS_OK;
4437 /* Set a hard link. */
4438 if (total_data == 0) {
4439 return NT_STATUS_INVALID_PARAMETER;
4442 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4443 if (!NT_STATUS_IS_OK(status)) {
4447 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4448 if (!NT_STATUS_IS_OK(status)) {
4452 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4455 return hardlink_internals(conn, oldname, fname);
4458 /****************************************************************************
4459 Deal with SMB_FILE_RENAME_INFORMATION.
4460 ****************************************************************************/
4462 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4471 /* uint32 root_fid; */ /* Not used */
4475 BOOL dest_has_wcard = False;
4476 NTSTATUS status = NT_STATUS_OK;
4479 if (total_data < 13) {
4480 return NT_STATUS_INVALID_PARAMETER;
4483 overwrite = (CVAL(pdata,0) ? True : False);
4484 /* root_fid = IVAL(pdata,4); */
4485 len = IVAL(pdata,8);
4487 if (len > (total_data - 12) || (len == 0)) {
4488 return NT_STATUS_INVALID_PARAMETER;
4491 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4492 if (!NT_STATUS_IS_OK(status)) {
4496 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4497 if (!NT_STATUS_IS_OK(status)) {
4501 /* Check the new name has no '/' characters. */
4502 if (strchr_m(newname, '/')) {
4503 return NT_STATUS_NOT_SUPPORTED;
4506 /* Create the base directory. */
4507 pstrcpy(base_name, fname);
4508 p = strrchr_m(base_name, '/');
4512 pstrcpy(base_name, "./");
4514 /* Append the new name. */
4515 pstrcat(base_name, newname);
4518 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4519 fsp->fnum, fsp->fsp_name, base_name ));
4520 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4522 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4524 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4530 /****************************************************************************
4531 Deal with SMB_SET_POSIX_ACL.
4532 ****************************************************************************/
4534 #if defined(HAVE_POSIX_ACLS)
4535 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4540 SMB_STRUCT_STAT *psbuf)
4542 uint16 posix_acl_version;
4543 uint16 num_file_acls;
4544 uint16 num_def_acls;
4545 BOOL valid_file_acls = True;
4546 BOOL valid_def_acls = True;
4548 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4549 return NT_STATUS_INVALID_PARAMETER;
4551 posix_acl_version = SVAL(pdata,0);
4552 num_file_acls = SVAL(pdata,2);
4553 num_def_acls = SVAL(pdata,4);
4555 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4556 valid_file_acls = False;
4560 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4561 valid_def_acls = False;
4565 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4566 return NT_STATUS_INVALID_PARAMETER;
4569 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4570 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4571 return NT_STATUS_INVALID_PARAMETER;
4574 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4575 fname ? fname : fsp->fsp_name,
4576 (unsigned int)num_file_acls,
4577 (unsigned int)num_def_acls));
4579 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4580 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4581 return map_nt_error_from_unix(errno);
4584 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4585 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4586 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4587 return map_nt_error_from_unix(errno);
4589 return NT_STATUS_OK;
4593 /****************************************************************************
4594 Deal with SMB_SET_POSIX_LOCK.
4595 ****************************************************************************/
4597 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4605 SMB_BIG_UINT offset;
4607 BOOL blocking_lock = False;
4608 enum brl_type lock_type;
4609 NTSTATUS status = NT_STATUS_OK;
4611 if (fsp == NULL || fsp->fh->fd == -1) {
4612 return NT_STATUS_INVALID_HANDLE;
4615 if (total_data != POSIX_LOCK_DATA_SIZE) {
4616 return NT_STATUS_INVALID_PARAMETER;
4619 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4620 case POSIX_LOCK_TYPE_READ:
4621 lock_type = READ_LOCK;
4623 case POSIX_LOCK_TYPE_WRITE:
4624 /* Return the right POSIX-mappable error code for files opened read-only. */
4625 if (!fsp->can_write) {
4626 return NT_STATUS_INVALID_HANDLE;
4628 lock_type = WRITE_LOCK;
4630 case POSIX_LOCK_TYPE_UNLOCK:
4631 lock_type = UNLOCK_LOCK;
4634 return NT_STATUS_INVALID_PARAMETER;
4637 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4638 blocking_lock = False;
4639 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4640 blocking_lock = True;
4642 return NT_STATUS_INVALID_PARAMETER;
4645 if (!lp_blocking_locks(SNUM(conn))) {
4646 blocking_lock = False;
4649 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4650 #if defined(HAVE_LONGLONG)
4651 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4652 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4653 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4654 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4655 #else /* HAVE_LONGLONG */
4656 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4657 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4658 #endif /* HAVE_LONGLONG */
4660 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4661 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4663 (unsigned int)lock_type,
4664 (unsigned int)lock_pid,
4668 if (lock_type == UNLOCK_LOCK) {
4669 status = do_unlock(fsp,
4675 uint32 block_smbpid;
4677 struct byte_range_lock *br_lck = do_lock(fsp,
4687 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4689 * A blocking lock was requested. Package up
4690 * this smb into a queued request and push it
4691 * onto the blocking lock queue.
4693 if(push_blocking_lock_request(br_lck,
4696 -1, /* infinite timeout. */
4704 TALLOC_FREE(br_lck);
4708 TALLOC_FREE(br_lck);
4714 /****************************************************************************
4715 Deal with SMB_INFO_STANDARD.
4716 ****************************************************************************/
4718 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4723 const SMB_STRUCT_STAT *psbuf)
4725 struct timespec ts[2];
4727 if (total_data < 12) {
4728 return NT_STATUS_INVALID_PARAMETER;
4732 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4734 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4736 DEBUG(10,("smb_set_info_standard: file %s\n",
4737 fname ? fname : fsp->fsp_name ));
4739 return smb_set_file_time(conn,
4746 /****************************************************************************
4747 Deal with SMB_SET_FILE_BASIC_INFO.
4748 ****************************************************************************/
4750 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4755 SMB_STRUCT_STAT *psbuf)
4757 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4758 struct timespec write_time;
4759 struct timespec changed_time;
4761 struct timespec ts[2];
4762 NTSTATUS status = NT_STATUS_OK;
4764 if (total_data < 36) {
4765 return NT_STATUS_INVALID_PARAMETER;
4768 /* Set the attributes */
4769 dosmode = IVAL(pdata,32);
4770 status = smb_set_file_dosmode(conn,
4774 if (!NT_STATUS_IS_OK(status)) {
4778 /* Ignore create time at offset pdata. */
4781 ts[0] = interpret_long_date(pdata+8);
4783 write_time = interpret_long_date(pdata+16);
4784 changed_time = interpret_long_date(pdata+24);
4787 ts[1] = timespec_min(&write_time, &changed_time);
4789 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4793 /* Prefer a defined time to an undefined one. */
4794 if (null_timespec(ts[1])) {
4795 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4798 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4799 fname ? fname : fsp->fsp_name ));
4801 return smb_set_file_time(conn,
4808 /****************************************************************************
4809 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4810 ****************************************************************************/
4812 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4817 SMB_STRUCT_STAT *psbuf)
4819 SMB_BIG_UINT allocation_size = 0;
4820 NTSTATUS status = NT_STATUS_OK;
4821 files_struct *new_fsp = NULL;
4823 if (!VALID_STAT(*psbuf)) {
4824 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4827 if (total_data < 8) {
4828 return NT_STATUS_INVALID_PARAMETER;
4831 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4832 #ifdef LARGE_SMB_OFF_T
4833 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4834 #else /* LARGE_SMB_OFF_T */
4835 if (IVAL(pdata,4) != 0) {
4836 /* more than 32 bits? */
4837 return NT_STATUS_INVALID_PARAMETER;
4839 #endif /* LARGE_SMB_OFF_T */
4841 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4842 fname, (double)allocation_size ));
4844 if (allocation_size) {
4845 allocation_size = smb_roundup(conn, allocation_size);
4848 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4849 fname, (double)allocation_size ));
4851 if (fsp && fsp->fh->fd != -1) {
4852 /* Open file handle. */
4853 /* Only change if needed. */
4854 if (allocation_size != get_file_size(*psbuf)) {
4855 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4856 return map_nt_error_from_unix(errno);
4859 /* But always update the time. */
4860 if (null_timespec(fsp->pending_modtime)) {
4862 * This is equivalent to a write. Ensure it's seen immediately
4863 * if there are no pending writes.
4865 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
4867 return NT_STATUS_OK;
4870 /* Pathname or stat or directory file. */
4872 status = open_file_ntcreate(conn, fname, psbuf,
4874 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4877 FILE_ATTRIBUTE_NORMAL,
4878 FORCE_OPLOCK_BREAK_TO_NONE,
4881 if (!NT_STATUS_IS_OK(status)) {
4882 /* NB. We check for open_was_deferred in the caller. */
4886 /* Only change if needed. */
4887 if (allocation_size != get_file_size(*psbuf)) {
4888 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4889 status = map_nt_error_from_unix(errno);
4890 close_file(new_fsp,NORMAL_CLOSE);
4895 /* Changing the allocation size should set the last mod time. */
4896 /* Don't need to call set_filetime as this will be flushed on
4899 fsp_set_pending_modtime(new_fsp, timespec_current());
4901 close_file(new_fsp,NORMAL_CLOSE);
4902 return NT_STATUS_OK;
4905 /****************************************************************************
4906 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4907 ****************************************************************************/
4909 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4914 SMB_STRUCT_STAT *psbuf)
4918 if (total_data < 8) {
4919 return NT_STATUS_INVALID_PARAMETER;
4922 size = IVAL(pdata,0);
4923 #ifdef LARGE_SMB_OFF_T
4924 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4925 #else /* LARGE_SMB_OFF_T */
4926 if (IVAL(pdata,4) != 0) {
4927 /* more than 32 bits? */
4928 return NT_STATUS_INVALID_PARAMETER;
4930 #endif /* LARGE_SMB_OFF_T */
4931 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4932 "file %s to %.0f\n", fname, (double)size ));
4934 return smb_set_file_size(conn,
4941 /****************************************************************************
4942 Allow a UNIX info mknod.
4943 ****************************************************************************/
4945 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4949 SMB_STRUCT_STAT *psbuf)
4951 uint32 file_type = IVAL(pdata,56);
4952 #if defined(HAVE_MAKEDEV)
4953 uint32 dev_major = IVAL(pdata,60);
4954 uint32 dev_minor = IVAL(pdata,68);
4956 SMB_DEV_T dev = (SMB_DEV_T)0;
4957 uint32 raw_unixmode = IVAL(pdata,84);
4961 if (total_data < 100) {
4962 return NT_STATUS_INVALID_PARAMETER;
4965 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4966 if (!NT_STATUS_IS_OK(status)) {
4970 #if defined(HAVE_MAKEDEV)
4971 dev = makedev(dev_major, dev_minor);
4974 switch (file_type) {
4975 #if defined(S_IFIFO)
4976 case UNIX_TYPE_FIFO:
4977 unixmode |= S_IFIFO;
4980 #if defined(S_IFSOCK)
4981 case UNIX_TYPE_SOCKET:
4982 unixmode |= S_IFSOCK;
4985 #if defined(S_IFCHR)
4986 case UNIX_TYPE_CHARDEV:
4987 unixmode |= S_IFCHR;
4990 #if defined(S_IFBLK)
4991 case UNIX_TYPE_BLKDEV:
4992 unixmode |= S_IFBLK;
4996 return NT_STATUS_INVALID_PARAMETER;
4999 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5000 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5002 /* Ok - do the mknod. */
5003 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5004 return map_nt_error_from_unix(errno);
5007 /* If any of the other "set" calls fail we
5008 * don't want to end up with a half-constructed mknod.
5011 if (lp_inherit_perms(SNUM(conn))) {
5013 conn, parent_dirname(fname),
5017 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5018 status = map_nt_error_from_unix(errno);
5019 SMB_VFS_UNLINK(conn,fname);
5022 return NT_STATUS_OK;
5025 /****************************************************************************
5026 Deal with SMB_SET_FILE_UNIX_BASIC.
5027 ****************************************************************************/
5029 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5034 SMB_STRUCT_STAT *psbuf)
5036 struct timespec ts[2];
5037 uint32 raw_unixmode;
5040 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5041 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5042 NTSTATUS status = NT_STATUS_OK;
5043 BOOL delete_on_fail = False;
5044 enum perm_type ptype;
5046 if (total_data < 100) {
5047 return NT_STATUS_INVALID_PARAMETER;
5050 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5051 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5052 size=IVAL(pdata,0); /* first 8 Bytes are size */
5053 #ifdef LARGE_SMB_OFF_T
5054 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5055 #else /* LARGE_SMB_OFF_T */
5056 if (IVAL(pdata,4) != 0) {
5057 /* more than 32 bits? */
5058 return NT_STATUS_INVALID_PARAMETER;
5060 #endif /* LARGE_SMB_OFF_T */
5063 ts[0] = interpret_long_date(pdata+24); /* access_time */
5064 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5065 set_owner = (uid_t)IVAL(pdata,40);
5066 set_grp = (gid_t)IVAL(pdata,48);
5067 raw_unixmode = IVAL(pdata,84);
5069 if (VALID_STAT(*psbuf)) {
5070 if (S_ISDIR(psbuf->st_mode)) {
5071 ptype = PERM_EXISTING_DIR;
5073 ptype = PERM_EXISTING_FILE;
5076 ptype = PERM_NEW_FILE;
5079 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5080 if (!NT_STATUS_IS_OK(status)) {
5084 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5085 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5086 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5088 if (!VALID_STAT(*psbuf)) {
5090 * The only valid use of this is to create character and block
5091 * devices, and named pipes. This is deprecated (IMHO) and
5092 * a new info level should be used for mknod. JRA.
5095 status = smb_unix_mknod(conn,
5100 if (!NT_STATUS_IS_OK(status)) {
5104 /* Ensure we don't try and change anything else. */
5105 raw_unixmode = SMB_MODE_NO_CHANGE;
5106 size = get_file_size(*psbuf);
5107 ts[0] = get_atimespec(psbuf);
5108 ts[1] = get_mtimespec(psbuf);
5110 * We continue here as we might want to change the
5113 delete_on_fail = True;
5117 /* Horrible backwards compatibility hack as an old server bug
5118 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5122 size = get_file_size(*psbuf);
5127 * Deal with the UNIX specific mode set.
5130 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5131 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5132 (unsigned int)unixmode, fname ));
5133 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5134 return map_nt_error_from_unix(errno);
5139 * Deal with the UNIX specific uid set.
5142 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5143 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5144 (unsigned int)set_owner, fname ));
5145 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5146 status = map_nt_error_from_unix(errno);
5147 if (delete_on_fail) {
5148 SMB_VFS_UNLINK(conn,fname);
5155 * Deal with the UNIX specific gid set.
5158 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5159 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5160 (unsigned int)set_owner, fname ));
5161 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5162 status = map_nt_error_from_unix(errno);
5163 if (delete_on_fail) {
5164 SMB_VFS_UNLINK(conn,fname);
5170 /* Deal with any size changes. */
5172 status = smb_set_file_size(conn,
5177 if (!NT_STATUS_IS_OK(status)) {
5181 /* Deal with any time changes. */
5183 return smb_set_file_time(conn,
5190 /****************************************************************************
5191 Deal with SMB_SET_FILE_UNIX_INFO2.
5192 ****************************************************************************/
5194 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5199 SMB_STRUCT_STAT *psbuf)
5205 if (total_data < 116) {
5206 return NT_STATUS_INVALID_PARAMETER;
5209 /* Start by setting all the fields that are common between UNIX_BASIC
5212 status = smb_set_file_unix_basic(conn, pdata, total_data,
5214 if (!NT_STATUS_IS_OK(status)) {
5218 smb_fflags = IVAL(pdata, 108);
5219 smb_fmask = IVAL(pdata, 112);
5221 /* NB: We should only attempt to alter the file flags if the client
5222 * sends a non-zero mask.
5224 if (smb_fmask != 0) {
5225 int stat_fflags = 0;
5227 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5229 /* Client asked to alter a flag we don't understand. */
5230 return NT_STATUS_INVALID_PARAMETER;
5233 if (fsp && fsp->fh->fd != -1) {
5234 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5235 return NT_STATUS_NOT_SUPPORTED;
5237 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5238 return map_nt_error_from_unix(errno);
5243 /* XXX: need to add support for changing the create_time here. You
5244 * can do this for paths on Darwin with setattrlist(2). The right way
5245 * to hook this up is probably by extending the VFS utimes interface.
5248 return NT_STATUS_OK;
5251 /****************************************************************************
5252 Create a directory with POSIX semantics.
5253 ****************************************************************************/
5255 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5259 SMB_STRUCT_STAT *psbuf,
5260 int *pdata_return_size)
5262 NTSTATUS status = NT_STATUS_OK;
5263 uint32 raw_unixmode = 0;
5264 uint32 mod_unixmode = 0;
5265 mode_t unixmode = (mode_t)0;
5266 files_struct *fsp = NULL;
5267 uint16 info_level_return = 0;
5269 char *pdata = *ppdata;
5271 if (total_data < 18) {
5272 return NT_STATUS_INVALID_PARAMETER;
5275 raw_unixmode = IVAL(pdata,8);
5276 /* Next 4 bytes are not yet defined. */
5278 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5279 if (!NT_STATUS_IS_OK(status)) {
5283 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5285 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5286 fname, (unsigned int)unixmode ));
5288 status = open_directory(conn,
5291 FILE_READ_ATTRIBUTES, /* Just a stat open */
5292 FILE_SHARE_NONE, /* Ignored for stat opens */
5299 if (NT_STATUS_IS_OK(status)) {
5300 close_file(fsp, NORMAL_CLOSE);
5303 info_level_return = SVAL(pdata,16);
5305 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5306 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5307 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5308 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5310 *pdata_return_size = 12;
5313 /* Realloc the data size */
5314 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5315 if (*ppdata == NULL) {
5316 *pdata_return_size = 0;
5317 return NT_STATUS_NO_MEMORY;
5321 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5322 SSVAL(pdata,2,0); /* No fnum. */
5323 SIVAL(pdata,4,info); /* Was directory created. */
5325 switch (info_level_return) {
5326 case SMB_QUERY_FILE_UNIX_BASIC:
5327 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5328 SSVAL(pdata,10,0); /* Padding. */
5329 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5331 case SMB_QUERY_FILE_UNIX_INFO2:
5332 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5333 SSVAL(pdata,10,0); /* Padding. */
5334 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5337 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5338 SSVAL(pdata,10,0); /* Padding. */
5345 /****************************************************************************
5346 Open/Create a file with POSIX semantics.
5347 ****************************************************************************/
5349 static NTSTATUS smb_posix_open(connection_struct *conn,
5353 SMB_STRUCT_STAT *psbuf,
5354 int *pdata_return_size)
5356 BOOL extended_oplock_granted = False;
5357 char *pdata = *ppdata;
5359 uint32 wire_open_mode = 0;
5360 uint32 raw_unixmode = 0;
5361 uint32 mod_unixmode = 0;
5362 uint32 create_disp = 0;
5363 uint32 access_mask = 0;
5364 uint32 create_options = 0;
5365 NTSTATUS status = NT_STATUS_OK;
5366 mode_t unixmode = (mode_t)0;
5367 files_struct *fsp = NULL;
5368 int oplock_request = 0;
5370 uint16 info_level_return = 0;
5372 if (total_data < 18) {
5373 return NT_STATUS_INVALID_PARAMETER;
5376 flags = IVAL(pdata,0);
5377 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5378 if (oplock_request) {
5379 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5382 wire_open_mode = IVAL(pdata,4);
5384 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5385 return smb_posix_mkdir(conn,
5393 switch (wire_open_mode & SMB_ACCMODE) {
5395 access_mask = FILE_READ_DATA;
5398 access_mask = FILE_WRITE_DATA;
5401 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5404 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5405 (unsigned int)wire_open_mode ));
5406 return NT_STATUS_INVALID_PARAMETER;
5409 wire_open_mode &= ~SMB_ACCMODE;
5411 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5412 create_disp = FILE_CREATE;
5413 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5414 create_disp = FILE_OVERWRITE_IF;
5415 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5416 create_disp = FILE_OPEN_IF;
5418 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5419 (unsigned int)wire_open_mode ));
5420 return NT_STATUS_INVALID_PARAMETER;
5423 raw_unixmode = IVAL(pdata,8);
5424 /* Next 4 bytes are not yet defined. */
5426 status = unix_perms_from_wire(conn,
5429 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5432 if (!NT_STATUS_IS_OK(status)) {
5436 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5438 if (wire_open_mode & SMB_O_SYNC) {
5439 create_options |= FILE_WRITE_THROUGH;
5441 if (wire_open_mode & SMB_O_APPEND) {
5442 access_mask |= FILE_APPEND_DATA;
5444 if (wire_open_mode & SMB_O_DIRECT) {
5445 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5448 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5450 (unsigned int)wire_open_mode,
5451 (unsigned int)unixmode ));
5453 status = open_file_ntcreate(conn,
5457 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5459 0, /* no create options yet. */
5465 if (!NT_STATUS_IS_OK(status)) {
5469 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5470 extended_oplock_granted = True;
5473 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5474 extended_oplock_granted = True;
5477 info_level_return = SVAL(pdata,16);
5479 /* Allocate the correct return size. */
5481 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5482 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5483 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5484 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5486 *pdata_return_size = 12;
5489 /* Realloc the data size */
5490 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5491 if (*ppdata == NULL) {
5492 close_file(fsp,ERROR_CLOSE);
5493 *pdata_return_size = 0;
5494 return NT_STATUS_NO_MEMORY;
5498 if (extended_oplock_granted) {
5499 if (flags & REQUEST_BATCH_OPLOCK) {
5500 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5502 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5504 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5505 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5507 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5510 SSVAL(pdata,2,fsp->fnum);
5511 SIVAL(pdata,4,info); /* Was file created etc. */
5513 switch (info_level_return) {
5514 case SMB_QUERY_FILE_UNIX_BASIC:
5515 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5516 SSVAL(pdata,10,0); /* padding. */
5517 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5519 case SMB_QUERY_FILE_UNIX_INFO2:
5520 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5521 SSVAL(pdata,10,0); /* padding. */
5522 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5525 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5526 SSVAL(pdata,10,0); /* padding. */
5529 return NT_STATUS_OK;
5532 /****************************************************************************
5533 Delete a file with POSIX semantics.
5534 ****************************************************************************/
5536 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5540 SMB_STRUCT_STAT *psbuf)
5542 NTSTATUS status = NT_STATUS_OK;
5543 files_struct *fsp = NULL;
5548 struct share_mode_lock *lck = NULL;
5550 if (total_data < 2) {
5551 return NT_STATUS_INVALID_PARAMETER;
5554 flags = SVAL(pdata,0);
5556 if (!VALID_STAT(*psbuf)) {
5557 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5560 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5561 !VALID_STAT_OF_DIR(*psbuf)) {
5562 return NT_STATUS_NOT_A_DIRECTORY;
5565 DEBUG(10,("smb_posix_unlink: %s %s\n",
5566 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5569 if (VALID_STAT_OF_DIR(*psbuf)) {
5570 status = open_directory(conn,
5574 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5577 FILE_FLAG_POSIX_SEMANTICS|0777,
5582 status = open_file_ntcreate(conn,
5586 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5589 FILE_FLAG_POSIX_SEMANTICS|0777,
5590 0, /* No oplock, but break existing ones. */
5595 if (!NT_STATUS_IS_OK(status)) {
5600 * Don't lie to client. If we can't really delete due to
5601 * non-POSIX opens return SHARING_VIOLATION.
5604 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
5606 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5607 "lock for file %s\n", fsp->fsp_name));
5608 close_file(fsp, NORMAL_CLOSE);
5609 return NT_STATUS_INVALID_PARAMETER;
5613 * See if others still have the file open. If this is the case, then
5614 * don't delete. If all opens are POSIX delete we can set the delete
5615 * on close disposition.
5617 for (i=0; i<lck->num_share_modes; i++) {
5618 struct share_mode_entry *e = &lck->share_modes[i];
5619 if (is_valid_share_mode_entry(e)) {
5620 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5623 /* Fail with sharing violation. */
5624 close_file(fsp, NORMAL_CLOSE);
5626 return NT_STATUS_SHARING_VIOLATION;
5631 * Set the delete on close.
5633 status = smb_set_file_disposition_info(conn,
5640 if (!NT_STATUS_IS_OK(status)) {
5641 close_file(fsp, NORMAL_CLOSE);
5646 return close_file(fsp, NORMAL_CLOSE);
5649 /****************************************************************************
5650 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5651 ****************************************************************************/
5653 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5654 unsigned int tran_call,
5655 char **pparams, int total_params, char **ppdata, int total_data,
5656 unsigned int max_data_bytes)
5658 char *params = *pparams;
5659 char *pdata = *ppdata;
5661 SMB_STRUCT_STAT sbuf;
5663 files_struct *fsp = NULL;
5664 NTSTATUS status = NT_STATUS_OK;
5665 int data_return_size = 0;
5668 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5673 if (tran_call == TRANSACT2_SETFILEINFO) {
5674 if (total_params < 4) {
5675 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5678 fsp = file_fsp(params,0);
5679 info_level = SVAL(params,2);
5681 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5683 * This is actually a SETFILEINFO on a directory
5684 * handle (returned from an NT SMB). NT5.0 seems
5685 * to do this call. JRA.
5687 pstrcpy(fname, fsp->fsp_name);
5688 if (INFO_LEVEL_IS_UNIX(info_level)) {
5689 /* Always do lstat for UNIX calls. */
5690 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5691 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5692 return UNIXERROR(ERRDOS,ERRbadpath);
5695 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5696 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5697 return UNIXERROR(ERRDOS,ERRbadpath);
5700 } else if (fsp && fsp->print_file) {
5702 * Doing a DELETE_ON_CLOSE should cancel a print job.
5704 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5705 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5707 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5710 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5713 return (UNIXERROR(ERRDOS,ERRbadpath));
5716 * Original code - this is an open file.
5718 CHECK_FSP(fsp,conn);
5720 pstrcpy(fname, fsp->fsp_name);
5722 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5723 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5724 return(UNIXERROR(ERRDOS,ERRbadfid));
5729 if (total_params < 7) {
5730 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5733 info_level = SVAL(params,0);
5734 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 return ERROR_NT(status);
5739 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5740 if (!NT_STATUS_IS_OK(status)) {
5741 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5742 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5744 return ERROR_NT(status);
5747 status = unix_convert(conn, fname, False, NULL, &sbuf);
5748 if (!NT_STATUS_IS_OK(status)) {
5749 return ERROR_NT(status);
5752 status = check_name(conn, fname);
5753 if (!NT_STATUS_IS_OK(status)) {
5754 return ERROR_NT(status);
5757 if (INFO_LEVEL_IS_UNIX(info_level)) {
5759 * For CIFS UNIX extensions the target name may not exist.
5762 /* Always do lstat for UNIX calls. */
5763 SMB_VFS_LSTAT(conn,fname,&sbuf);
5765 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5766 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5767 return UNIXERROR(ERRDOS,ERRbadpath);
5771 if (!CAN_WRITE(conn)) {
5772 return ERROR_DOS(ERRSRV,ERRaccess);
5775 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5776 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5779 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5780 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5782 /* Realloc the parameter size */
5783 *pparams = (char *)SMB_REALLOC(*pparams,2);
5784 if (*pparams == NULL) {
5785 return ERROR_NT(NT_STATUS_NO_MEMORY);
5791 if (fsp && !null_timespec(fsp->pending_modtime)) {
5792 /* the pending modtime overrides the current modtime */
5793 set_mtimespec(&sbuf, fsp->pending_modtime);
5796 switch (info_level) {
5798 case SMB_INFO_STANDARD:
5800 status = smb_set_info_standard(conn,
5809 case SMB_INFO_SET_EA:
5811 status = smb_info_set_ea(conn,
5819 case SMB_SET_FILE_BASIC_INFO:
5820 case SMB_FILE_BASIC_INFORMATION:
5822 status = smb_set_file_basic_info(conn,
5831 case SMB_FILE_ALLOCATION_INFORMATION:
5832 case SMB_SET_FILE_ALLOCATION_INFO:
5834 status = smb_set_file_allocation_info(conn,
5843 case SMB_FILE_END_OF_FILE_INFORMATION:
5844 case SMB_SET_FILE_END_OF_FILE_INFO:
5846 status = smb_set_file_end_of_file_info(conn,
5855 case SMB_FILE_DISPOSITION_INFORMATION:
5856 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5859 /* JRA - We used to just ignore this on a path ?
5860 * Shouldn't this be invalid level on a pathname
5863 if (tran_call != TRANSACT2_SETFILEINFO) {
5864 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5867 status = smb_set_file_disposition_info(conn,
5876 case SMB_FILE_POSITION_INFORMATION:
5878 status = smb_file_position_information(conn,
5885 /* From tridge Samba4 :
5886 * MODE_INFORMATION in setfileinfo (I have no
5887 * idea what "mode information" on a file is - it takes a value of 0,
5888 * 2, 4 or 6. What could it be?).
5891 case SMB_FILE_MODE_INFORMATION:
5893 status = smb_file_mode_information(conn,
5900 * CIFS UNIX extensions.
5903 case SMB_SET_FILE_UNIX_BASIC:
5905 status = smb_set_file_unix_basic(conn,
5914 case SMB_SET_FILE_UNIX_INFO2:
5916 status = smb_set_file_unix_info2(conn,
5925 case SMB_SET_FILE_UNIX_LINK:
5927 if (tran_call != TRANSACT2_SETPATHINFO) {
5928 /* We must have a pathname for this. */
5929 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5931 status = smb_set_file_unix_link(conn,
5939 case SMB_SET_FILE_UNIX_HLINK:
5941 if (tran_call != TRANSACT2_SETPATHINFO) {
5942 /* We must have a pathname for this. */
5943 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5945 status = smb_set_file_unix_hlink(conn,
5954 case SMB_FILE_RENAME_INFORMATION:
5956 status = smb_file_rename_information(conn,
5966 #if defined(HAVE_POSIX_ACLS)
5967 case SMB_SET_POSIX_ACL:
5969 status = smb_set_posix_acl(conn,
5979 case SMB_SET_POSIX_LOCK:
5981 if (tran_call != TRANSACT2_SETFILEINFO) {
5982 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5984 status = smb_set_posix_lock(conn,
5993 case SMB_POSIX_PATH_OPEN:
5995 if (tran_call != TRANSACT2_SETPATHINFO) {
5996 /* We must have a pathname for this. */
5997 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6000 status = smb_posix_open(conn,
6009 case SMB_POSIX_PATH_UNLINK:
6011 if (tran_call != TRANSACT2_SETPATHINFO) {
6012 /* We must have a pathname for this. */
6013 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6016 status = smb_posix_unlink(conn,
6025 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6029 if (!NT_STATUS_IS_OK(status)) {
6030 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6031 /* We have re-scheduled this call. */
6034 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6035 /* We have re-scheduled this call. */
6038 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6039 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6041 if (info_level == SMB_POSIX_PATH_OPEN) {
6042 return ERROR_OPEN(status);
6044 return ERROR_NT(status);
6048 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6053 /****************************************************************************
6054 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6055 ****************************************************************************/
6057 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6058 char **pparams, int total_params, char **ppdata, int total_data,
6059 unsigned int max_data_bytes)
6061 char *params = *pparams;
6062 char *pdata = *ppdata;
6064 SMB_STRUCT_STAT sbuf;
6065 NTSTATUS status = NT_STATUS_OK;
6066 struct ea_list *ea_list = NULL;
6068 if (!CAN_WRITE(conn))
6069 return ERROR_DOS(ERRSRV,ERRaccess);
6071 if (total_params < 5) {
6072 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6075 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6076 if (!NT_STATUS_IS_OK(status)) {
6077 return ERROR_NT(status);
6080 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6082 status = unix_convert(conn, directory, False, NULL, &sbuf);
6083 if (!NT_STATUS_IS_OK(status)) {
6084 return ERROR_NT(status);
6087 status = check_name(conn, directory);
6088 if (!NT_STATUS_IS_OK(status)) {
6089 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6090 return ERROR_NT(status);
6093 /* Any data in this call is an EA list. */
6094 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6095 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6099 * OS/2 workplace shell seems to send SET_EA requests of "null"
6100 * length (4 bytes containing IVAL 4).
6101 * They seem to have no effect. Bug #3212. JRA.
6104 if (total_data != 4) {
6105 if (total_data < 10) {
6106 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6109 if (IVAL(pdata,0) > total_data) {
6110 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6111 IVAL(pdata,0), (unsigned int)total_data));
6112 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6115 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6118 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6120 } else if (IVAL(pdata,0) != 4) {
6121 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6124 status = create_directory(conn, directory);
6126 if (!NT_STATUS_IS_OK(status)) {
6127 return ERROR_NT(status);
6130 /* Try and set any given EA. */
6132 status = set_ea(conn, NULL, directory, ea_list);
6133 if (!NT_STATUS_IS_OK(status)) {
6134 return ERROR_NT(status);
6138 /* Realloc the parameter and data sizes */
6139 *pparams = (char *)SMB_REALLOC(*pparams,2);
6140 if(*pparams == NULL) {
6141 return ERROR_NT(NT_STATUS_NO_MEMORY);
6147 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6152 /****************************************************************************
6153 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6154 We don't actually do this - we just send a null response.
6155 ****************************************************************************/
6157 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6158 char **pparams, int total_params, char **ppdata, int total_data,
6159 unsigned int max_data_bytes)
6161 static uint16 fnf_handle = 257;
6162 char *params = *pparams;
6165 if (total_params < 6) {
6166 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6169 info_level = SVAL(params,4);
6170 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6172 switch (info_level) {
6177 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6180 /* Realloc the parameter and data sizes */
6181 *pparams = (char *)SMB_REALLOC(*pparams,6);
6182 if (*pparams == NULL) {
6183 return ERROR_NT(NT_STATUS_NO_MEMORY);
6187 SSVAL(params,0,fnf_handle);
6188 SSVAL(params,2,0); /* No changes */
6189 SSVAL(params,4,0); /* No EA errors */
6196 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6201 /****************************************************************************
6202 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6203 changes). Currently this does nothing.
6204 ****************************************************************************/
6206 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6207 char **pparams, int total_params, char **ppdata, int total_data,
6208 unsigned int max_data_bytes)
6210 char *params = *pparams;
6212 DEBUG(3,("call_trans2findnotifynext\n"));
6214 /* Realloc the parameter and data sizes */
6215 *pparams = (char *)SMB_REALLOC(*pparams,4);
6216 if (*pparams == NULL) {
6217 return ERROR_NT(NT_STATUS_NO_MEMORY);
6221 SSVAL(params,0,0); /* No changes */
6222 SSVAL(params,2,0); /* No EA errors */
6224 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6229 /****************************************************************************
6230 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6231 ****************************************************************************/
6233 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6234 char **pparams, int total_params, char **ppdata, int total_data,
6235 unsigned int max_data_bytes)
6237 char *params = *pparams;
6240 int max_referral_level;
6241 NTSTATUS status = NT_STATUS_OK;
6243 DEBUG(10,("call_trans2getdfsreferral\n"));
6245 if (total_params < 3) {
6246 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6249 max_referral_level = SVAL(params,0);
6251 if(!lp_host_msdfs())
6252 return ERROR_DOS(ERRDOS,ERRbadfunc);
6254 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6255 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6256 return ERROR_NT(status);
6258 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6259 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6264 #define LMCAT_SPL 0x53
6265 #define LMFUNC_GETJOBID 0x60
6267 /****************************************************************************
6268 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6269 ****************************************************************************/
6271 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6272 char **pparams, int total_params, char **ppdata, int total_data,
6273 unsigned int max_data_bytes)
6275 char *pdata = *ppdata;
6276 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6278 /* check for an invalid fid before proceeding */
6281 return(ERROR_DOS(ERRDOS,ERRbadfid));
6283 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6284 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6285 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6286 if (*ppdata == NULL) {
6287 return ERROR_NT(NT_STATUS_NO_MEMORY);
6291 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6292 CAN ACCEPT THIS IN UNICODE. JRA. */
6294 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6295 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6296 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6297 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6300 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6301 return ERROR_DOS(ERRSRV,ERRerror);
6305 /****************************************************************************
6306 Reply to a SMBfindclose (stop trans2 directory search).
6307 ****************************************************************************/
6309 int reply_findclose(connection_struct *conn,
6310 char *inbuf,char *outbuf,int length,int bufsize)
6313 int dptr_num=SVALS(inbuf,smb_vwv0);
6314 START_PROFILE(SMBfindclose);
6316 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6318 dptr_close(&dptr_num);
6320 outsize = set_message(outbuf,0,0,False);
6322 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6324 END_PROFILE(SMBfindclose);
6328 /****************************************************************************
6329 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6330 ****************************************************************************/
6332 int reply_findnclose(connection_struct *conn,
6333 char *inbuf,char *outbuf,int length,int bufsize)
6337 START_PROFILE(SMBfindnclose);
6339 dptr_num = SVAL(inbuf,smb_vwv0);
6341 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6343 /* We never give out valid handles for a
6344 findnotifyfirst - so any dptr_num is ok here.
6347 outsize = set_message(outbuf,0,0,False);
6349 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6351 END_PROFILE(SMBfindnclose);
6355 int handle_trans2(connection_struct *conn,
6356 struct trans_state *state,
6357 char *inbuf, char *outbuf, int size, int bufsize)
6361 if (Protocol >= PROTOCOL_NT1) {
6362 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6365 /* Now we must call the relevant TRANS2 function */
6366 switch(state->call) {
6367 case TRANSACT2_OPEN:
6369 START_PROFILE(Trans2_open);
6370 outsize = call_trans2open(
6371 conn, inbuf, outbuf, bufsize,
6372 &state->param, state->total_param,
6373 &state->data, state->total_data,
6374 state->max_data_return);
6375 END_PROFILE(Trans2_open);
6379 case TRANSACT2_FINDFIRST:
6381 START_PROFILE(Trans2_findfirst);
6382 outsize = call_trans2findfirst(
6383 conn, inbuf, outbuf, bufsize,
6384 &state->param, state->total_param,
6385 &state->data, state->total_data,
6386 state->max_data_return);
6387 END_PROFILE(Trans2_findfirst);
6391 case TRANSACT2_FINDNEXT:
6393 START_PROFILE(Trans2_findnext);
6394 outsize = call_trans2findnext(
6395 conn, inbuf, outbuf, size, bufsize,
6396 &state->param, state->total_param,
6397 &state->data, state->total_data,
6398 state->max_data_return);
6399 END_PROFILE(Trans2_findnext);
6403 case TRANSACT2_QFSINFO:
6405 START_PROFILE(Trans2_qfsinfo);
6406 outsize = call_trans2qfsinfo(
6407 conn, inbuf, outbuf, size, bufsize,
6408 &state->param, state->total_param,
6409 &state->data, state->total_data,
6410 state->max_data_return);
6411 END_PROFILE(Trans2_qfsinfo);
6415 case TRANSACT2_SETFSINFO:
6417 START_PROFILE(Trans2_setfsinfo);
6418 outsize = call_trans2setfsinfo(
6419 conn, inbuf, outbuf, size, bufsize,
6420 &state->param, state->total_param,
6421 &state->data, state->total_data,
6422 state->max_data_return);
6423 END_PROFILE(Trans2_setfsinfo);
6427 case TRANSACT2_QPATHINFO:
6428 case TRANSACT2_QFILEINFO:
6430 START_PROFILE(Trans2_qpathinfo);
6431 outsize = call_trans2qfilepathinfo(
6432 conn, inbuf, outbuf, size, bufsize, state->call,
6433 &state->param, state->total_param,
6434 &state->data, state->total_data,
6435 state->max_data_return);
6436 END_PROFILE(Trans2_qpathinfo);
6440 case TRANSACT2_SETPATHINFO:
6441 case TRANSACT2_SETFILEINFO:
6443 START_PROFILE(Trans2_setpathinfo);
6444 outsize = call_trans2setfilepathinfo(
6445 conn, inbuf, outbuf, size, bufsize, state->call,
6446 &state->param, state->total_param,
6447 &state->data, state->total_data,
6448 state->max_data_return);
6449 END_PROFILE(Trans2_setpathinfo);
6453 case TRANSACT2_FINDNOTIFYFIRST:
6455 START_PROFILE(Trans2_findnotifyfirst);
6456 outsize = call_trans2findnotifyfirst(
6457 conn, inbuf, outbuf, size, bufsize,
6458 &state->param, state->total_param,
6459 &state->data, state->total_data,
6460 state->max_data_return);
6461 END_PROFILE(Trans2_findnotifyfirst);
6465 case TRANSACT2_FINDNOTIFYNEXT:
6467 START_PROFILE(Trans2_findnotifynext);
6468 outsize = call_trans2findnotifynext(
6469 conn, inbuf, outbuf, size, bufsize,
6470 &state->param, state->total_param,
6471 &state->data, state->total_data,
6472 state->max_data_return);
6473 END_PROFILE(Trans2_findnotifynext);
6477 case TRANSACT2_MKDIR:
6479 START_PROFILE(Trans2_mkdir);
6480 outsize = call_trans2mkdir(
6481 conn, inbuf, outbuf, size, bufsize,
6482 &state->param, state->total_param,
6483 &state->data, state->total_data,
6484 state->max_data_return);
6485 END_PROFILE(Trans2_mkdir);
6489 case TRANSACT2_GET_DFS_REFERRAL:
6491 START_PROFILE(Trans2_get_dfs_referral);
6492 outsize = call_trans2getdfsreferral(
6493 conn, inbuf, outbuf, size, bufsize,
6494 &state->param, state->total_param,
6495 &state->data, state->total_data,
6496 state->max_data_return);
6497 END_PROFILE(Trans2_get_dfs_referral);
6501 case TRANSACT2_IOCTL:
6503 START_PROFILE(Trans2_ioctl);
6504 outsize = call_trans2ioctl(
6505 conn, inbuf, outbuf, size, bufsize,
6506 &state->param, state->total_param,
6507 &state->data, state->total_data,
6508 state->max_data_return);
6509 END_PROFILE(Trans2_ioctl);
6514 /* Error in request */
6515 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6516 outsize = ERROR_DOS(ERRSRV,ERRerror);
6522 /****************************************************************************
6523 Reply to a SMBtrans2.
6524 ****************************************************************************/
6526 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6527 int size, int bufsize)
6530 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6531 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6532 unsigned int psoff = SVAL(inbuf, smb_psoff);
6533 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6534 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6535 struct trans_state *state;
6538 START_PROFILE(SMBtrans2);
6540 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6541 if (!NT_STATUS_IS_OK(result)) {
6542 DEBUG(2, ("Got invalid trans2 request: %s\n",
6543 nt_errstr(result)));
6544 END_PROFILE(SMBtrans2);
6545 return ERROR_NT(result);
6548 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6549 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6550 END_PROFILE(SMBtrans2);
6551 return ERROR_DOS(ERRSRV,ERRaccess);
6554 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6555 DEBUG(0, ("talloc failed\n"));
6556 END_PROFILE(SMBtrans2);
6557 return ERROR_NT(NT_STATUS_NO_MEMORY);
6560 state->cmd = SMBtrans2;
6562 state->mid = SVAL(inbuf, smb_mid);
6563 state->vuid = SVAL(inbuf, smb_uid);
6564 state->setup_count = SVAL(inbuf, smb_suwcnt);
6565 state->setup = NULL;
6566 state->total_param = SVAL(inbuf, smb_tpscnt);
6567 state->param = NULL;
6568 state->total_data = SVAL(inbuf, smb_tdscnt);
6570 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6571 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6572 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6573 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6574 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6576 state->call = tran_call;
6578 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6579 is so as a sanity check */
6580 if (state->setup_count != 1) {
6582 * Need to have rc=0 for ioctl to get job id for OS/2.
6583 * Network printing will fail if function is not successful.
6584 * Similar function in reply.c will be used if protocol
6585 * is LANMAN1.0 instead of LM1.2X002.
6586 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6587 * outbuf doesn't have to be set(only job id is used).
6589 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6590 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6591 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6592 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6594 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6595 DEBUG(2,("Transaction is %d\n",tran_call));
6597 END_PROFILE(SMBtrans2);
6598 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6602 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6605 if (state->total_data) {
6606 /* Can't use talloc here, the core routines do realloc on the
6607 * params and data. */
6608 state->data = (char *)SMB_MALLOC(state->total_data);
6609 if (state->data == NULL) {
6610 DEBUG(0,("reply_trans2: data malloc fail for %u "
6611 "bytes !\n", (unsigned int)state->total_data));
6613 END_PROFILE(SMBtrans2);
6614 return(ERROR_DOS(ERRDOS,ERRnomem));
6616 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6618 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6619 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6622 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6625 if (state->total_param) {
6626 /* Can't use talloc here, the core routines do realloc on the
6627 * params and data. */
6628 state->param = (char *)SMB_MALLOC(state->total_param);
6629 if (state->param == NULL) {
6630 DEBUG(0,("reply_trans: param malloc fail for %u "
6631 "bytes !\n", (unsigned int)state->total_param));
6632 SAFE_FREE(state->data);
6634 END_PROFILE(SMBtrans2);
6635 return(ERROR_DOS(ERRDOS,ERRnomem));
6637 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6639 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6640 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6643 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6646 state->received_data = dscnt;
6647 state->received_param = pscnt;
6649 if ((state->received_param == state->total_param) &&
6650 (state->received_data == state->total_data)) {
6652 outsize = handle_trans2(conn, state, inbuf, outbuf,
6654 SAFE_FREE(state->data);
6655 SAFE_FREE(state->param);
6657 END_PROFILE(SMBtrans2);
6661 DLIST_ADD(conn->pending_trans, state);
6663 /* We need to send an interim response then receive the rest
6664 of the parameter/data bytes */
6665 outsize = set_message(outbuf,0,0,False);
6667 END_PROFILE(SMBtrans2);
6672 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6673 SAFE_FREE(state->data);
6674 SAFE_FREE(state->param);
6676 END_PROFILE(SMBtrans2);
6677 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6681 /****************************************************************************
6682 Reply to a SMBtranss2
6683 ****************************************************************************/
6685 int reply_transs2(connection_struct *conn,
6686 char *inbuf,char *outbuf,int size,int bufsize)
6689 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6690 struct trans_state *state;
6692 START_PROFILE(SMBtranss2);
6696 for (state = conn->pending_trans; state != NULL;
6697 state = state->next) {
6698 if (state->mid == SVAL(inbuf,smb_mid)) {
6703 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6704 END_PROFILE(SMBtranss2);
6705 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6708 /* Revise state->total_param and state->total_data in case they have
6709 changed downwards */
6711 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6712 state->total_param = SVAL(inbuf, smb_tpscnt);
6713 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6714 state->total_data = SVAL(inbuf, smb_tdscnt);
6716 pcnt = SVAL(inbuf, smb_spscnt);
6717 poff = SVAL(inbuf, smb_spsoff);
6718 pdisp = SVAL(inbuf, smb_spsdisp);
6720 dcnt = SVAL(inbuf, smb_sdscnt);
6721 doff = SVAL(inbuf, smb_sdsoff);
6722 ddisp = SVAL(inbuf, smb_sdsdisp);
6724 state->received_param += pcnt;
6725 state->received_data += dcnt;
6727 if ((state->received_data > state->total_data) ||
6728 (state->received_param > state->total_param))
6732 if (pdisp+pcnt > state->total_param)
6734 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6736 if (pdisp > state->total_param)
6738 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6739 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6741 if (state->param + pdisp < state->param)
6744 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6749 if (ddisp+dcnt > state->total_data)
6751 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6753 if (ddisp > state->total_data)
6755 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6756 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6758 if (state->data + ddisp < state->data)
6761 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6765 if ((state->received_param < state->total_param) ||
6766 (state->received_data < state->total_data)) {
6767 END_PROFILE(SMBtranss2);
6771 /* construct_reply_common has done us the favor to pre-fill the
6772 * command field with SMBtranss2 which is wrong :-)
6774 SCVAL(outbuf,smb_com,SMBtrans2);
6776 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6778 DLIST_REMOVE(conn->pending_trans, state);
6779 SAFE_FREE(state->data);
6780 SAFE_FREE(state->param);
6784 END_PROFILE(SMBtranss2);
6785 return(ERROR_DOS(ERRSRV,ERRnosupport));
6788 END_PROFILE(SMBtranss2);
6793 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6794 DLIST_REMOVE(conn->pending_trans, state);
6795 SAFE_FREE(state->data);
6796 SAFE_FREE(state->param);
6798 END_PROFILE(SMBtranss2);
6799 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);