2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct *conn,
41 const SMB_STRUCT_STAT *psbuf);
43 static char *store_file_unix_basic_info2(connection_struct *conn,
46 const SMB_STRUCT_STAT *psbuf);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
55 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type = get_remote_arch();
59 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60 val = SMB_ROUNDUP(val,rval);
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
68 ********************************************************************/
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
74 if(S_ISDIR(sbuf->st_mode)) {
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
81 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
84 if (fsp && fsp->initial_allocation_size)
85 ret = MAX(ret,fsp->initial_allocation_size);
87 return smb_roundup(conn, ret);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120 const char *fname, char *ea_name, struct ea_struct *pea)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size = 256;
129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 if (fsp && fsp->fh->fd != -1) {
135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150 dump_data(10, (uint8 *)val, sizeret);
153 if (strnequal(ea_name, "user.", 5)) {
154 pea->name = &ea_name[5];
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168 const char *fname, size_t *pea_total_len)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size = 1024;
176 struct ea_list *ea_list_head = NULL;
180 if (!lp_ea_support(SNUM(conn))) {
184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
191 if (fsp && fsp->fh->fd != -1) {
192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
197 if (sizeret == -1 && errno == ERANGE) {
198 ea_namelist_size *= 2;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211 struct ea_list *listp;
213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
216 listp = TALLOC_P(mem_ctx, struct ea_list);
220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
226 push_ascii_fstring(dos_ea_name, listp->ea.name);
227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len, dos_ea_name,
230 (unsigned int)listp->ea.value.length ));
232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
234 /* Add on 4 for total length. */
235 if (*pea_total_len) {
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250 connection_struct *conn, struct ea_list *ea_list)
252 unsigned int ret_data_size = 4;
255 SMB_ASSERT(total_data_size >= 4);
257 if (!lp_ea_support(SNUM(conn))) {
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
270 if (ea_list->ea.value.length > 65535) {
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290 SIVAL(pdata,0,ret_data_size);
291 return ret_data_size;
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
296 size_t total_ea_len = 0;
297 TALLOC_CTX *mem_ctx = NULL;
299 if (!lp_ea_support(SNUM(conn))) {
302 mem_ctx = talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304 talloc_destroy(mem_ctx);
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
318 for (; ea_list; ea_list = ea_list->next) {
319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name[5], ea_list->ea.name));
322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
326 talloc_destroy(mem_ctx);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
335 if (!lp_ea_support(SNUM(conn))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED;
339 for (;ea_list; ea_list = ea_list->next) {
341 fstring unix_ea_name;
343 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name, ea_list->ea.name);
346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
350 if (samba_private_attr_name(unix_ea_name)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352 return NT_STATUS_ACCESS_DENIED;
355 if (ea_list->ea.value.length == 0) {
356 /* Remove the attribute. */
357 if (fsp && (fsp->fh->fd != -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name, fsp->fsp_name));
360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name, fname));
364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
367 /* Removing a non existent attribute always succeeds. */
368 if (ret == -1 && errno == ENOATTR) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
375 if (fsp && (fsp->fh->fd != -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name, fsp->fsp_name));
378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name, fname));
383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
390 if (errno == ENOTSUP) {
391 return NT_STATUS_EAS_NOT_SUPPORTED;
394 return map_nt_error_from_unix(errno);
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
406 struct ea_list *ea_list_head = NULL;
409 while (offset + 2 < data_size) {
410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411 unsigned int namelen = CVAL(pdata,offset);
413 offset++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417 (offset > data_size) || (namelen > data_size) ||
418 (offset + namelen >= data_size)) {
421 /* Ensure the name is null terminated. */
422 if (pdata[offset + namelen] != '\0') {
425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
430 offset += (namelen + 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
446 unsigned int namelen;
456 eal->ea.flags = CVAL(pdata,0);
457 namelen = CVAL(pdata,1);
458 val_len = SVAL(pdata,2);
460 if (4 + namelen + 1 + val_len > data_size) {
464 /* Ensure the name is null terminated. */
465 if (pdata[namelen + 4] != '\0') {
468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474 if (!eal->ea.value.data) {
478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal->ea.value.data[val_len] = '\0';
482 /* But don't count the null. */
483 eal->ea.value.length--;
486 *pbytes_used = 4 + namelen + 1 + val_len;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490 dump_data(10, eal->ea.value.data, eal->ea.value.length);
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
501 struct ea_list *ea_list_head = NULL;
503 size_t bytes_used = 0;
505 while (offset < data_size) {
506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513 offset += bytes_used;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list *ealist)
526 struct ea_list *listp;
529 for (listp = ealist; listp; listp = listp->next) {
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 /* Add on 4 for total length. */
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
549 struct ea_list *nlistp, *flistp;
551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552 for (flistp = file_list; flistp; flistp = flistp->next) {
553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
559 /* Copy the data from this entry. */
560 nlistp->ea.flags = flistp->ea.flags;
561 nlistp->ea.value = flistp->ea.value;
564 nlistp->ea.flags = 0;
565 ZERO_STRUCT(nlistp->ea.value);
569 *total_ea_len = ea_list_size(name_list);
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(const char *inbuf,
589 /* As we are using a protocol > LANMAN1 then the max_send
590 variable must have been set in the sessetupX call.
591 This takes precedence over the max_xmit field in the
592 global struct. These different max_xmit variables should
593 be merged as this is now too confusing */
595 int data_to_send = datasize;
596 int params_to_send = paramsize;
598 const char *pp = params;
599 const char *pd = pdata;
600 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
601 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
602 int data_alignment_offset = 0;
604 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
606 set_message(inbuf,outbuf,10,0,True);
608 /* Modify the data_to_send and datasize and set the error if
609 we're trying to send more than max_data_bytes. We still send
610 the part of the packet(s) that fit. Strange, but needed
613 if (max_data_bytes > 0 && datasize > max_data_bytes) {
614 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
615 max_data_bytes, datasize ));
616 datasize = data_to_send = max_data_bytes;
617 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
620 /* If there genuinely are no parameters or data to send just send the empty packet */
622 if(params_to_send == 0 && data_to_send == 0) {
624 if (!send_smb(smbd_server_fd(),outbuf))
625 exit_server_cleanly("send_trans2_replies: send_smb failed.");
629 /* When sending params and data ensure that both are nicely aligned */
630 /* Only do this alignment when there is also data to send - else
631 can cause NT redirector problems. */
633 if (((params_to_send % 4) != 0) && (data_to_send != 0))
634 data_alignment_offset = 4 - (params_to_send % 4);
636 /* Space is bufsize minus Netbios over TCP header minus SMB header */
637 /* The alignment_offset is to align the param bytes on an even byte
638 boundary. NT 4.0 Beta needs this to work correctly. */
640 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
642 /* useable_space can never be more than max_send minus the alignment offset. */
644 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
646 while (params_to_send || data_to_send) {
647 /* Calculate whether we will totally or partially fill this packet */
649 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
651 /* We can never send more than useable_space */
653 * Note that 'useable_space' does not include the alignment offsets,
654 * but we must include the alignment offsets in the calculation of
655 * the length of the data we send over the wire, as the alignment offsets
656 * are sent here. Fix from Marc_Jacobsen@hp.com.
659 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
661 set_message(inbuf, outbuf, 10, total_sent_thistime, True);
663 /* Set total params and data to be sent */
664 SSVAL(outbuf,smb_tprcnt,paramsize);
665 SSVAL(outbuf,smb_tdrcnt,datasize);
667 /* Calculate how many parameters and data we can fit into
668 * this packet. Parameters get precedence
671 params_sent_thistime = MIN(params_to_send,useable_space);
672 data_sent_thistime = useable_space - params_sent_thistime;
673 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
675 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
677 /* smb_proff is the offset from the start of the SMB header to the
678 parameter bytes, however the first 4 bytes of outbuf are
679 the Netbios over TCP header. Thus use smb_base() to subtract
680 them from the calculation */
682 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
684 if(params_sent_thistime == 0)
685 SSVAL(outbuf,smb_prdisp,0);
687 /* Absolute displacement of param bytes sent in this packet */
688 SSVAL(outbuf,smb_prdisp,pp - params);
690 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
691 if(data_sent_thistime == 0) {
692 SSVAL(outbuf,smb_droff,0);
693 SSVAL(outbuf,smb_drdisp, 0);
695 /* The offset of the data bytes is the offset of the
696 parameter bytes plus the number of parameters being sent this time */
697 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
698 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
699 SSVAL(outbuf,smb_drdisp, pd - pdata);
702 /* Copy the param bytes into the packet */
704 if(params_sent_thistime)
705 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
707 /* Copy in the data bytes */
708 if(data_sent_thistime)
709 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
710 data_alignment_offset,pd,data_sent_thistime);
712 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
713 params_sent_thistime, data_sent_thistime, useable_space));
714 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
715 params_to_send, data_to_send, paramsize, datasize));
717 /* Send the packet */
719 if (!send_smb(smbd_server_fd(),outbuf))
720 exit_server_cleanly("send_trans2_replies: send_smb failed.");
722 pp += params_sent_thistime;
723 pd += data_sent_thistime;
725 params_to_send -= params_sent_thistime;
726 data_to_send -= data_sent_thistime;
729 if(params_to_send < 0 || data_to_send < 0) {
730 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
731 params_to_send, data_to_send));
739 /****************************************************************************
740 Reply to a TRANSACT2_OPEN.
741 ****************************************************************************/
743 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
744 char **pparams, int total_params, char **ppdata, int total_data,
745 unsigned int max_data_bytes)
747 char *params = *pparams;
748 char *pdata = *ppdata;
753 BOOL return_additional_info;
764 SMB_STRUCT_STAT sbuf;
767 struct ea_list *ea_list = NULL;
772 uint32 create_disposition;
773 uint32 create_options = 0;
776 * Ensure we have enough parameters to perform the operation.
779 if (total_params < 29) {
780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
783 flags = SVAL(params, 0);
784 deny_mode = SVAL(params, 2);
785 open_attr = SVAL(params,6);
786 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
787 if (oplock_request) {
788 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
792 return_additional_info = BITSETW(params,0);
793 open_sattr = SVAL(params, 4);
794 open_time = make_unix_date3(params+8);
796 open_ofun = SVAL(params,12);
797 open_size = IVAL(params,14);
801 return(ERROR_DOS(ERRSRV,ERRaccess));
804 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
805 if (!NT_STATUS_IS_OK(status)) {
806 return ERROR_NT(status);
809 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
810 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
811 (unsigned int)open_ofun, open_size));
813 /* XXXX we need to handle passed times, sattr and flags */
815 status = unix_convert(conn, fname, False, NULL, &sbuf);
816 if (!NT_STATUS_IS_OK(status)) {
817 return ERROR_NT(status);
820 status = check_name(conn, fname);
821 if (!NT_STATUS_IS_OK(status)) {
822 return ERROR_NT(status);
825 if (open_ofun == 0) {
826 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
829 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
834 return ERROR_DOS(ERRDOS, ERRbadaccess);
837 /* Any data in this call is an EA list. */
838 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
839 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
842 if (total_data != 4) {
843 if (total_data < 10) {
844 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
847 if (IVAL(pdata,0) > total_data) {
848 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
849 IVAL(pdata,0), (unsigned int)total_data));
850 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
853 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
858 } else if (IVAL(pdata,0) != 4) {
859 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
862 status = open_file_ntcreate(conn,fname,&sbuf,
871 if (!NT_STATUS_IS_OK(status)) {
872 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
873 /* We have re-scheduled this call. */
876 return ERROR_NT(status);
879 size = get_file_size(sbuf);
880 fattr = dos_mode(conn,fname,&sbuf);
881 mtime = sbuf.st_mtime;
884 close_file(fsp,ERROR_CLOSE);
885 return(ERROR_DOS(ERRDOS,ERRnoaccess));
888 /* Save the requested allocation size. */
889 /* Allocate space for the file if a size hint is supplied */
890 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
891 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
892 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
893 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
894 if (fsp->is_directory) {
895 close_file(fsp,ERROR_CLOSE);
896 /* Can't set allocation size on a directory. */
897 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
899 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
900 close_file(fsp,ERROR_CLOSE);
901 return ERROR_NT(NT_STATUS_DISK_FULL);
904 /* Adjust size here to return the right size in the reply.
905 Windows does it this way. */
906 size = fsp->initial_allocation_size;
908 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
912 if (ea_list && smb_action == FILE_WAS_CREATED) {
913 status = set_ea(conn, fsp, fname, ea_list);
914 if (!NT_STATUS_IS_OK(status)) {
915 close_file(fsp,ERROR_CLOSE);
916 return ERROR_NT(status);
920 /* Realloc the size of parameters and data we will return */
921 *pparams = (char *)SMB_REALLOC(*pparams, 30);
922 if(*pparams == NULL ) {
923 return ERROR_NT(NT_STATUS_NO_MEMORY);
927 SSVAL(params,0,fsp->fnum);
928 SSVAL(params,2,fattr);
929 srv_put_dos_date2(params,4, mtime);
930 SIVAL(params,8, (uint32)size);
931 SSVAL(params,12,deny_mode);
932 SSVAL(params,14,0); /* open_type - file or directory. */
933 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
935 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
936 smb_action |= EXTENDED_OPLOCK_GRANTED;
939 SSVAL(params,18,smb_action);
942 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
944 SIVAL(params,20,inode);
945 SSVAL(params,24,0); /* Padding. */
947 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
948 SIVAL(params, 26, ea_size);
950 SIVAL(params, 26, 0);
953 /* Send the required number of replies */
954 send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
959 /*********************************************************
960 Routine to check if a given string matches exactly.
961 as a special case a mask of "." does NOT match. That
962 is required for correct wildcard semantics
963 Case can be significant or not.
964 **********************************************************/
966 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
968 if (mask[0] == '.' && mask[1] == 0)
970 if (conn->case_sensitive)
971 return strcmp(str,mask)==0;
972 if (StrCaseCmp(str,mask) != 0) {
975 if (dptr_has_wild(conn->dirptr)) {
981 /****************************************************************************
982 Return the filetype for UNIX extensions.
983 ****************************************************************************/
985 static uint32 unix_filetype(mode_t mode)
988 return UNIX_TYPE_FILE;
989 else if(S_ISDIR(mode))
990 return UNIX_TYPE_DIR;
992 else if(S_ISLNK(mode))
993 return UNIX_TYPE_SYMLINK;
996 else if(S_ISCHR(mode))
997 return UNIX_TYPE_CHARDEV;
1000 else if(S_ISBLK(mode))
1001 return UNIX_TYPE_BLKDEV;
1004 else if(S_ISFIFO(mode))
1005 return UNIX_TYPE_FIFO;
1008 else if(S_ISSOCK(mode))
1009 return UNIX_TYPE_SOCKET;
1012 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1013 return UNIX_TYPE_UNKNOWN;
1016 /****************************************************************************
1017 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1018 ****************************************************************************/
1020 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1022 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1023 SMB_STRUCT_STAT *psbuf,
1025 enum perm_type ptype,
1030 if (perms == SMB_MODE_NO_CHANGE) {
1031 if (!VALID_STAT(*psbuf)) {
1032 return NT_STATUS_INVALID_PARAMETER;
1034 *ret_perms = psbuf->st_mode;
1035 return NT_STATUS_OK;
1039 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1040 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1041 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1042 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1043 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1044 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1045 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1046 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1047 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1049 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1052 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1055 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1060 /* Apply mode mask */
1061 ret &= lp_create_mask(SNUM(conn));
1062 /* Add in force bits */
1063 ret |= lp_force_create_mode(SNUM(conn));
1066 ret &= lp_dir_mask(SNUM(conn));
1067 /* Add in force bits */
1068 ret |= lp_force_dir_mode(SNUM(conn));
1070 case PERM_EXISTING_FILE:
1071 /* Apply mode mask */
1072 ret &= lp_security_mask(SNUM(conn));
1073 /* Add in force bits */
1074 ret |= lp_force_security_mode(SNUM(conn));
1076 case PERM_EXISTING_DIR:
1077 /* Apply mode mask */
1078 ret &= lp_dir_security_mask(SNUM(conn));
1079 /* Add in force bits */
1080 ret |= lp_force_dir_security_mode(SNUM(conn));
1085 return NT_STATUS_OK;
1088 /****************************************************************************
1089 Get a level dependent lanman2 dir entry.
1090 ****************************************************************************/
1092 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1093 void *inbuf, char *outbuf,
1094 char *path_mask,uint32 dirtype,int info_level,
1095 int requires_resume_key,
1096 BOOL dont_descend,char **ppdata,
1097 char *base_data, int space_remaining,
1098 BOOL *out_of_space, BOOL *got_exact_match,
1099 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1103 SMB_STRUCT_STAT sbuf;
1107 char *p, *q, *pdata = *ppdata;
1111 SMB_OFF_T file_size = 0;
1112 SMB_BIG_UINT allocation_size = 0;
1114 struct timespec mdate_ts, adate_ts, create_date_ts;
1115 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1117 char *last_entry_ptr;
1119 uint32 nt_extmode; /* Used for NT connections instead of mode */
1120 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1121 BOOL check_mangled_names = lp_manglednames(conn->params);
1124 *out_of_space = False;
1125 *got_exact_match = False;
1127 ZERO_STRUCT(mdate_ts);
1128 ZERO_STRUCT(adate_ts);
1129 ZERO_STRUCT(create_date_ts);
1134 p = strrchr_m(path_mask,'/');
1137 pstrcpy(mask,"*.*");
1141 pstrcpy(mask, path_mask);
1146 BOOL ms_dfs_link = False;
1148 /* Needed if we run out of space */
1149 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1150 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1153 * Due to bugs in NT client redirectors we are not using
1154 * resume keys any more - set them to zero.
1155 * Check out the related comments in findfirst/findnext.
1161 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1162 (long)conn->dirptr,curr_dirpos));
1169 * fname may get mangled, dname is never mangled.
1170 * Whenever we're accessing the filesystem we use
1171 * pathreal which is composed from dname.
1174 pstrcpy(fname,dname);
1176 /* This will mangle fname if it's an illegal name. */
1177 mangle_map(fname,False,True,conn->params);
1179 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1180 got_match = mask_match(fname, mask, conn->case_sensitive);
1183 if(!got_match && check_mangled_names &&
1184 !mangle_is_8_3(fname, False, conn->params)) {
1185 pstring mangled_name;
1188 * It turns out that NT matches wildcards against
1189 * both long *and* short names. This may explain some
1190 * of the wildcard wierdness from old DOS clients
1191 * that some people have been seeing.... JRA.
1194 pstrcpy(mangled_name, fname);
1196 /* Force the mangling into 8.3. */
1197 mangle_map( mangled_name, True, False, conn->params);
1198 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1199 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1204 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1205 if (dont_descend && !isdots) {
1209 pstrcpy(pathreal,conn->dirpath);
1211 pstrcat(pathreal,"/");
1213 pstrcat(pathreal,dname);
1215 if (INFO_LEVEL_IS_UNIX(info_level)) {
1216 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1217 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1218 pathreal,strerror(errno)));
1221 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1222 pstring link_target;
1224 /* Needed to show the msdfs symlinks as
1227 if(lp_host_msdfs() &&
1228 lp_msdfs_root(SNUM(conn)) &&
1229 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1230 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1233 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1237 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1238 pathreal,strerror(errno)));
1244 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1246 mode = dos_mode(conn,pathreal,&sbuf);
1249 if (!dir_check_ftype(conn,mode,dirtype)) {
1250 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1254 if (!(mode & aDIR)) {
1255 file_size = get_file_size(sbuf);
1257 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1259 mdate_ts = get_mtimespec(&sbuf);
1260 adate_ts = get_atimespec(&sbuf);
1261 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1263 if (lp_dos_filetime_resolution(SNUM(conn))) {
1264 dos_filetime_timespec(&create_date_ts);
1265 dos_filetime_timespec(&mdate_ts);
1266 dos_filetime_timespec(&adate_ts);
1269 create_date = convert_timespec_to_time_t(create_date_ts);
1270 mdate = convert_timespec_to_time_t(mdate_ts);
1271 adate = convert_timespec_to_time_t(adate_ts);
1273 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1277 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1284 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1286 switch (info_level) {
1287 case SMB_FIND_INFO_STANDARD:
1288 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1289 if(requires_resume_key) {
1293 srv_put_dos_date2(p,0,create_date);
1294 srv_put_dos_date2(p,4,adate);
1295 srv_put_dos_date2(p,8,mdate);
1296 SIVAL(p,12,(uint32)file_size);
1297 SIVAL(p,16,(uint32)allocation_size);
1301 p += align_string(outbuf, p, 0);
1302 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1303 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1305 SCVAL(nameptr, -1, len - 2);
1307 SCVAL(nameptr, -1, 0);
1311 SCVAL(nameptr, -1, len - 1);
1313 SCVAL(nameptr, -1, 0);
1319 case SMB_FIND_EA_SIZE:
1320 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1321 if(requires_resume_key) {
1325 srv_put_dos_date2(p,0,create_date);
1326 srv_put_dos_date2(p,4,adate);
1327 srv_put_dos_date2(p,8,mdate);
1328 SIVAL(p,12,(uint32)file_size);
1329 SIVAL(p,16,(uint32)allocation_size);
1332 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1333 SIVAL(p,22,ea_size); /* Extended attributes */
1337 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1338 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1351 SCVAL(nameptr,0,len);
1353 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1356 case SMB_FIND_EA_LIST:
1358 struct ea_list *file_list = NULL;
1361 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1365 if(requires_resume_key) {
1369 srv_put_dos_date2(p,0,create_date);
1370 srv_put_dos_date2(p,4,adate);
1371 srv_put_dos_date2(p,8,mdate);
1372 SIVAL(p,12,(uint32)file_size);
1373 SIVAL(p,16,(uint32)allocation_size);
1375 p += 22; /* p now points to the EA area. */
1377 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1378 name_list = ea_list_union(name_list, file_list, &ea_len);
1380 /* We need to determine if this entry will fit in the space available. */
1381 /* Max string size is 255 bytes. */
1382 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1383 /* Move the dirptr back to prev_dirpos */
1384 dptr_SeekDir(conn->dirptr, prev_dirpos);
1385 *out_of_space = True;
1386 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1387 return False; /* Not finished - just out of space */
1390 /* Push the ea_data followed by the name. */
1391 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1393 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1394 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1407 SCVAL(nameptr,0,len);
1409 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1413 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1414 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1415 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1417 SIVAL(p,0,reskey); p += 4;
1418 put_long_date_timespec(p,create_date_ts); p += 8;
1419 put_long_date_timespec(p,adate_ts); p += 8;
1420 put_long_date_timespec(p,mdate_ts); p += 8;
1421 put_long_date_timespec(p,mdate_ts); p += 8;
1422 SOFF_T(p,0,file_size); p += 8;
1423 SOFF_T(p,0,allocation_size); p += 8;
1424 SIVAL(p,0,nt_extmode); p += 4;
1425 q = p; p += 4; /* q is placeholder for name length. */
1427 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1428 SIVAL(p,0,ea_size); /* Extended attributes */
1431 /* Clear the short name buffer. This is
1432 * IMPORTANT as not doing so will trigger
1433 * a Win2k client bug. JRA.
1435 if (!was_8_3 && check_mangled_names) {
1436 pstring mangled_name;
1437 pstrcpy(mangled_name, fname);
1438 mangle_map(mangled_name,True,True,
1440 mangled_name[12] = 0;
1441 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1443 memset(p + 2 + len,'\0',24 - len);
1450 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1453 SIVAL(p,0,0); /* Ensure any padding is null. */
1454 len = PTR_DIFF(p, pdata);
1455 len = (len + 3) & ~3;
1460 case SMB_FIND_FILE_DIRECTORY_INFO:
1461 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1463 SIVAL(p,0,reskey); p += 4;
1464 put_long_date_timespec(p,create_date_ts); p += 8;
1465 put_long_date_timespec(p,adate_ts); p += 8;
1466 put_long_date_timespec(p,mdate_ts); p += 8;
1467 put_long_date_timespec(p,mdate_ts); p += 8;
1468 SOFF_T(p,0,file_size); p += 8;
1469 SOFF_T(p,0,allocation_size); p += 8;
1470 SIVAL(p,0,nt_extmode); p += 4;
1471 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1474 SIVAL(p,0,0); /* Ensure any padding is null. */
1475 len = PTR_DIFF(p, pdata);
1476 len = (len + 3) & ~3;
1481 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1482 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1484 SIVAL(p,0,reskey); p += 4;
1485 put_long_date_timespec(p,create_date_ts); p += 8;
1486 put_long_date_timespec(p,adate_ts); p += 8;
1487 put_long_date_timespec(p,mdate_ts); p += 8;
1488 put_long_date_timespec(p,mdate_ts); p += 8;
1489 SOFF_T(p,0,file_size); p += 8;
1490 SOFF_T(p,0,allocation_size); p += 8;
1491 SIVAL(p,0,nt_extmode); p += 4;
1492 q = p; p += 4; /* q is placeholder for name length. */
1494 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1495 SIVAL(p,0,ea_size); /* Extended attributes */
1498 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1502 SIVAL(p,0,0); /* Ensure any padding is null. */
1503 len = PTR_DIFF(p, pdata);
1504 len = (len + 3) & ~3;
1509 case SMB_FIND_FILE_NAMES_INFO:
1510 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1512 SIVAL(p,0,reskey); p += 4;
1514 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1515 acl on a dir (tridge) */
1516 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1519 SIVAL(p,0,0); /* Ensure any padding is null. */
1520 len = PTR_DIFF(p, pdata);
1521 len = (len + 3) & ~3;
1526 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1527 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1529 SIVAL(p,0,reskey); p += 4;
1530 put_long_date_timespec(p,create_date_ts); p += 8;
1531 put_long_date_timespec(p,adate_ts); p += 8;
1532 put_long_date_timespec(p,mdate_ts); p += 8;
1533 put_long_date_timespec(p,mdate_ts); p += 8;
1534 SOFF_T(p,0,file_size); p += 8;
1535 SOFF_T(p,0,allocation_size); p += 8;
1536 SIVAL(p,0,nt_extmode); p += 4;
1537 q = p; p += 4; /* q is placeholder for name length. */
1539 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1540 SIVAL(p,0,ea_size); /* Extended attributes */
1543 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1544 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1545 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1546 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1549 SIVAL(p,0,0); /* Ensure any padding is null. */
1550 len = PTR_DIFF(p, pdata);
1551 len = (len + 3) & ~3;
1556 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1557 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1558 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1560 SIVAL(p,0,reskey); p += 4;
1561 put_long_date_timespec(p,create_date_ts); p += 8;
1562 put_long_date_timespec(p,adate_ts); p += 8;
1563 put_long_date_timespec(p,mdate_ts); p += 8;
1564 put_long_date_timespec(p,mdate_ts); p += 8;
1565 SOFF_T(p,0,file_size); p += 8;
1566 SOFF_T(p,0,allocation_size); p += 8;
1567 SIVAL(p,0,nt_extmode); p += 4;
1568 q = p; p += 4; /* q is placeholder for name length */
1570 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1571 SIVAL(p,0,ea_size); /* Extended attributes */
1574 /* Clear the short name buffer. This is
1575 * IMPORTANT as not doing so will trigger
1576 * a Win2k client bug. JRA.
1578 if (!was_8_3 && check_mangled_names) {
1579 pstring mangled_name;
1580 pstrcpy(mangled_name, fname);
1581 mangle_map(mangled_name,True,True,
1583 mangled_name[12] = 0;
1584 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1587 memset(p + 2 + len,'\0',24 - len);
1594 SSVAL(p,0,0); p += 2; /* Reserved ? */
1595 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1596 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1597 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1600 SIVAL(p,0,0); /* Ensure any padding is null. */
1601 len = PTR_DIFF(p, pdata);
1602 len = (len + 3) & ~3;
1607 /* CIFS UNIX Extension. */
1609 case SMB_FIND_FILE_UNIX:
1610 case SMB_FIND_FILE_UNIX_INFO2:
1612 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1614 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1616 if (info_level == SMB_FIND_FILE_UNIX) {
1617 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1618 p = store_file_unix_basic(conn, p,
1620 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1622 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1623 p = store_file_unix_basic_info2(conn, p,
1627 len = srvstr_push(outbuf, p, fname, -1, 0);
1628 SIVAL(nameptr, 0, len);
1632 SIVAL(p,0,0); /* Ensure any padding is null. */
1634 len = PTR_DIFF(p, pdata);
1635 len = (len + 3) & ~3;
1636 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1638 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1647 if (PTR_DIFF(p,pdata) > space_remaining) {
1648 /* Move the dirptr back to prev_dirpos */
1649 dptr_SeekDir(conn->dirptr, prev_dirpos);
1650 *out_of_space = True;
1651 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1652 return False; /* Not finished - just out of space */
1655 /* Setup the last entry pointer, as an offset from base_data */
1656 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1657 /* Advance the data pointer to the next slot */
1663 /****************************************************************************
1664 Reply to a TRANS2_FINDFIRST.
1665 ****************************************************************************/
1667 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1668 char **pparams, int total_params, char **ppdata, int total_data,
1669 unsigned int max_data_bytes)
1671 /* We must be careful here that we don't return more than the
1672 allowed number of data bytes. If this means returning fewer than
1673 maxentries then so be it. We assume that the redirector has
1674 enough room for the fixed number of parameter bytes it has
1676 char *params = *pparams;
1677 char *pdata = *ppdata;
1680 uint16 findfirst_flags;
1681 BOOL close_after_first;
1683 BOOL requires_resume_key;
1688 int last_entry_off=0;
1692 BOOL finished = False;
1693 BOOL dont_descend = False;
1694 BOOL out_of_space = False;
1695 int space_remaining;
1696 BOOL mask_contains_wcard = False;
1697 SMB_STRUCT_STAT sbuf;
1698 TALLOC_CTX *ea_ctx = NULL;
1699 struct ea_list *ea_list = NULL;
1700 NTSTATUS ntstatus = NT_STATUS_OK;
1702 if (total_params < 13) {
1703 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1706 dirtype = SVAL(params,0);
1707 maxentries = SVAL(params,2);
1708 findfirst_flags = SVAL(params,4);
1709 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1710 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1711 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1712 info_level = SVAL(params,6);
1714 *directory = *mask = 0;
1716 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1717 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1718 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1719 info_level, max_data_bytes));
1722 /* W2K3 seems to treat zero as 1. */
1726 switch (info_level) {
1727 case SMB_FIND_INFO_STANDARD:
1728 case SMB_FIND_EA_SIZE:
1729 case SMB_FIND_EA_LIST:
1730 case SMB_FIND_FILE_DIRECTORY_INFO:
1731 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1732 case SMB_FIND_FILE_NAMES_INFO:
1733 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1734 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1735 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1737 case SMB_FIND_FILE_UNIX:
1738 case SMB_FIND_FILE_UNIX_INFO2:
1739 if (!lp_unix_extensions()) {
1740 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1744 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1747 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1748 if (!NT_STATUS_IS_OK(ntstatus)) {
1749 return ERROR_NT(ntstatus);
1752 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1753 if (!NT_STATUS_IS_OK(ntstatus)) {
1754 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1755 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1757 return ERROR_NT(ntstatus);
1760 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1761 if (!NT_STATUS_IS_OK(ntstatus)) {
1762 return ERROR_NT(ntstatus);
1764 ntstatus = check_name(conn, directory);
1765 if (!NT_STATUS_IS_OK(ntstatus)) {
1766 return ERROR_NT(ntstatus);
1769 p = strrchr_m(directory,'/');
1771 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1772 if((directory[0] == '.') && (directory[1] == '\0')) {
1774 mask_contains_wcard = True;
1776 pstrcpy(mask,directory);
1778 pstrcpy(directory,"./");
1784 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1786 if (info_level == SMB_FIND_EA_LIST) {
1789 if (total_data < 4) {
1790 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1793 ea_size = IVAL(pdata,0);
1794 if (ea_size != total_data) {
1795 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1796 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1797 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1800 if (!lp_ea_support(SNUM(conn))) {
1801 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1804 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1805 return ERROR_NT(NT_STATUS_NO_MEMORY);
1808 /* Pull out the list of names. */
1809 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1811 talloc_destroy(ea_ctx);
1812 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1816 *ppdata = (char *)SMB_REALLOC(
1817 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1818 if(*ppdata == NULL ) {
1819 talloc_destroy(ea_ctx);
1820 return ERROR_NT(NT_STATUS_NO_MEMORY);
1824 /* Realloc the params space */
1825 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1826 if (*pparams == NULL) {
1827 talloc_destroy(ea_ctx);
1828 return ERROR_NT(NT_STATUS_NO_MEMORY);
1832 /* Save the wildcard match and attribs we are using on this directory -
1833 needed as lanman2 assumes these are being saved between calls */
1835 ntstatus = dptr_create(conn,
1839 SVAL(inbuf,smb_pid),
1841 mask_contains_wcard,
1845 if (!NT_STATUS_IS_OK(ntstatus)) {
1846 talloc_destroy(ea_ctx);
1847 return ERROR_NT(ntstatus);
1850 dptr_num = dptr_dnum(conn->dirptr);
1851 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1853 /* We don't need to check for VOL here as this is returned by
1854 a different TRANS2 call. */
1856 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1857 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1858 dont_descend = True;
1861 space_remaining = max_data_bytes;
1862 out_of_space = False;
1864 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1865 BOOL got_exact_match = False;
1867 /* this is a heuristic to avoid seeking the dirptr except when
1868 absolutely necessary. It allows for a filename of about 40 chars */
1869 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1870 out_of_space = True;
1873 finished = !get_lanman2_dir_entry(conn,
1875 mask,dirtype,info_level,
1876 requires_resume_key,dont_descend,
1877 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1878 &last_entry_off, ea_list, ea_ctx);
1881 if (finished && out_of_space)
1884 if (!finished && !out_of_space)
1888 * As an optimisation if we know we aren't looking
1889 * for a wildcard name (ie. the name matches the wildcard exactly)
1890 * then we can finish on any (first) match.
1891 * This speeds up large directory searches. JRA.
1897 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1900 talloc_destroy(ea_ctx);
1902 /* Check if we can close the dirptr */
1903 if(close_after_first || (finished && close_if_end)) {
1904 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1905 dptr_close(&dptr_num);
1909 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1910 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1911 * the protocol level is less than NT1. Tested with smbclient. JRA.
1912 * This should fix the OS/2 client bug #2335.
1915 if(numentries == 0) {
1916 dptr_close(&dptr_num);
1917 if (Protocol < PROTOCOL_NT1) {
1918 return ERROR_DOS(ERRDOS,ERRnofiles);
1920 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1924 /* At this point pdata points to numentries directory entries. */
1926 /* Set up the return parameter block */
1927 SSVAL(params,0,dptr_num);
1928 SSVAL(params,2,numentries);
1929 SSVAL(params,4,finished);
1930 SSVAL(params,6,0); /* Never an EA error */
1931 SSVAL(params,8,last_entry_off);
1933 send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1935 if ((! *directory) && dptr_path(dptr_num))
1936 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1938 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1939 smb_fn_name(CVAL(inbuf,smb_com)),
1940 mask, directory, dirtype, numentries ) );
1943 * Force a name mangle here to ensure that the
1944 * mask as an 8.3 name is top of the mangled cache.
1945 * The reasons for this are subtle. Don't remove
1946 * this code unless you know what you are doing
1947 * (see PR#13758). JRA.
1950 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1951 mangle_map(mask, True, True, conn->params);
1956 /****************************************************************************
1957 Reply to a TRANS2_FINDNEXT.
1958 ****************************************************************************/
1960 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1961 char **pparams, int total_params, char **ppdata, int total_data,
1962 unsigned int max_data_bytes)
1964 /* We must be careful here that we don't return more than the
1965 allowed number of data bytes. If this means returning fewer than
1966 maxentries then so be it. We assume that the redirector has
1967 enough room for the fixed number of parameter bytes it has
1969 char *params = *pparams;
1970 char *pdata = *ppdata;
1975 uint16 findnext_flags;
1976 BOOL close_after_request;
1978 BOOL requires_resume_key;
1980 BOOL mask_contains_wcard = False;
1981 pstring resume_name;
1987 int i, last_entry_off=0;
1988 BOOL finished = False;
1989 BOOL dont_descend = False;
1990 BOOL out_of_space = False;
1991 int space_remaining;
1992 TALLOC_CTX *ea_ctx = NULL;
1993 struct ea_list *ea_list = NULL;
1994 NTSTATUS ntstatus = NT_STATUS_OK;
1996 if (total_params < 13) {
1997 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2000 dptr_num = SVAL(params,0);
2001 maxentries = SVAL(params,2);
2002 info_level = SVAL(params,4);
2003 resume_key = IVAL(params,6);
2004 findnext_flags = SVAL(params,10);
2005 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2006 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2007 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2008 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2010 *mask = *directory = *resume_name = 0;
2012 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2013 if (!NT_STATUS_IS_OK(ntstatus)) {
2014 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2015 complain (it thinks we're asking for the directory above the shared
2016 path or an invalid name). Catch this as the resume name is only compared, never used in
2017 a file access. JRA. */
2018 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2019 pstrcpy(resume_name, "..");
2020 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2021 pstrcpy(resume_name, ".");
2023 return ERROR_NT(ntstatus);
2027 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2028 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2029 resume_key = %d resume name = %s continue=%d level = %d\n",
2030 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2031 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2034 /* W2K3 seems to treat zero as 1. */
2038 switch (info_level) {
2039 case SMB_FIND_INFO_STANDARD:
2040 case SMB_FIND_EA_SIZE:
2041 case SMB_FIND_EA_LIST:
2042 case SMB_FIND_FILE_DIRECTORY_INFO:
2043 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2044 case SMB_FIND_FILE_NAMES_INFO:
2045 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2046 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2047 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2049 case SMB_FIND_FILE_UNIX:
2050 case SMB_FIND_FILE_UNIX_INFO2:
2051 if (!lp_unix_extensions()) {
2052 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2056 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2059 if (info_level == SMB_FIND_EA_LIST) {
2062 if (total_data < 4) {
2063 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2066 ea_size = IVAL(pdata,0);
2067 if (ea_size != total_data) {
2068 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2069 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2070 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2073 if (!lp_ea_support(SNUM(conn))) {
2074 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2077 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2078 return ERROR_NT(NT_STATUS_NO_MEMORY);
2081 /* Pull out the list of names. */
2082 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2084 talloc_destroy(ea_ctx);
2085 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2089 *ppdata = (char *)SMB_REALLOC(
2090 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2091 if(*ppdata == NULL) {
2092 talloc_destroy(ea_ctx);
2093 return ERROR_NT(NT_STATUS_NO_MEMORY);
2098 /* Realloc the params space */
2099 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2100 if(*pparams == NULL ) {
2101 talloc_destroy(ea_ctx);
2102 return ERROR_NT(NT_STATUS_NO_MEMORY);
2107 /* Check that the dptr is valid */
2108 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2109 talloc_destroy(ea_ctx);
2110 return ERROR_DOS(ERRDOS,ERRnofiles);
2113 string_set(&conn->dirpath,dptr_path(dptr_num));
2115 /* Get the wildcard mask from the dptr */
2116 if((p = dptr_wcard(dptr_num))== NULL) {
2117 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2118 talloc_destroy(ea_ctx);
2119 return ERROR_DOS(ERRDOS,ERRnofiles);
2123 pstrcpy(directory,conn->dirpath);
2125 /* Get the attr mask from the dptr */
2126 dirtype = dptr_attr(dptr_num);
2128 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2129 dptr_num, mask, dirtype,
2131 dptr_TellDir(conn->dirptr)));
2133 /* We don't need to check for VOL here as this is returned by
2134 a different TRANS2 call. */
2136 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2137 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2138 dont_descend = True;
2141 space_remaining = max_data_bytes;
2142 out_of_space = False;
2145 * Seek to the correct position. We no longer use the resume key but
2146 * depend on the last file name instead.
2149 if(*resume_name && !continue_bit) {
2152 long current_pos = 0;
2154 * Remember, mangle_map is called by
2155 * get_lanman2_dir_entry(), so the resume name
2156 * could be mangled. Ensure we check the unmangled name.
2159 if (mangle_is_mangled(resume_name, conn->params)) {
2160 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2165 * Fix for NT redirector problem triggered by resume key indexes
2166 * changing between directory scans. We now return a resume key of 0
2167 * and instead look for the filename to continue from (also given
2168 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2169 * findfirst/findnext (as is usual) then the directory pointer
2170 * should already be at the correct place.
2173 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2174 } /* end if resume_name && !continue_bit */
2176 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2177 BOOL got_exact_match = False;
2179 /* this is a heuristic to avoid seeking the dirptr except when
2180 absolutely necessary. It allows for a filename of about 40 chars */
2181 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2182 out_of_space = True;
2185 finished = !get_lanman2_dir_entry(conn,
2187 mask,dirtype,info_level,
2188 requires_resume_key,dont_descend,
2189 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2190 &last_entry_off, ea_list, ea_ctx);
2193 if (finished && out_of_space)
2196 if (!finished && !out_of_space)
2200 * As an optimisation if we know we aren't looking
2201 * for a wildcard name (ie. the name matches the wildcard exactly)
2202 * then we can finish on any (first) match.
2203 * This speeds up large directory searches. JRA.
2209 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2212 talloc_destroy(ea_ctx);
2214 /* Check if we can close the dirptr */
2215 if(close_after_request || (finished && close_if_end)) {
2216 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2217 dptr_close(&dptr_num); /* This frees up the saved mask */
2220 /* Set up the return parameter block */
2221 SSVAL(params,0,numentries);
2222 SSVAL(params,2,finished);
2223 SSVAL(params,4,0); /* Never an EA error */
2224 SSVAL(params,6,last_entry_off);
2226 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2228 if ((! *directory) && dptr_path(dptr_num))
2229 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2231 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2232 smb_fn_name(CVAL(inbuf,smb_com)),
2233 mask, directory, dirtype, numentries ) );
2238 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2240 E_md4hash(lp_servicename(SNUM(conn)),objid);
2244 /****************************************************************************
2245 Reply to a TRANS2_QFSINFO (query filesystem info).
2246 ****************************************************************************/
2248 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2249 char **pparams, int total_params, char **ppdata, int total_data,
2250 unsigned int max_data_bytes)
2253 char *params = *pparams;
2257 const char *vname = volume_label(SNUM(conn));
2258 int snum = SNUM(conn);
2259 char *fstype = lp_fstype(SNUM(conn));
2262 if (total_params < 2) {
2263 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2266 info_level = SVAL(params,0);
2268 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2270 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2271 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2272 return ERROR_DOS(ERRSRV,ERRinvdevice);
2275 *ppdata = (char *)SMB_REALLOC(
2276 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2277 if (*ppdata == NULL ) {
2278 return ERROR_NT(NT_STATUS_NO_MEMORY);
2282 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2284 switch (info_level) {
2285 case SMB_INFO_ALLOCATION:
2287 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2289 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2290 return(UNIXERROR(ERRHRD,ERRgeneral));
2293 block_size = lp_block_size(snum);
2294 if (bsize < block_size) {
2295 SMB_BIG_UINT factor = block_size/bsize;
2300 if (bsize > block_size) {
2301 SMB_BIG_UINT factor = bsize/block_size;
2306 bytes_per_sector = 512;
2307 sectors_per_unit = bsize/bytes_per_sector;
2309 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2310 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2311 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2313 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2314 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2315 SIVAL(pdata,l1_cUnit,dsize);
2316 SIVAL(pdata,l1_cUnitAvail,dfree);
2317 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2321 case SMB_INFO_VOLUME:
2322 /* Return volume name */
2324 * Add volume serial number - hash of a combination of
2325 * the called hostname and the service name.
2327 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2329 * Win2k3 and previous mess this up by sending a name length
2330 * one byte short. I believe only older clients (OS/2 Win9x) use
2331 * this call so try fixing this by adding a terminating null to
2332 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2334 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2335 SCVAL(pdata,l2_vol_cch,len);
2336 data_len = l2_vol_szVolLabel + len;
2337 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2338 (unsigned)st.st_ctime, len, vname));
2341 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2342 case SMB_FS_ATTRIBUTE_INFORMATION:
2345 #if defined(HAVE_SYS_QUOTAS)
2346 quota_flag = FILE_VOLUME_QUOTAS;
2349 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2350 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2351 FILE_SUPPORTS_OBJECT_IDS|
2352 FILE_UNICODE_ON_DISK|
2353 quota_flag); /* FS ATTRIBUTES */
2355 SIVAL(pdata,4,255); /* Max filename component length */
2356 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2357 and will think we can't do long filenames */
2358 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2360 data_len = 12 + len;
2363 case SMB_QUERY_FS_LABEL_INFO:
2364 case SMB_FS_LABEL_INFORMATION:
2365 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2370 case SMB_QUERY_FS_VOLUME_INFO:
2371 case SMB_FS_VOLUME_INFORMATION:
2374 * Add volume serial number - hash of a combination of
2375 * the called hostname and the service name.
2377 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2378 (str_checksum(get_local_machine_name())<<16));
2380 /* Max label len is 32 characters. */
2381 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2382 SIVAL(pdata,12,len);
2385 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2386 (int)strlen(vname),vname, lp_servicename(snum)));
2389 case SMB_QUERY_FS_SIZE_INFO:
2390 case SMB_FS_SIZE_INFORMATION:
2392 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2394 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2395 return(UNIXERROR(ERRHRD,ERRgeneral));
2397 block_size = lp_block_size(snum);
2398 if (bsize < block_size) {
2399 SMB_BIG_UINT factor = block_size/bsize;
2404 if (bsize > block_size) {
2405 SMB_BIG_UINT factor = bsize/block_size;
2410 bytes_per_sector = 512;
2411 sectors_per_unit = bsize/bytes_per_sector;
2412 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2413 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2414 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2415 SBIG_UINT(pdata,0,dsize);
2416 SBIG_UINT(pdata,8,dfree);
2417 SIVAL(pdata,16,sectors_per_unit);
2418 SIVAL(pdata,20,bytes_per_sector);
2422 case SMB_FS_FULL_SIZE_INFORMATION:
2424 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2426 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2427 return(UNIXERROR(ERRHRD,ERRgeneral));
2429 block_size = lp_block_size(snum);
2430 if (bsize < block_size) {
2431 SMB_BIG_UINT factor = block_size/bsize;
2436 if (bsize > block_size) {
2437 SMB_BIG_UINT factor = bsize/block_size;
2442 bytes_per_sector = 512;
2443 sectors_per_unit = bsize/bytes_per_sector;
2444 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2445 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2446 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2447 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2448 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2449 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2450 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2451 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2455 case SMB_QUERY_FS_DEVICE_INFO:
2456 case SMB_FS_DEVICE_INFORMATION:
2458 SIVAL(pdata,0,0); /* dev type */
2459 SIVAL(pdata,4,0); /* characteristics */
2462 #ifdef HAVE_SYS_QUOTAS
2463 case SMB_FS_QUOTA_INFORMATION:
2465 * what we have to send --metze:
2467 * Unknown1: 24 NULL bytes
2468 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2469 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2470 * Quota Flags: 2 byte :
2471 * Unknown3: 6 NULL bytes
2475 * details for Quota Flags:
2477 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2478 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2479 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2480 * 0x0001 Enable Quotas: enable quota for this fs
2484 /* we need to fake up a fsp here,
2485 * because its not send in this call
2488 SMB_NTQUOTA_STRUCT quotas;
2491 ZERO_STRUCT(quotas);
2497 if (current_user.ut.uid != 0) {
2498 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2499 lp_servicename(SNUM(conn)),conn->user));
2500 return ERROR_DOS(ERRDOS,ERRnoaccess);
2503 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2504 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2505 return ERROR_DOS(ERRSRV,ERRerror);
2510 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2512 /* Unknown1 24 NULL bytes*/
2513 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2514 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2515 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2517 /* Default Soft Quota 8 bytes */
2518 SBIG_UINT(pdata,24,quotas.softlim);
2520 /* Default Hard Quota 8 bytes */
2521 SBIG_UINT(pdata,32,quotas.hardlim);
2523 /* Quota flag 2 bytes */
2524 SSVAL(pdata,40,quotas.qflags);
2526 /* Unknown3 6 NULL bytes */
2532 #endif /* HAVE_SYS_QUOTAS */
2533 case SMB_FS_OBJECTID_INFORMATION:
2535 unsigned char objid[16];
2536 memcpy(pdata,create_volume_objectid(conn, objid),16);
2542 * Query the version and capabilities of the CIFS UNIX extensions
2546 case SMB_QUERY_CIFS_UNIX_INFO:
2547 if (!lp_unix_extensions()) {
2548 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2551 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2552 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2553 /* We have POSIX ACLs, pathname and locking capability. */
2554 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2555 CIFS_UNIX_POSIX_ACLS_CAP|
2556 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2557 CIFS_UNIX_FCNTL_LOCKS_CAP|
2558 CIFS_UNIX_EXTATTR_CAP|
2559 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2560 /* Ensure we don't do this on signed or sealed data. */
2561 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2565 case SMB_QUERY_POSIX_FS_INFO:
2568 vfs_statvfs_struct svfs;
2570 if (!lp_unix_extensions()) {
2571 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2574 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2578 SIVAL(pdata,0,svfs.OptimalTransferSize);
2579 SIVAL(pdata,4,svfs.BlockSize);
2580 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2581 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2582 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2583 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2584 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2585 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2586 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2588 } else if (rc == EOPNOTSUPP) {
2589 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2590 #endif /* EOPNOTSUPP */
2592 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2593 return ERROR_DOS(ERRSRV,ERRerror);
2598 case SMB_QUERY_POSIX_WHOAMI:
2604 if (!lp_unix_extensions()) {
2605 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2608 if (max_data_bytes < 40) {
2609 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2612 /* We ARE guest if global_sid_Builtin_Guests is
2613 * in our list of SIDs.
2615 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2616 current_user.nt_user_token)) {
2617 flags |= SMB_WHOAMI_GUEST;
2620 /* We are NOT guest if global_sid_Authenticated_Users
2621 * is in our list of SIDs.
2623 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2624 current_user.nt_user_token)) {
2625 flags &= ~SMB_WHOAMI_GUEST;
2628 /* NOTE: 8 bytes for UID/GID, irrespective of native
2629 * platform size. This matches
2630 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2632 data_len = 4 /* flags */
2639 + 4 /* pad/reserved */
2640 + (current_user.ut.ngroups * 8)
2642 + (current_user.nt_user_token->num_sids *
2646 SIVAL(pdata, 0, flags);
2647 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2648 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2649 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2652 if (data_len >= max_data_bytes) {
2653 /* Potential overflow, skip the GIDs and SIDs. */
2655 SIVAL(pdata, 24, 0); /* num_groups */
2656 SIVAL(pdata, 28, 0); /* num_sids */
2657 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2658 SIVAL(pdata, 36, 0); /* reserved */
2664 SIVAL(pdata, 24, current_user.ut.ngroups);
2666 current_user.nt_user_token->num_sids);
2668 /* We walk the SID list twice, but this call is fairly
2669 * infrequent, and I don't expect that it's performance
2670 * sensitive -- jpeach
2672 for (i = 0, sid_bytes = 0;
2673 i < current_user.nt_user_token->num_sids; ++i) {
2675 sid_size(¤t_user.nt_user_token->user_sids[i]);
2678 /* SID list byte count */
2679 SIVAL(pdata, 32, sid_bytes);
2681 /* 4 bytes pad/reserved - must be zero */
2682 SIVAL(pdata, 36, 0);
2686 for (i = 0; i < current_user.ut.ngroups; ++i) {
2687 SBIG_UINT(pdata, data_len,
2688 (SMB_BIG_UINT)current_user.ut.groups[i]);
2694 i < current_user.nt_user_token->num_sids; ++i) {
2696 sid_size(¤t_user.nt_user_token->user_sids[i]);
2698 sid_linearize(pdata + data_len, sid_len,
2699 ¤t_user.nt_user_token->user_sids[i]);
2700 data_len += sid_len;
2706 case SMB_MAC_QUERY_FS_INFO:
2708 * Thursby MAC extension... ONLY on NTFS filesystems
2709 * once we do streams then we don't need this
2711 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2713 SIVAL(pdata,84,0x100); /* Don't support mac... */
2718 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2722 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2724 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2729 /****************************************************************************
2730 Reply to a TRANS2_SETFSINFO (set filesystem info).
2731 ****************************************************************************/
2733 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2734 char **pparams, int total_params, char **ppdata, int total_data,
2735 unsigned int max_data_bytes)
2737 char *pdata = *ppdata;
2738 char *params = *pparams;
2742 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2745 if (total_params < 4) {
2746 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2748 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2751 info_level = SVAL(params,2);
2753 switch(info_level) {
2754 case SMB_SET_CIFS_UNIX_INFO:
2756 uint16 client_unix_major;
2757 uint16 client_unix_minor;
2758 uint32 client_unix_cap_low;
2759 uint32 client_unix_cap_high;
2761 if (!lp_unix_extensions()) {
2762 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2765 /* There should be 12 bytes of capabilities set. */
2766 if (total_data < 8) {
2767 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2769 client_unix_major = SVAL(pdata,0);
2770 client_unix_minor = SVAL(pdata,2);
2771 client_unix_cap_low = IVAL(pdata,4);
2772 client_unix_cap_high = IVAL(pdata,8);
2773 /* Just print these values for now. */
2774 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2775 cap_low = 0x%x, cap_high = 0x%x\n",
2776 (unsigned int)client_unix_major,
2777 (unsigned int)client_unix_minor,
2778 (unsigned int)client_unix_cap_low,
2779 (unsigned int)client_unix_cap_high ));
2781 /* Here is where we must switch to posix pathname processing... */
2782 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2783 lp_set_posix_pathnames();
2784 mangle_change_to_posix();
2787 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2788 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2789 /* Client that knows how to do posix locks,
2790 * but not posix open/mkdir operations. Set a
2791 * default type for read/write checks. */
2793 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2798 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2801 size_t param_len = 0;
2802 size_t data_len = total_data;
2804 if (!lp_unix_extensions()) {
2805 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2808 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2810 status = srv_request_encryption_setup(conn,
2811 (unsigned char **)ppdata,
2813 (unsigned char **)pparams,
2817 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2818 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2819 } else if (!NT_STATUS_IS_OK(status)) {
2820 return ERROR_NT(status);
2823 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2825 if (NT_STATUS_IS_OK(status)) {
2826 /* Server-side transport encryption is now *on*. */
2827 status = srv_encryption_start(conn);
2828 if (!NT_STATUS_IS_OK(status)) {
2829 exit_server_cleanly("Failure in setting up encrypted transport");
2834 case SMB_FS_QUOTA_INFORMATION:
2836 files_struct *fsp = NULL;
2837 SMB_NTQUOTA_STRUCT quotas;
2839 ZERO_STRUCT(quotas);
2842 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2843 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2844 lp_servicename(SNUM(conn)),conn->user));
2845 return ERROR_DOS(ERRSRV,ERRaccess);
2848 /* note: normaly there're 48 bytes,
2849 * but we didn't use the last 6 bytes for now
2852 fsp = file_fsp(params,0);
2853 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2854 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2855 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2858 if (total_data < 42) {
2859 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2861 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2864 /* unknown_1 24 NULL bytes in pdata*/
2866 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2867 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2868 #ifdef LARGE_SMB_OFF_T
2869 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2870 #else /* LARGE_SMB_OFF_T */
2871 if ((IVAL(pdata,28) != 0)&&
2872 ((quotas.softlim != 0xFFFFFFFF)||
2873 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2874 /* more than 32 bits? */
2875 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2877 #endif /* LARGE_SMB_OFF_T */
2879 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2880 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2881 #ifdef LARGE_SMB_OFF_T
2882 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2883 #else /* LARGE_SMB_OFF_T */
2884 if ((IVAL(pdata,36) != 0)&&
2885 ((quotas.hardlim != 0xFFFFFFFF)||
2886 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2887 /* more than 32 bits? */
2888 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2890 #endif /* LARGE_SMB_OFF_T */
2892 /* quota_flags 2 bytes **/
2893 quotas.qflags = SVAL(pdata,40);
2895 /* unknown_2 6 NULL bytes follow*/
2897 /* now set the quotas */
2898 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2899 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2900 return ERROR_DOS(ERRSRV,ERRerror);
2906 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2908 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2913 * sending this reply works fine,
2914 * but I'm not sure it's the same
2915 * like windows do...
2918 outsize = set_message(inbuf, outbuf,10,0,True);
2923 #if defined(HAVE_POSIX_ACLS)
2924 /****************************************************************************
2925 Utility function to count the number of entries in a POSIX acl.
2926 ****************************************************************************/
2928 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2930 unsigned int ace_count = 0;
2931 int entry_id = SMB_ACL_FIRST_ENTRY;
2932 SMB_ACL_ENTRY_T entry;
2934 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2936 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2937 entry_id = SMB_ACL_NEXT_ENTRY;
2944 /****************************************************************************
2945 Utility function to marshall a POSIX acl into wire format.
2946 ****************************************************************************/
2948 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2950 int entry_id = SMB_ACL_FIRST_ENTRY;
2951 SMB_ACL_ENTRY_T entry;
2953 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2954 SMB_ACL_TAG_T tagtype;
2955 SMB_ACL_PERMSET_T permset;
2956 unsigned char perms = 0;
2957 unsigned int own_grp;
2960 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2961 entry_id = SMB_ACL_NEXT_ENTRY;
2964 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2965 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2969 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2970 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2974 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2975 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2976 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2978 SCVAL(pdata,1,perms);
2981 case SMB_ACL_USER_OBJ:
2982 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2983 own_grp = (unsigned int)pst->st_uid;
2984 SIVAL(pdata,2,own_grp);
2989 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2991 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2993 own_grp = (unsigned int)*puid;
2994 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2995 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2996 SIVAL(pdata,2,own_grp);
3000 case SMB_ACL_GROUP_OBJ:
3001 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3002 own_grp = (unsigned int)pst->st_gid;
3003 SIVAL(pdata,2,own_grp);
3008 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3010 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3012 own_grp = (unsigned int)*pgid;
3013 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3014 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3015 SIVAL(pdata,2,own_grp);
3020 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3021 SIVAL(pdata,2,0xFFFFFFFF);
3022 SIVAL(pdata,6,0xFFFFFFFF);
3025 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3026 SIVAL(pdata,2,0xFFFFFFFF);
3027 SIVAL(pdata,6,0xFFFFFFFF);
3030 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3033 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3040 /****************************************************************************
3041 Store the FILE_UNIX_BASIC info.
3042 ****************************************************************************/
3044 static char *store_file_unix_basic(connection_struct *conn,
3047 const SMB_STRUCT_STAT *psbuf)
3049 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3050 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3052 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3055 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3058 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3059 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3060 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3063 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3067 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3071 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3074 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3078 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3082 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3085 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3089 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3096 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3097 * the chflags(2) (or equivalent) flags.
3099 * XXX: this really should be behind the VFS interface. To do this, we would
3100 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3101 * Each VFS module could then implement it's own mapping as appropriate for the
3102 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3104 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3108 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3112 { UF_IMMUTABLE, EXT_IMMUTABLE },
3116 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3120 { UF_HIDDEN, EXT_HIDDEN },
3123 /* Do not remove. We need to guarantee that this array has at least one
3124 * entry to build on HP-UX.
3130 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3131 uint32 *smb_fflags, uint32 *smb_fmask)
3133 #ifdef HAVE_STAT_ST_FLAGS
3136 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3137 *smb_fmask |= info2_flags_map[i].smb_fflag;
3138 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3139 *smb_fflags |= info2_flags_map[i].smb_fflag;
3142 #endif /* HAVE_STAT_ST_FLAGS */
3145 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3146 const uint32 smb_fflags,
3147 const uint32 smb_fmask,
3150 #ifdef HAVE_STAT_ST_FLAGS
3151 uint32 max_fmask = 0;
3154 *stat_fflags = psbuf->st_flags;
3156 /* For each flags requested in smb_fmask, check the state of the
3157 * corresponding flag in smb_fflags and set or clear the matching
3161 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3162 max_fmask |= info2_flags_map[i].smb_fflag;
3163 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3164 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3165 *stat_fflags |= info2_flags_map[i].stat_fflag;
3167 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3172 /* If smb_fmask is asking to set any bits that are not supported by
3173 * our flag mappings, we should fail.
3175 if ((smb_fmask & max_fmask) != smb_fmask) {
3182 #endif /* HAVE_STAT_ST_FLAGS */
3186 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3187 * of file flags and birth (create) time.
3189 static char *store_file_unix_basic_info2(connection_struct *conn,
3192 const SMB_STRUCT_STAT *psbuf)
3194 uint32 file_flags = 0;
3195 uint32 flags_mask = 0;
3197 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3199 /* Create (birth) time 64 bit */
3200 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3203 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3204 SIVAL(pdata, 0, file_flags); /* flags */
3205 SIVAL(pdata, 4, flags_mask); /* mask */
3211 /****************************************************************************
3212 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3213 ****************************************************************************/
3215 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3216 unsigned int tran_call,
3217 char **pparams, int total_params, char **ppdata, int total_data,
3218 unsigned int max_data_bytes)
3220 char *params = *pparams;
3221 char *pdata = *ppdata;
3222 unsigned int data_size = 0;
3223 unsigned int param_size = 2;
3225 smb_np_struct *p_pipe = NULL;
3228 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3231 if (total_params < 4) {
3232 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3235 p_pipe = get_rpc_pipe_p(params,0);
3236 if (p_pipe == NULL) {
3237 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3240 info_level = SVAL(params,2);
3242 *pparams = (char *)SMB_REALLOC(*pparams,2);
3243 if (*pparams == NULL) {
3244 return ERROR_NT(NT_STATUS_NO_MEMORY);
3248 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3249 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3250 if (*ppdata == NULL ) {
3251 return ERROR_NT(NT_STATUS_NO_MEMORY);
3255 switch (info_level) {
3256 case SMB_FILE_STANDARD_INFORMATION:
3258 SOFF_T(pdata,0,4096LL);
3265 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3268 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3273 /****************************************************************************
3274 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3275 file name or file id).
3276 ****************************************************************************/
3278 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3279 unsigned int tran_call,
3280 char **pparams, int total_params, char **ppdata, int total_data,
3281 unsigned int max_data_bytes)
3283 char *params = *pparams;
3284 char *pdata = *ppdata;
3288 SMB_OFF_T file_size=0;
3289 SMB_BIG_UINT allocation_size=0;
3290 unsigned int data_size = 0;
3291 unsigned int param_size = 2;
3292 SMB_STRUCT_STAT sbuf;
3293 pstring fname, dos_fname;
3298 BOOL delete_pending = False;
3300 time_t create_time, mtime, atime;
3301 struct timespec create_time_ts, mtime_ts, atime_ts;
3302 files_struct *fsp = NULL;
3303 TALLOC_CTX *data_ctx = NULL;
3304 struct ea_list *ea_list = NULL;
3305 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3306 char *lock_data = NULL;
3309 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3313 if (tran_call == TRANSACT2_QFILEINFO) {
3314 if (total_params < 4) {
3315 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3319 return call_trans2qpipeinfo(conn,
3332 fsp = file_fsp(params,0);
3333 info_level = SVAL(params,2);
3335 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3337 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3338 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3341 if(fsp && (fsp->fake_file_handle)) {
3343 * This is actually for the QUOTA_FAKE_FILE --metze
3346 pstrcpy(fname, fsp->fsp_name);
3347 /* We know this name is ok, it's already passed the checks. */
3349 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3351 * This is actually a QFILEINFO on a directory
3352 * handle (returned from an NT SMB). NT5.0 seems
3353 * to do this call. JRA.
3355 /* We know this name is ok, it's already passed the checks. */
3356 pstrcpy(fname, fsp->fsp_name);
3358 if (INFO_LEVEL_IS_UNIX(info_level)) {
3359 /* Always do lstat for UNIX calls. */
3360 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3361 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3362 return UNIXERROR(ERRDOS,ERRbadpath);
3364 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3365 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3366 return UNIXERROR(ERRDOS,ERRbadpath);
3369 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3372 * Original code - this is an open file.
3374 CHECK_FSP(fsp,conn);
3376 pstrcpy(fname, fsp->fsp_name);
3377 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3378 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3379 return(UNIXERROR(ERRDOS,ERRbadfid));
3381 pos = fsp->fh->position_information;
3382 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3383 access_mask = fsp->access_mask;
3386 NTSTATUS status = NT_STATUS_OK;
3389 if (total_params < 7) {
3390 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3393 info_level = SVAL(params,0);
3395 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3397 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3398 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3401 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3402 if (!NT_STATUS_IS_OK(status)) {
3403 return ERROR_NT(status);
3406 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3407 if (!NT_STATUS_IS_OK(status)) {
3408 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3409 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3411 return ERROR_NT(status);
3414 status = unix_convert(conn, fname, False, NULL, &sbuf);
3415 if (!NT_STATUS_IS_OK(status)) {
3416 return ERROR_NT(status);
3418 status = check_name(conn, fname);
3419 if (!NT_STATUS_IS_OK(status)) {
3420 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3421 return ERROR_NT(status);
3424 if (INFO_LEVEL_IS_UNIX(info_level)) {
3425 /* Always do lstat for UNIX calls. */
3426 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3427 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3428 return UNIXERROR(ERRDOS,ERRbadpath);
3430 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3431 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3432 return UNIXERROR(ERRDOS,ERRbadpath);
3435 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3436 if (delete_pending) {
3437 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3441 nlink = sbuf.st_nlink;
3443 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3444 /* NTFS does not seem to count ".." */
3448 if ((nlink > 0) && delete_pending) {
3452 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3453 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3456 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3457 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3459 p = strrchr_m(fname,'/');
3465 mode = dos_mode(conn,fname,&sbuf);
3467 mode = FILE_ATTRIBUTE_NORMAL;
3469 fullpathname = fname;
3471 file_size = get_file_size(sbuf);
3473 /* Pull out any data sent here before we realloc. */
3474 switch (info_level) {
3475 case SMB_INFO_QUERY_EAS_FROM_LIST:
3477 /* Pull any EA list from the data portion. */
3480 if (total_data < 4) {
3481 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3483 ea_size = IVAL(pdata,0);
3485 if (total_data > 0 && ea_size != total_data) {
3486 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3487 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3488 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3491 if (!lp_ea_support(SNUM(conn))) {
3492 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3495 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3496 return ERROR_NT(NT_STATUS_NO_MEMORY);
3499 /* Pull out the list of names. */
3500 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3502 talloc_destroy(data_ctx);
3503 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3508 case SMB_QUERY_POSIX_LOCK:
3510 if (fsp == NULL || fsp->fh->fd == -1) {
3511 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3514 if (total_data != POSIX_LOCK_DATA_SIZE) {
3515 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3518 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3519 return ERROR_NT(NT_STATUS_NO_MEMORY);
3522 /* Copy the lock range data. */
3523 lock_data = (char *)TALLOC_MEMDUP(
3524 data_ctx, pdata, total_data);
3526 talloc_destroy(data_ctx);
3527 return ERROR_NT(NT_STATUS_NO_MEMORY);
3534 *pparams = (char *)SMB_REALLOC(*pparams,2);
3535 if (*pparams == NULL) {
3536 talloc_destroy(data_ctx);
3537 return ERROR_NT(NT_STATUS_NO_MEMORY);
3541 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3542 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3543 if (*ppdata == NULL ) {
3544 talloc_destroy(data_ctx);
3545 return ERROR_NT(NT_STATUS_NO_MEMORY);
3549 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3550 mtime_ts = get_mtimespec(&sbuf);
3551 atime_ts = get_atimespec(&sbuf);
3553 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3556 if (!null_timespec(fsp->pending_modtime)) {
3557 /* the pending modtime overrides the current modtime */
3558 mtime_ts = fsp->pending_modtime;
3561 /* Do we have this path open ? */
3562 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3563 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3564 /* the pending modtime overrides the current modtime */
3565 mtime_ts = fsp1->pending_modtime;
3567 if (fsp1 && fsp1->initial_allocation_size) {
3568 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3572 if (lp_dos_filetime_resolution(SNUM(conn))) {
3573 dos_filetime_timespec(&create_time_ts);
3574 dos_filetime_timespec(&mtime_ts);
3575 dos_filetime_timespec(&atime_ts);
3578 create_time = convert_timespec_to_time_t(create_time_ts);
3579 mtime = convert_timespec_to_time_t(mtime_ts);
3580 atime = convert_timespec_to_time_t(atime_ts);
3582 /* NT expects the name to be in an exact form of the *full*
3583 filename. See the trans2 torture test */
3584 if (strequal(base_name,".")) {
3585 pstrcpy(dos_fname, "\\");
3587 pstr_sprintf(dos_fname, "\\%s", fname);
3588 string_replace(dos_fname, '/', '\\');
3591 switch (info_level) {
3592 case SMB_INFO_STANDARD:
3593 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3595 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3596 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3597 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3598 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3599 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3600 SSVAL(pdata,l1_attrFile,mode);
3603 case SMB_INFO_QUERY_EA_SIZE:
3605 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3606 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3608 srv_put_dos_date2(pdata,0,create_time);
3609 srv_put_dos_date2(pdata,4,atime);
3610 srv_put_dos_date2(pdata,8,mtime); /* write time */
3611 SIVAL(pdata,12,(uint32)file_size);
3612 SIVAL(pdata,16,(uint32)allocation_size);
3613 SSVAL(pdata,20,mode);
3614 SIVAL(pdata,22,ea_size);
3618 case SMB_INFO_IS_NAME_VALID:
3619 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3620 if (tran_call == TRANSACT2_QFILEINFO) {
3621 /* os/2 needs this ? really ?*/
3622 return ERROR_DOS(ERRDOS,ERRbadfunc);
3628 case SMB_INFO_QUERY_EAS_FROM_LIST:
3630 size_t total_ea_len = 0;
3631 struct ea_list *ea_file_list = NULL;
3633 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3635 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3636 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3638 if (!ea_list || (total_ea_len > data_size)) {
3639 talloc_destroy(data_ctx);
3641 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3645 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3646 talloc_destroy(data_ctx);
3650 case SMB_INFO_QUERY_ALL_EAS:
3652 /* We have data_size bytes to put EA's into. */
3653 size_t total_ea_len = 0;
3655 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3657 data_ctx = talloc_init("ea_ctx");
3659 return ERROR_NT(NT_STATUS_NO_MEMORY);
3662 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3663 if (!ea_list || (total_ea_len > data_size)) {
3664 talloc_destroy(data_ctx);
3666 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3670 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3671 talloc_destroy(data_ctx);
3675 case SMB_FILE_BASIC_INFORMATION:
3676 case SMB_QUERY_FILE_BASIC_INFO:
3678 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3679 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3680 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3682 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3686 put_long_date_timespec(pdata,create_time_ts);
3687 put_long_date_timespec(pdata+8,atime_ts);
3688 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3689 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3690 SIVAL(pdata,32,mode);
3692 DEBUG(5,("SMB_QFBI - "));
3693 DEBUG(5,("create: %s ", ctime(&create_time)));
3694 DEBUG(5,("access: %s ", ctime(&atime)));
3695 DEBUG(5,("write: %s ", ctime(&mtime)));
3696 DEBUG(5,("change: %s ", ctime(&mtime)));
3697 DEBUG(5,("mode: %x\n", mode));
3700 case SMB_FILE_STANDARD_INFORMATION:
3701 case SMB_QUERY_FILE_STANDARD_INFO:
3703 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3705 SOFF_T(pdata,0,allocation_size);
3706 SOFF_T(pdata,8,file_size);
3707 SIVAL(pdata,16,nlink);
3708 SCVAL(pdata,20,delete_pending?1:0);
3709 SCVAL(pdata,21,(mode&aDIR)?1:0);
3710 SSVAL(pdata,22,0); /* Padding. */
3713 case SMB_FILE_EA_INFORMATION:
3714 case SMB_QUERY_FILE_EA_INFO:
3716 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3717 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3719 SIVAL(pdata,0,ea_size);
3723 /* Get the 8.3 name - used if NT SMB was negotiated. */
3724 case SMB_QUERY_FILE_ALT_NAME_INFO:
3725 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3729 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3730 pstrcpy(short_name,base_name);
3731 /* Mangle if not already 8.3 */
3732 if(!mangle_is_8_3(short_name, True, conn->params)) {
3733 mangle_map(short_name,True,True,conn->params);
3735 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3736 data_size = 4 + len;
3741 case SMB_QUERY_FILE_NAME_INFO:
3743 this must be *exactly* right for ACLs on mapped drives to work
3745 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3746 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3747 data_size = 4 + len;
3751 case SMB_FILE_ALLOCATION_INFORMATION:
3752 case SMB_QUERY_FILE_ALLOCATION_INFO:
3753 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3755 SOFF_T(pdata,0,allocation_size);
3758 case SMB_FILE_END_OF_FILE_INFORMATION:
3759 case SMB_QUERY_FILE_END_OF_FILEINFO:
3760 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3762 SOFF_T(pdata,0,file_size);
3765 case SMB_QUERY_FILE_ALL_INFO:
3766 case SMB_FILE_ALL_INFORMATION:
3768 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3769 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3770 put_long_date_timespec(pdata,create_time_ts);
3771 put_long_date_timespec(pdata+8,atime_ts);
3772 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3773 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3774 SIVAL(pdata,32,mode);
3775 SIVAL(pdata,36,0); /* padding. */
3777 SOFF_T(pdata,0,allocation_size);
3778 SOFF_T(pdata,8,file_size);
3779 SIVAL(pdata,16,nlink);
3780 SCVAL(pdata,20,delete_pending);
3781 SCVAL(pdata,21,(mode&aDIR)?1:0);
3784 SIVAL(pdata,0,ea_size);
3785 pdata += 4; /* EA info */
3786 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3789 data_size = PTR_DIFF(pdata,(*ppdata));
3792 case SMB_FILE_INTERNAL_INFORMATION:
3793 /* This should be an index number - looks like
3796 I think this causes us to fail the IFSKIT
3797 BasicFileInformationTest. -tpot */
3799 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3800 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3801 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3805 case SMB_FILE_ACCESS_INFORMATION:
3806 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3807 SIVAL(pdata,0,access_mask);
3811 case SMB_FILE_NAME_INFORMATION:
3812 /* Pathname with leading '\'. */
3815 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3816 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3817 SIVAL(pdata,0,byte_len);
3818 data_size = 4 + byte_len;
3822 case SMB_FILE_DISPOSITION_INFORMATION:
3823 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3825 SCVAL(pdata,0,delete_pending);
3828 case SMB_FILE_POSITION_INFORMATION:
3829 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3831 SOFF_T(pdata,0,pos);
3834 case SMB_FILE_MODE_INFORMATION:
3835 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3836 SIVAL(pdata,0,mode);
3840 case SMB_FILE_ALIGNMENT_INFORMATION:
3841 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3842 SIVAL(pdata,0,0); /* No alignment needed. */
3848 * NT4 server just returns "invalid query" to this - if we try to answer
3849 * it then NTws gets a BSOD! (tridge).
3850 * W2K seems to want this. JRA.
3852 case SMB_QUERY_FILE_STREAM_INFO:
3854 case SMB_FILE_STREAM_INFORMATION:
3855 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3859 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3860 SIVAL(pdata,0,0); /* ??? */
3861 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3862 SOFF_T(pdata,8,file_size);
3863 SOFF_T(pdata,16,allocation_size);
3864 data_size = 24 + byte_len;
3868 case SMB_QUERY_COMPRESSION_INFO:
3869 case SMB_FILE_COMPRESSION_INFORMATION:
3870 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3871 SOFF_T(pdata,0,file_size);
3872 SIVAL(pdata,8,0); /* ??? */
3873 SIVAL(pdata,12,0); /* ??? */
3877 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3878 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3879 put_long_date_timespec(pdata,create_time_ts);
3880 put_long_date_timespec(pdata+8,atime_ts);
3881 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3882 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3883 SOFF_T(pdata,32,allocation_size);
3884 SOFF_T(pdata,40,file_size);
3885 SIVAL(pdata,48,mode);
3886 SIVAL(pdata,52,0); /* ??? */
3890 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3891 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3892 SIVAL(pdata,0,mode);
3898 * CIFS UNIX Extensions.
3901 case SMB_QUERY_FILE_UNIX_BASIC:
3903 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3904 data_size = PTR_DIFF(pdata,(*ppdata));
3908 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3910 for (i=0; i<100; i++)
3911 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3917 case SMB_QUERY_FILE_UNIX_INFO2:
3919 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3920 data_size = PTR_DIFF(pdata,(*ppdata));
3924 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3926 for (i=0; i<100; i++)
3927 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3933 case SMB_QUERY_FILE_UNIX_LINK:
3937 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3939 if(!S_ISLNK(sbuf.st_mode))
3940 return(UNIXERROR(ERRSRV,ERRbadlink));
3942 return(UNIXERROR(ERRDOS,ERRbadlink));
3944 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3946 return(UNIXERROR(ERRDOS,ERRnoaccess));
3948 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3950 data_size = PTR_DIFF(pdata,(*ppdata));
3955 #if defined(HAVE_POSIX_ACLS)
3956 case SMB_QUERY_POSIX_ACL:
3958 SMB_ACL_T file_acl = NULL;
3959 SMB_ACL_T def_acl = NULL;
3960 uint16 num_file_acls = 0;
3961 uint16 num_def_acls = 0;
3963 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3964 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3966 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3969 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3970 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3972 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3975 if (S_ISDIR(sbuf.st_mode)) {
3976 if (fsp && fsp->is_directory) {
3977 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3979 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3981 def_acl = free_empty_sys_acl(conn, def_acl);
3984 num_file_acls = count_acl_entries(conn, file_acl);
3985 num_def_acls = count_acl_entries(conn, def_acl);
3987 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3988 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3990 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3991 SMB_POSIX_ACL_HEADER_SIZE) ));
3993 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3996 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3998 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4001 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4002 SSVAL(pdata,2,num_file_acls);
4003 SSVAL(pdata,4,num_def_acls);
4004 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4006 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4009 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4011 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4013 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4015 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4018 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4020 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4024 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4027 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4029 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4035 case SMB_QUERY_POSIX_LOCK:
4037 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4039 SMB_BIG_UINT offset;
4041 enum brl_type lock_type;
4043 if (total_data != POSIX_LOCK_DATA_SIZE) {
4044 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4047 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4048 case POSIX_LOCK_TYPE_READ:
4049 lock_type = READ_LOCK;
4051 case POSIX_LOCK_TYPE_WRITE:
4052 lock_type = WRITE_LOCK;
4054 case POSIX_LOCK_TYPE_UNLOCK:
4056 /* There's no point in asking for an unlock... */
4057 talloc_destroy(data_ctx);
4058 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4061 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4062 #if defined(HAVE_LONGLONG)
4063 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4064 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4065 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4066 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4067 #else /* HAVE_LONGLONG */
4068 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4069 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4070 #endif /* HAVE_LONGLONG */
4072 status = query_lock(fsp,
4079 if (ERROR_WAS_LOCK_DENIED(status)) {
4080 /* Here we need to report who has it locked... */
4081 data_size = POSIX_LOCK_DATA_SIZE;
4083 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4084 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4085 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4086 #if defined(HAVE_LONGLONG)
4087 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4088 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4089 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4090 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4091 #else /* HAVE_LONGLONG */
4092 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4093 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4094 #endif /* HAVE_LONGLONG */
4096 } else if (NT_STATUS_IS_OK(status)) {
4097 /* For success we just return a copy of what we sent
4098 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4099 data_size = POSIX_LOCK_DATA_SIZE;
4100 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4101 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4103 return ERROR_NT(status);
4109 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4112 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4117 /****************************************************************************
4118 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4120 ****************************************************************************/
4122 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4124 SMB_STRUCT_STAT sbuf1, sbuf2;
4125 pstring last_component_oldname;
4126 pstring last_component_newname;
4127 NTSTATUS status = NT_STATUS_OK;
4132 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4133 if (!NT_STATUS_IS_OK(status)) {
4137 status = check_name(conn, oldname);
4138 if (!NT_STATUS_IS_OK(status)) {
4142 /* source must already exist. */
4143 if (!VALID_STAT(sbuf1)) {
4144 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4147 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4148 if (!NT_STATUS_IS_OK(status)) {
4152 status = check_name(conn, newname);
4153 if (!NT_STATUS_IS_OK(status)) {
4157 /* Disallow if newname already exists. */
4158 if (VALID_STAT(sbuf2)) {
4159 return NT_STATUS_OBJECT_NAME_COLLISION;
4162 /* No links from a directory. */
4163 if (S_ISDIR(sbuf1.st_mode)) {
4164 return NT_STATUS_FILE_IS_A_DIRECTORY;
4167 /* Ensure this is within the share. */
4168 status = reduce_name(conn, oldname);
4169 if (!NT_STATUS_IS_OK(status)) {
4173 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4175 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4176 status = map_nt_error_from_unix(errno);
4177 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4178 nt_errstr(status), newname, oldname));
4184 /****************************************************************************
4185 Deal with setting the time from any of the setfilepathinfo functions.
4186 ****************************************************************************/
4188 static NTSTATUS smb_set_file_time(connection_struct *conn,
4191 const SMB_STRUCT_STAT *psbuf,
4192 struct timespec ts[2])
4195 FILE_NOTIFY_CHANGE_LAST_ACCESS
4196 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4199 if (!VALID_STAT(*psbuf)) {
4200 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4203 /* get some defaults (no modifications) if any info is zero or -1. */
4204 if (null_timespec(ts[0])) {
4205 ts[0] = get_atimespec(psbuf);
4206 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4209 if (null_timespec(ts[1])) {
4210 ts[1] = get_mtimespec(psbuf);
4211 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4214 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4215 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4218 * Try and set the times of this file if
4219 * they are different from the current values.
4223 struct timespec mts = get_mtimespec(psbuf);
4224 struct timespec ats = get_atimespec(psbuf);
4225 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4226 return NT_STATUS_OK;
4232 * This was a setfileinfo on an open file.
4233 * NT does this a lot. We also need to
4234 * set the time here, as it can be read by
4235 * FindFirst/FindNext and with the patch for bug #2045
4236 * in smbd/fileio.c it ensures that this timestamp is
4237 * kept sticky even after a write. We save the request
4238 * away and will set it on file close and after a write. JRA.
4241 if (!null_timespec(ts[1])) {
4242 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4243 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4244 fsp_set_pending_modtime(fsp, ts[1]);
4248 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4250 if(file_ntimes(conn, fname, ts)!=0) {
4251 return map_nt_error_from_unix(errno);
4254 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4256 return NT_STATUS_OK;
4259 /****************************************************************************
4260 Deal with setting the dosmode from any of the setfilepathinfo functions.
4261 ****************************************************************************/
4263 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4265 SMB_STRUCT_STAT *psbuf,
4268 if (!VALID_STAT(*psbuf)) {
4269 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4273 if (S_ISDIR(psbuf->st_mode)) {
4280 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4282 /* check the mode isn't different, before changing it */
4283 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4285 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4286 fname, (unsigned int)dosmode ));
4288 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4289 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4290 fname, strerror(errno)));
4291 return map_nt_error_from_unix(errno);
4294 return NT_STATUS_OK;
4297 /****************************************************************************
4298 Deal with setting the size from any of the setfilepathinfo functions.
4299 ****************************************************************************/
4301 static NTSTATUS smb_set_file_size(connection_struct *conn,
4304 SMB_STRUCT_STAT *psbuf,
4307 NTSTATUS status = NT_STATUS_OK;
4308 files_struct *new_fsp = NULL;
4310 if (!VALID_STAT(*psbuf)) {
4311 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4314 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4316 if (size == get_file_size(*psbuf)) {
4317 return NT_STATUS_OK;
4320 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4321 fname, (double)size ));
4323 if (fsp && fsp->fh->fd != -1) {
4324 /* Handle based call. */
4325 if (vfs_set_filelen(fsp, size) == -1) {
4326 return map_nt_error_from_unix(errno);
4328 return NT_STATUS_OK;
4331 status = open_file_ntcreate(conn, fname, psbuf,
4333 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4336 FILE_ATTRIBUTE_NORMAL,
4337 FORCE_OPLOCK_BREAK_TO_NONE,
4340 if (!NT_STATUS_IS_OK(status)) {
4341 /* NB. We check for open_was_deferred in the caller. */
4345 if (vfs_set_filelen(new_fsp, size) == -1) {
4346 status = map_nt_error_from_unix(errno);
4347 close_file(new_fsp,NORMAL_CLOSE);
4351 close_file(new_fsp,NORMAL_CLOSE);
4352 return NT_STATUS_OK;
4355 /****************************************************************************
4356 Deal with SMB_INFO_SET_EA.
4357 ****************************************************************************/
4359 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4365 struct ea_list *ea_list = NULL;
4366 TALLOC_CTX *ctx = NULL;
4367 NTSTATUS status = NT_STATUS_OK;
4369 if (total_data < 10) {
4371 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4372 length. They seem to have no effect. Bug #3212. JRA */
4374 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4375 /* We're done. We only get EA info in this call. */
4376 return NT_STATUS_OK;
4379 return NT_STATUS_INVALID_PARAMETER;
4382 if (IVAL(pdata,0) > total_data) {
4383 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4384 IVAL(pdata,0), (unsigned int)total_data));
4385 return NT_STATUS_INVALID_PARAMETER;
4388 ctx = talloc_init("SMB_INFO_SET_EA");
4390 return NT_STATUS_NO_MEMORY;
4392 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4394 talloc_destroy(ctx);
4395 return NT_STATUS_INVALID_PARAMETER;
4397 status = set_ea(conn, fsp, fname, ea_list);
4398 talloc_destroy(ctx);
4403 /****************************************************************************
4404 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4405 ****************************************************************************/
4407 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4412 SMB_STRUCT_STAT *psbuf)
4414 NTSTATUS status = NT_STATUS_OK;
4415 BOOL delete_on_close;
4418 if (total_data < 1) {
4419 return NT_STATUS_INVALID_PARAMETER;
4423 return NT_STATUS_INVALID_HANDLE;
4426 delete_on_close = (CVAL(pdata,0) ? True : False);
4427 dosmode = dos_mode(conn, fname, psbuf);
4429 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4430 "delete_on_close = %u\n",
4432 (unsigned int)dosmode,
4433 (unsigned int)delete_on_close ));
4435 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4437 if (!NT_STATUS_IS_OK(status)) {
4441 /* The set is across all open files on this dev/inode pair. */
4442 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4443 return NT_STATUS_ACCESS_DENIED;
4445 return NT_STATUS_OK;
4448 /****************************************************************************
4449 Deal with SMB_FILE_POSITION_INFORMATION.
4450 ****************************************************************************/
4452 static NTSTATUS smb_file_position_information(connection_struct *conn,
4457 SMB_BIG_UINT position_information;
4459 if (total_data < 8) {
4460 return NT_STATUS_INVALID_PARAMETER;
4464 /* Ignore on pathname based set. */
4465 return NT_STATUS_OK;
4468 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4469 #ifdef LARGE_SMB_OFF_T
4470 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4471 #else /* LARGE_SMB_OFF_T */
4472 if (IVAL(pdata,4) != 0) {
4473 /* more than 32 bits? */
4474 return NT_STATUS_INVALID_PARAMETER;
4476 #endif /* LARGE_SMB_OFF_T */
4478 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4479 fsp->fsp_name, (double)position_information ));
4480 fsp->fh->position_information = position_information;
4481 return NT_STATUS_OK;
4484 /****************************************************************************
4485 Deal with SMB_FILE_MODE_INFORMATION.
4486 ****************************************************************************/
4488 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4494 if (total_data < 4) {
4495 return NT_STATUS_INVALID_PARAMETER;
4497 mode = IVAL(pdata,0);
4498 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4499 return NT_STATUS_INVALID_PARAMETER;
4501 return NT_STATUS_OK;
4504 /****************************************************************************
4505 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4506 ****************************************************************************/
4508 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4514 pstring link_target;
4515 const char *newname = fname;
4516 NTSTATUS status = NT_STATUS_OK;
4518 /* Set a symbolic link. */
4519 /* Don't allow this if follow links is false. */
4521 if (total_data == 0) {
4522 return NT_STATUS_INVALID_PARAMETER;
4525 if (!lp_symlinks(SNUM(conn))) {
4526 return NT_STATUS_ACCESS_DENIED;
4529 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4531 /* !widelinks forces the target path to be within the share. */
4532 /* This means we can interpret the target as a pathname. */
4533 if (!lp_widelinks(SNUM(conn))) {
4535 char *last_dirp = NULL;
4537 if (*link_target == '/') {
4538 /* No absolute paths allowed. */
4539 return NT_STATUS_ACCESS_DENIED;
4541 pstrcpy(rel_name, newname);
4542 last_dirp = strrchr_m(rel_name, '/');
4544 last_dirp[1] = '\0';
4546 pstrcpy(rel_name, "./");
4548 pstrcat(rel_name, link_target);
4550 status = check_name(conn, rel_name);
4551 if (!NT_STATUS_IS_OK(status)) {
4556 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4557 newname, link_target ));
4559 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4560 return map_nt_error_from_unix(errno);
4563 return NT_STATUS_OK;
4566 /****************************************************************************
4567 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4568 ****************************************************************************/
4570 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4578 NTSTATUS status = NT_STATUS_OK;
4580 /* Set a hard link. */
4581 if (total_data == 0) {
4582 return NT_STATUS_INVALID_PARAMETER;
4585 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4586 if (!NT_STATUS_IS_OK(status)) {
4590 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4591 if (!NT_STATUS_IS_OK(status)) {
4595 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4598 return hardlink_internals(conn, oldname, fname);
4601 /****************************************************************************
4602 Deal with SMB_FILE_RENAME_INFORMATION.
4603 ****************************************************************************/
4605 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4614 /* uint32 root_fid; */ /* Not used */
4618 BOOL dest_has_wcard = False;
4619 NTSTATUS status = NT_STATUS_OK;
4622 if (total_data < 13) {
4623 return NT_STATUS_INVALID_PARAMETER;
4626 overwrite = (CVAL(pdata,0) ? True : False);
4627 /* root_fid = IVAL(pdata,4); */
4628 len = IVAL(pdata,8);
4630 if (len > (total_data - 12) || (len == 0)) {
4631 return NT_STATUS_INVALID_PARAMETER;
4634 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4635 if (!NT_STATUS_IS_OK(status)) {
4639 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4640 if (!NT_STATUS_IS_OK(status)) {
4644 /* Check the new name has no '/' characters. */
4645 if (strchr_m(newname, '/')) {
4646 return NT_STATUS_NOT_SUPPORTED;
4649 /* Create the base directory. */
4650 pstrcpy(base_name, fname);
4651 p = strrchr_m(base_name, '/');
4655 pstrcpy(base_name, "./");
4657 /* Append the new name. */
4658 pstrcat(base_name, newname);
4661 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4662 fsp->fnum, fsp->fsp_name, base_name ));
4663 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4665 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4667 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4673 /****************************************************************************
4674 Deal with SMB_SET_POSIX_ACL.
4675 ****************************************************************************/
4677 #if defined(HAVE_POSIX_ACLS)
4678 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4683 SMB_STRUCT_STAT *psbuf)
4685 uint16 posix_acl_version;
4686 uint16 num_file_acls;
4687 uint16 num_def_acls;
4688 BOOL valid_file_acls = True;
4689 BOOL valid_def_acls = True;
4691 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4692 return NT_STATUS_INVALID_PARAMETER;
4694 posix_acl_version = SVAL(pdata,0);
4695 num_file_acls = SVAL(pdata,2);
4696 num_def_acls = SVAL(pdata,4);
4698 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4699 valid_file_acls = False;
4703 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4704 valid_def_acls = False;
4708 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4709 return NT_STATUS_INVALID_PARAMETER;
4712 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4713 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4714 return NT_STATUS_INVALID_PARAMETER;
4717 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4718 fname ? fname : fsp->fsp_name,
4719 (unsigned int)num_file_acls,
4720 (unsigned int)num_def_acls));
4722 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4723 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4724 return map_nt_error_from_unix(errno);
4727 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4728 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4729 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4730 return map_nt_error_from_unix(errno);
4732 return NT_STATUS_OK;
4736 /****************************************************************************
4737 Deal with SMB_SET_POSIX_LOCK.
4738 ****************************************************************************/
4740 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4748 SMB_BIG_UINT offset;
4750 BOOL blocking_lock = False;
4751 enum brl_type lock_type;
4752 NTSTATUS status = NT_STATUS_OK;
4754 if (fsp == NULL || fsp->fh->fd == -1) {
4755 return NT_STATUS_INVALID_HANDLE;
4758 if (total_data != POSIX_LOCK_DATA_SIZE) {
4759 return NT_STATUS_INVALID_PARAMETER;
4762 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4763 case POSIX_LOCK_TYPE_READ:
4764 lock_type = READ_LOCK;
4766 case POSIX_LOCK_TYPE_WRITE:
4767 /* Return the right POSIX-mappable error code for files opened read-only. */
4768 if (!fsp->can_write) {
4769 return NT_STATUS_INVALID_HANDLE;
4771 lock_type = WRITE_LOCK;
4773 case POSIX_LOCK_TYPE_UNLOCK:
4774 lock_type = UNLOCK_LOCK;
4777 return NT_STATUS_INVALID_PARAMETER;
4780 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4781 blocking_lock = False;
4782 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4783 blocking_lock = True;
4785 return NT_STATUS_INVALID_PARAMETER;
4788 if (!lp_blocking_locks(SNUM(conn))) {
4789 blocking_lock = False;
4792 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4793 #if defined(HAVE_LONGLONG)
4794 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4795 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4796 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4797 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4798 #else /* HAVE_LONGLONG */
4799 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4800 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4801 #endif /* HAVE_LONGLONG */
4803 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4804 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4806 (unsigned int)lock_type,
4807 (unsigned int)lock_pid,
4811 if (lock_type == UNLOCK_LOCK) {
4812 status = do_unlock(smbd_messaging_context(),
4819 uint32 block_smbpid;
4821 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4832 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4834 * A blocking lock was requested. Package up
4835 * this smb into a queued request and push it
4836 * onto the blocking lock queue.
4838 if(push_blocking_lock_request(br_lck,
4841 -1, /* infinite timeout. */
4849 TALLOC_FREE(br_lck);
4853 TALLOC_FREE(br_lck);
4859 /****************************************************************************
4860 Deal with SMB_INFO_STANDARD.
4861 ****************************************************************************/
4863 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4868 const SMB_STRUCT_STAT *psbuf)
4870 struct timespec ts[2];
4872 if (total_data < 12) {
4873 return NT_STATUS_INVALID_PARAMETER;
4877 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4879 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4881 DEBUG(10,("smb_set_info_standard: file %s\n",
4882 fname ? fname : fsp->fsp_name ));
4884 return smb_set_file_time(conn,
4891 /****************************************************************************
4892 Deal with SMB_SET_FILE_BASIC_INFO.
4893 ****************************************************************************/
4895 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4900 SMB_STRUCT_STAT *psbuf)
4902 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4903 struct timespec write_time;
4904 struct timespec changed_time;
4906 struct timespec ts[2];
4907 NTSTATUS status = NT_STATUS_OK;
4909 if (total_data < 36) {
4910 return NT_STATUS_INVALID_PARAMETER;
4913 /* Set the attributes */
4914 dosmode = IVAL(pdata,32);
4915 status = smb_set_file_dosmode(conn,
4919 if (!NT_STATUS_IS_OK(status)) {
4923 /* Ignore create time at offset pdata. */
4926 ts[0] = interpret_long_date(pdata+8);
4928 write_time = interpret_long_date(pdata+16);
4929 changed_time = interpret_long_date(pdata+24);
4932 ts[1] = timespec_min(&write_time, &changed_time);
4934 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4938 /* Prefer a defined time to an undefined one. */
4939 if (null_timespec(ts[1])) {
4940 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4943 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4944 fname ? fname : fsp->fsp_name ));
4946 return smb_set_file_time(conn,
4953 /****************************************************************************
4954 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4955 ****************************************************************************/
4957 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4962 SMB_STRUCT_STAT *psbuf)
4964 SMB_BIG_UINT allocation_size = 0;
4965 NTSTATUS status = NT_STATUS_OK;
4966 files_struct *new_fsp = NULL;
4968 if (!VALID_STAT(*psbuf)) {
4969 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4972 if (total_data < 8) {
4973 return NT_STATUS_INVALID_PARAMETER;
4976 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4977 #ifdef LARGE_SMB_OFF_T
4978 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4979 #else /* LARGE_SMB_OFF_T */
4980 if (IVAL(pdata,4) != 0) {
4981 /* more than 32 bits? */
4982 return NT_STATUS_INVALID_PARAMETER;
4984 #endif /* LARGE_SMB_OFF_T */
4986 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4987 fname, (double)allocation_size ));
4989 if (allocation_size) {
4990 allocation_size = smb_roundup(conn, allocation_size);
4993 if(allocation_size == get_file_size(*psbuf)) {
4994 return NT_STATUS_OK;
4997 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4998 fname, (double)allocation_size ));
5000 if (fsp && fsp->fh->fd != -1) {
5001 /* Open file handle. */
5002 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5003 return map_nt_error_from_unix(errno);
5005 return NT_STATUS_OK;
5008 /* Pathname or stat or directory file. */
5010 status = open_file_ntcreate(conn, fname, psbuf,
5012 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5015 FILE_ATTRIBUTE_NORMAL,
5016 FORCE_OPLOCK_BREAK_TO_NONE,
5019 if (!NT_STATUS_IS_OK(status)) {
5020 /* NB. We check for open_was_deferred in the caller. */
5023 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5024 status = map_nt_error_from_unix(errno);
5025 close_file(new_fsp,NORMAL_CLOSE);
5029 close_file(new_fsp,NORMAL_CLOSE);
5030 return NT_STATUS_OK;
5033 /****************************************************************************
5034 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5035 ****************************************************************************/
5037 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5042 SMB_STRUCT_STAT *psbuf)
5046 if (total_data < 8) {
5047 return NT_STATUS_INVALID_PARAMETER;
5050 size = IVAL(pdata,0);
5051 #ifdef LARGE_SMB_OFF_T
5052 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5053 #else /* LARGE_SMB_OFF_T */
5054 if (IVAL(pdata,4) != 0) {
5055 /* more than 32 bits? */
5056 return NT_STATUS_INVALID_PARAMETER;
5058 #endif /* LARGE_SMB_OFF_T */
5059 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5060 "file %s to %.0f\n", fname, (double)size ));
5062 return smb_set_file_size(conn,
5069 /****************************************************************************
5070 Allow a UNIX info mknod.
5071 ****************************************************************************/
5073 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5077 SMB_STRUCT_STAT *psbuf)
5079 uint32 file_type = IVAL(pdata,56);
5080 #if defined(HAVE_MAKEDEV)
5081 uint32 dev_major = IVAL(pdata,60);
5082 uint32 dev_minor = IVAL(pdata,68);
5084 SMB_DEV_T dev = (SMB_DEV_T)0;
5085 uint32 raw_unixmode = IVAL(pdata,84);
5089 if (total_data < 100) {
5090 return NT_STATUS_INVALID_PARAMETER;
5093 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5094 if (!NT_STATUS_IS_OK(status)) {
5098 #if defined(HAVE_MAKEDEV)
5099 dev = makedev(dev_major, dev_minor);
5102 switch (file_type) {
5103 #if defined(S_IFIFO)
5104 case UNIX_TYPE_FIFO:
5105 unixmode |= S_IFIFO;
5108 #if defined(S_IFSOCK)
5109 case UNIX_TYPE_SOCKET:
5110 unixmode |= S_IFSOCK;
5113 #if defined(S_IFCHR)
5114 case UNIX_TYPE_CHARDEV:
5115 unixmode |= S_IFCHR;
5118 #if defined(S_IFBLK)
5119 case UNIX_TYPE_BLKDEV:
5120 unixmode |= S_IFBLK;
5124 return NT_STATUS_INVALID_PARAMETER;
5127 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5128 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5130 /* Ok - do the mknod. */
5131 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5132 return map_nt_error_from_unix(errno);
5135 /* If any of the other "set" calls fail we
5136 * don't want to end up with a half-constructed mknod.
5139 if (lp_inherit_perms(SNUM(conn))) {
5141 conn, parent_dirname(fname),
5145 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5146 status = map_nt_error_from_unix(errno);
5147 SMB_VFS_UNLINK(conn,fname);
5150 return NT_STATUS_OK;
5153 /****************************************************************************
5154 Deal with SMB_SET_FILE_UNIX_BASIC.
5155 ****************************************************************************/
5157 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5162 SMB_STRUCT_STAT *psbuf)
5164 struct timespec ts[2];
5165 uint32 raw_unixmode;
5168 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5169 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5170 NTSTATUS status = NT_STATUS_OK;
5171 BOOL delete_on_fail = False;
5172 enum perm_type ptype;
5174 if (total_data < 100) {
5175 return NT_STATUS_INVALID_PARAMETER;
5178 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5179 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5180 size=IVAL(pdata,0); /* first 8 Bytes are size */
5181 #ifdef LARGE_SMB_OFF_T
5182 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5183 #else /* LARGE_SMB_OFF_T */
5184 if (IVAL(pdata,4) != 0) {
5185 /* more than 32 bits? */
5186 return NT_STATUS_INVALID_PARAMETER;
5188 #endif /* LARGE_SMB_OFF_T */
5191 ts[0] = interpret_long_date(pdata+24); /* access_time */
5192 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5193 set_owner = (uid_t)IVAL(pdata,40);
5194 set_grp = (gid_t)IVAL(pdata,48);
5195 raw_unixmode = IVAL(pdata,84);
5197 if (VALID_STAT(*psbuf)) {
5198 if (S_ISDIR(psbuf->st_mode)) {
5199 ptype = PERM_EXISTING_DIR;
5201 ptype = PERM_EXISTING_FILE;
5204 ptype = PERM_NEW_FILE;
5207 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5208 if (!NT_STATUS_IS_OK(status)) {
5212 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5213 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5214 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5216 if (!VALID_STAT(*psbuf)) {
5218 * The only valid use of this is to create character and block
5219 * devices, and named pipes. This is deprecated (IMHO) and
5220 * a new info level should be used for mknod. JRA.
5223 status = smb_unix_mknod(conn,
5228 if (!NT_STATUS_IS_OK(status)) {
5232 /* Ensure we don't try and change anything else. */
5233 raw_unixmode = SMB_MODE_NO_CHANGE;
5234 size = get_file_size(*psbuf);
5235 ts[0] = get_atimespec(psbuf);
5236 ts[1] = get_mtimespec(psbuf);
5238 * We continue here as we might want to change the
5241 delete_on_fail = True;
5245 /* Horrible backwards compatibility hack as an old server bug
5246 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5250 size = get_file_size(*psbuf);
5255 * Deal with the UNIX specific mode set.
5258 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5259 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5260 (unsigned int)unixmode, fname ));
5261 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5262 return map_nt_error_from_unix(errno);
5267 * Deal with the UNIX specific uid set.
5270 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5273 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5274 (unsigned int)set_owner, fname ));
5276 if (S_ISLNK(psbuf->st_mode)) {
5277 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5279 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5283 status = map_nt_error_from_unix(errno);
5284 if (delete_on_fail) {
5285 SMB_VFS_UNLINK(conn,fname);
5292 * Deal with the UNIX specific gid set.
5295 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5296 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5297 (unsigned int)set_owner, fname ));
5298 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5299 status = map_nt_error_from_unix(errno);
5300 if (delete_on_fail) {
5301 SMB_VFS_UNLINK(conn,fname);
5307 /* Deal with any size changes. */
5309 status = smb_set_file_size(conn,
5314 if (!NT_STATUS_IS_OK(status)) {
5318 /* Deal with any time changes. */
5320 return smb_set_file_time(conn,
5327 /****************************************************************************
5328 Deal with SMB_SET_FILE_UNIX_INFO2.
5329 ****************************************************************************/
5331 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5336 SMB_STRUCT_STAT *psbuf)
5342 if (total_data < 116) {
5343 return NT_STATUS_INVALID_PARAMETER;
5346 /* Start by setting all the fields that are common between UNIX_BASIC
5349 status = smb_set_file_unix_basic(conn, pdata, total_data,
5351 if (!NT_STATUS_IS_OK(status)) {
5355 smb_fflags = IVAL(pdata, 108);
5356 smb_fmask = IVAL(pdata, 112);
5358 /* NB: We should only attempt to alter the file flags if the client
5359 * sends a non-zero mask.
5361 if (smb_fmask != 0) {
5362 int stat_fflags = 0;
5364 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5366 /* Client asked to alter a flag we don't understand. */
5367 return NT_STATUS_INVALID_PARAMETER;
5370 if (fsp && fsp->fh->fd != -1) {
5371 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5372 return NT_STATUS_NOT_SUPPORTED;
5374 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5375 return map_nt_error_from_unix(errno);
5380 /* XXX: need to add support for changing the create_time here. You
5381 * can do this for paths on Darwin with setattrlist(2). The right way
5382 * to hook this up is probably by extending the VFS utimes interface.
5385 return NT_STATUS_OK;
5388 /****************************************************************************
5389 Create a directory with POSIX semantics.
5390 ****************************************************************************/
5392 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5396 SMB_STRUCT_STAT *psbuf,
5397 int *pdata_return_size)
5399 NTSTATUS status = NT_STATUS_OK;
5400 uint32 raw_unixmode = 0;
5401 uint32 mod_unixmode = 0;
5402 mode_t unixmode = (mode_t)0;
5403 files_struct *fsp = NULL;
5404 uint16 info_level_return = 0;
5406 char *pdata = *ppdata;
5408 if (total_data < 18) {
5409 return NT_STATUS_INVALID_PARAMETER;
5412 raw_unixmode = IVAL(pdata,8);
5413 /* Next 4 bytes are not yet defined. */
5415 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5416 if (!NT_STATUS_IS_OK(status)) {
5420 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5422 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5423 fname, (unsigned int)unixmode ));
5425 status = open_directory(conn,
5428 FILE_READ_ATTRIBUTES, /* Just a stat open */
5429 FILE_SHARE_NONE, /* Ignored for stat opens */
5436 if (NT_STATUS_IS_OK(status)) {
5437 close_file(fsp, NORMAL_CLOSE);
5440 info_level_return = SVAL(pdata,16);
5442 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5443 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5444 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5445 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5447 *pdata_return_size = 12;
5450 /* Realloc the data size */
5451 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5452 if (*ppdata == NULL) {
5453 *pdata_return_size = 0;
5454 return NT_STATUS_NO_MEMORY;
5458 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5459 SSVAL(pdata,2,0); /* No fnum. */
5460 SIVAL(pdata,4,info); /* Was directory created. */
5462 switch (info_level_return) {
5463 case SMB_QUERY_FILE_UNIX_BASIC:
5464 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5465 SSVAL(pdata,10,0); /* Padding. */
5466 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5468 case SMB_QUERY_FILE_UNIX_INFO2:
5469 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5470 SSVAL(pdata,10,0); /* Padding. */
5471 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5474 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5475 SSVAL(pdata,10,0); /* Padding. */
5482 /****************************************************************************
5483 Open/Create a file with POSIX semantics.
5484 ****************************************************************************/
5486 static NTSTATUS smb_posix_open(connection_struct *conn,
5490 SMB_STRUCT_STAT *psbuf,
5491 int *pdata_return_size)
5493 BOOL extended_oplock_granted = False;
5494 char *pdata = *ppdata;
5496 uint32 wire_open_mode = 0;
5497 uint32 raw_unixmode = 0;
5498 uint32 mod_unixmode = 0;
5499 uint32 create_disp = 0;
5500 uint32 access_mask = 0;
5501 uint32 create_options = 0;
5502 NTSTATUS status = NT_STATUS_OK;
5503 mode_t unixmode = (mode_t)0;
5504 files_struct *fsp = NULL;
5505 int oplock_request = 0;
5507 uint16 info_level_return = 0;
5509 if (total_data < 18) {
5510 return NT_STATUS_INVALID_PARAMETER;
5513 flags = IVAL(pdata,0);
5514 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5515 if (oplock_request) {
5516 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5519 wire_open_mode = IVAL(pdata,4);
5521 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5522 return smb_posix_mkdir(conn,
5530 switch (wire_open_mode & SMB_ACCMODE) {
5532 access_mask = FILE_READ_DATA;
5535 access_mask = FILE_WRITE_DATA;
5538 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5541 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5542 (unsigned int)wire_open_mode ));
5543 return NT_STATUS_INVALID_PARAMETER;
5546 wire_open_mode &= ~SMB_ACCMODE;
5548 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5549 create_disp = FILE_CREATE;
5550 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5551 create_disp = FILE_OVERWRITE_IF;
5552 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5553 create_disp = FILE_OPEN_IF;
5555 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5556 (unsigned int)wire_open_mode ));
5557 return NT_STATUS_INVALID_PARAMETER;
5560 raw_unixmode = IVAL(pdata,8);
5561 /* Next 4 bytes are not yet defined. */
5563 status = unix_perms_from_wire(conn,
5566 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5569 if (!NT_STATUS_IS_OK(status)) {
5573 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5575 if (wire_open_mode & SMB_O_SYNC) {
5576 create_options |= FILE_WRITE_THROUGH;
5578 if (wire_open_mode & SMB_O_APPEND) {
5579 access_mask |= FILE_APPEND_DATA;
5581 if (wire_open_mode & SMB_O_DIRECT) {
5582 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5585 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5587 (unsigned int)wire_open_mode,
5588 (unsigned int)unixmode ));
5590 status = open_file_ntcreate(conn,
5594 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5596 0, /* no create options yet. */
5602 if (!NT_STATUS_IS_OK(status)) {
5606 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5607 extended_oplock_granted = True;
5610 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5611 extended_oplock_granted = True;
5614 info_level_return = SVAL(pdata,16);
5616 /* Allocate the correct return size. */
5618 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5619 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5620 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5621 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5623 *pdata_return_size = 12;
5626 /* Realloc the data size */
5627 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5628 if (*ppdata == NULL) {
5629 close_file(fsp,ERROR_CLOSE);
5630 *pdata_return_size = 0;
5631 return NT_STATUS_NO_MEMORY;
5635 if (extended_oplock_granted) {
5636 if (flags & REQUEST_BATCH_OPLOCK) {
5637 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5639 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5641 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5642 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5644 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5647 SSVAL(pdata,2,fsp->fnum);
5648 SIVAL(pdata,4,info); /* Was file created etc. */
5650 switch (info_level_return) {
5651 case SMB_QUERY_FILE_UNIX_BASIC:
5652 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5653 SSVAL(pdata,10,0); /* padding. */
5654 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5656 case SMB_QUERY_FILE_UNIX_INFO2:
5657 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5658 SSVAL(pdata,10,0); /* padding. */
5659 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5662 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5663 SSVAL(pdata,10,0); /* padding. */
5666 return NT_STATUS_OK;
5669 /****************************************************************************
5670 Delete a file with POSIX semantics.
5671 ****************************************************************************/
5673 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5677 SMB_STRUCT_STAT *psbuf)
5679 NTSTATUS status = NT_STATUS_OK;
5680 files_struct *fsp = NULL;
5684 if (total_data < 2) {
5685 return NT_STATUS_INVALID_PARAMETER;
5688 flags = SVAL(pdata,0);
5690 if (!VALID_STAT(*psbuf)) {
5691 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5694 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5695 !VALID_STAT_OF_DIR(*psbuf)) {
5696 return NT_STATUS_NOT_A_DIRECTORY;
5699 DEBUG(10,("smb_posix_unlink: %s %s\n",
5700 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5703 if (VALID_STAT_OF_DIR(*psbuf)) {
5704 status = open_directory(conn,
5708 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5710 FILE_DELETE_ON_CLOSE,
5711 FILE_FLAG_POSIX_SEMANTICS|0777,
5717 status = open_file_ntcreate(conn,
5721 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5724 FILE_FLAG_POSIX_SEMANTICS|0777,
5725 0, /* No oplock, but break existing ones. */
5729 * For file opens we must set the delete on close
5733 if (!NT_STATUS_IS_OK(status)) {
5737 status = smb_set_file_disposition_info(conn,
5745 if (!NT_STATUS_IS_OK(status)) {
5748 return close_file(fsp, NORMAL_CLOSE);
5751 /****************************************************************************
5752 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5753 ****************************************************************************/
5755 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5756 unsigned int tran_call,
5757 char **pparams, int total_params, char **ppdata, int total_data,
5758 unsigned int max_data_bytes)
5760 char *params = *pparams;
5761 char *pdata = *ppdata;
5763 SMB_STRUCT_STAT sbuf;
5765 files_struct *fsp = NULL;
5766 NTSTATUS status = NT_STATUS_OK;
5767 int data_return_size = 0;
5770 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5775 if (tran_call == TRANSACT2_SETFILEINFO) {
5776 if (total_params < 4) {
5777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5780 fsp = file_fsp(params,0);
5781 info_level = SVAL(params,2);
5783 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5785 * This is actually a SETFILEINFO on a directory
5786 * handle (returned from an NT SMB). NT5.0 seems
5787 * to do this call. JRA.
5789 pstrcpy(fname, fsp->fsp_name);
5790 if (INFO_LEVEL_IS_UNIX(info_level)) {
5791 /* Always do lstat for UNIX calls. */
5792 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5793 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5794 return UNIXERROR(ERRDOS,ERRbadpath);
5797 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5798 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5799 return UNIXERROR(ERRDOS,ERRbadpath);
5802 } else if (fsp && fsp->print_file) {
5804 * Doing a DELETE_ON_CLOSE should cancel a print job.
5806 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5807 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5809 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5812 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5815 return (UNIXERROR(ERRDOS,ERRbadpath));
5818 * Original code - this is an open file.
5820 CHECK_FSP(fsp,conn);
5822 pstrcpy(fname, fsp->fsp_name);
5824 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5825 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5826 return(UNIXERROR(ERRDOS,ERRbadfid));
5831 if (total_params < 7) {
5832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5835 info_level = SVAL(params,0);
5836 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5837 if (!NT_STATUS_IS_OK(status)) {
5838 return ERROR_NT(status);
5841 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5842 if (!NT_STATUS_IS_OK(status)) {
5843 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5844 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5846 return ERROR_NT(status);
5849 status = unix_convert(conn, fname, False, NULL, &sbuf);
5850 if (!NT_STATUS_IS_OK(status)) {
5851 return ERROR_NT(status);
5854 status = check_name(conn, fname);
5855 if (!NT_STATUS_IS_OK(status)) {
5856 return ERROR_NT(status);
5859 if (INFO_LEVEL_IS_UNIX(info_level)) {
5861 * For CIFS UNIX extensions the target name may not exist.
5864 /* Always do lstat for UNIX calls. */
5865 SMB_VFS_LSTAT(conn,fname,&sbuf);
5867 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5868 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5869 return UNIXERROR(ERRDOS,ERRbadpath);
5873 if (!CAN_WRITE(conn)) {
5874 return ERROR_DOS(ERRSRV,ERRaccess);
5877 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5878 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5881 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5882 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5884 /* Realloc the parameter size */
5885 *pparams = (char *)SMB_REALLOC(*pparams,2);
5886 if (*pparams == NULL) {
5887 return ERROR_NT(NT_STATUS_NO_MEMORY);
5893 if (fsp && !null_timespec(fsp->pending_modtime)) {
5894 /* the pending modtime overrides the current modtime */
5895 set_mtimespec(&sbuf, fsp->pending_modtime);
5898 switch (info_level) {
5900 case SMB_INFO_STANDARD:
5902 status = smb_set_info_standard(conn,
5911 case SMB_INFO_SET_EA:
5913 status = smb_info_set_ea(conn,
5921 case SMB_SET_FILE_BASIC_INFO:
5922 case SMB_FILE_BASIC_INFORMATION:
5924 status = smb_set_file_basic_info(conn,
5933 case SMB_FILE_ALLOCATION_INFORMATION:
5934 case SMB_SET_FILE_ALLOCATION_INFO:
5936 status = smb_set_file_allocation_info(conn,
5945 case SMB_FILE_END_OF_FILE_INFORMATION:
5946 case SMB_SET_FILE_END_OF_FILE_INFO:
5948 status = smb_set_file_end_of_file_info(conn,
5957 case SMB_FILE_DISPOSITION_INFORMATION:
5958 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5961 /* JRA - We used to just ignore this on a path ?
5962 * Shouldn't this be invalid level on a pathname
5965 if (tran_call != TRANSACT2_SETFILEINFO) {
5966 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5969 status = smb_set_file_disposition_info(conn,
5978 case SMB_FILE_POSITION_INFORMATION:
5980 status = smb_file_position_information(conn,
5987 /* From tridge Samba4 :
5988 * MODE_INFORMATION in setfileinfo (I have no
5989 * idea what "mode information" on a file is - it takes a value of 0,
5990 * 2, 4 or 6. What could it be?).
5993 case SMB_FILE_MODE_INFORMATION:
5995 status = smb_file_mode_information(conn,
6002 * CIFS UNIX extensions.
6005 case SMB_SET_FILE_UNIX_BASIC:
6007 status = smb_set_file_unix_basic(conn,
6016 case SMB_SET_FILE_UNIX_INFO2:
6018 status = smb_set_file_unix_info2(conn,
6027 case SMB_SET_FILE_UNIX_LINK:
6029 if (tran_call != TRANSACT2_SETPATHINFO) {
6030 /* We must have a pathname for this. */
6031 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6033 status = smb_set_file_unix_link(conn,
6041 case SMB_SET_FILE_UNIX_HLINK:
6043 if (tran_call != TRANSACT2_SETPATHINFO) {
6044 /* We must have a pathname for this. */
6045 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6047 status = smb_set_file_unix_hlink(conn,
6056 case SMB_FILE_RENAME_INFORMATION:
6058 status = smb_file_rename_information(conn,
6068 #if defined(HAVE_POSIX_ACLS)
6069 case SMB_SET_POSIX_ACL:
6071 status = smb_set_posix_acl(conn,
6081 case SMB_SET_POSIX_LOCK:
6083 if (tran_call != TRANSACT2_SETFILEINFO) {
6084 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6086 status = smb_set_posix_lock(conn,
6095 case SMB_POSIX_PATH_OPEN:
6097 if (tran_call != TRANSACT2_SETPATHINFO) {
6098 /* We must have a pathname for this. */
6099 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6102 status = smb_posix_open(conn,
6111 case SMB_POSIX_PATH_UNLINK:
6113 if (tran_call != TRANSACT2_SETPATHINFO) {
6114 /* We must have a pathname for this. */
6115 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6118 status = smb_posix_unlink(conn,
6127 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6131 if (!NT_STATUS_IS_OK(status)) {
6132 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6133 /* We have re-scheduled this call. */
6136 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6137 /* We have re-scheduled this call. */
6140 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6141 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6143 return ERROR_NT(status);
6147 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6152 /****************************************************************************
6153 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6154 ****************************************************************************/
6156 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6157 char **pparams, int total_params, char **ppdata, int total_data,
6158 unsigned int max_data_bytes)
6160 char *params = *pparams;
6161 char *pdata = *ppdata;
6163 SMB_STRUCT_STAT sbuf;
6164 NTSTATUS status = NT_STATUS_OK;
6165 struct ea_list *ea_list = NULL;
6167 if (!CAN_WRITE(conn))
6168 return ERROR_DOS(ERRSRV,ERRaccess);
6170 if (total_params < 5) {
6171 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6174 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6175 if (!NT_STATUS_IS_OK(status)) {
6176 return ERROR_NT(status);
6179 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6181 status = unix_convert(conn, directory, False, NULL, &sbuf);
6182 if (!NT_STATUS_IS_OK(status)) {
6183 return ERROR_NT(status);
6186 status = check_name(conn, directory);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6189 return ERROR_NT(status);
6192 /* Any data in this call is an EA list. */
6193 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6194 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6198 * OS/2 workplace shell seems to send SET_EA requests of "null"
6199 * length (4 bytes containing IVAL 4).
6200 * They seem to have no effect. Bug #3212. JRA.
6203 if (total_data != 4) {
6204 if (total_data < 10) {
6205 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6208 if (IVAL(pdata,0) > total_data) {
6209 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6210 IVAL(pdata,0), (unsigned int)total_data));
6211 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6214 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6217 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6219 } else if (IVAL(pdata,0) != 4) {
6220 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6223 status = create_directory(conn, directory);
6225 if (!NT_STATUS_IS_OK(status)) {
6226 return ERROR_NT(status);
6229 /* Try and set any given EA. */
6231 status = set_ea(conn, NULL, directory, ea_list);
6232 if (!NT_STATUS_IS_OK(status)) {
6233 return ERROR_NT(status);
6237 /* Realloc the parameter and data sizes */
6238 *pparams = (char *)SMB_REALLOC(*pparams,2);
6239 if(*pparams == NULL) {
6240 return ERROR_NT(NT_STATUS_NO_MEMORY);
6246 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6251 /****************************************************************************
6252 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6253 We don't actually do this - we just send a null response.
6254 ****************************************************************************/
6256 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6257 char **pparams, int total_params, char **ppdata, int total_data,
6258 unsigned int max_data_bytes)
6260 static uint16 fnf_handle = 257;
6261 char *params = *pparams;
6264 if (total_params < 6) {
6265 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6268 info_level = SVAL(params,4);
6269 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6271 switch (info_level) {
6276 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6279 /* Realloc the parameter and data sizes */
6280 *pparams = (char *)SMB_REALLOC(*pparams,6);
6281 if (*pparams == NULL) {
6282 return ERROR_NT(NT_STATUS_NO_MEMORY);
6286 SSVAL(params,0,fnf_handle);
6287 SSVAL(params,2,0); /* No changes */
6288 SSVAL(params,4,0); /* No EA errors */
6295 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6300 /****************************************************************************
6301 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6302 changes). Currently this does nothing.
6303 ****************************************************************************/
6305 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6306 char **pparams, int total_params, char **ppdata, int total_data,
6307 unsigned int max_data_bytes)
6309 char *params = *pparams;
6311 DEBUG(3,("call_trans2findnotifynext\n"));
6313 /* Realloc the parameter and data sizes */
6314 *pparams = (char *)SMB_REALLOC(*pparams,4);
6315 if (*pparams == NULL) {
6316 return ERROR_NT(NT_STATUS_NO_MEMORY);
6320 SSVAL(params,0,0); /* No changes */
6321 SSVAL(params,2,0); /* No EA errors */
6323 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6328 /****************************************************************************
6329 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6330 ****************************************************************************/
6332 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6333 char **pparams, int total_params, char **ppdata, int total_data,
6334 unsigned int max_data_bytes)
6336 char *params = *pparams;
6339 int max_referral_level;
6340 NTSTATUS status = NT_STATUS_OK;
6342 DEBUG(10,("call_trans2getdfsreferral\n"));
6344 if (total_params < 3) {
6345 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6348 max_referral_level = SVAL(params,0);
6350 if(!lp_host_msdfs())
6351 return ERROR_DOS(ERRDOS,ERRbadfunc);
6353 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6354 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6355 return ERROR_NT(status);
6357 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6358 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6363 #define LMCAT_SPL 0x53
6364 #define LMFUNC_GETJOBID 0x60
6366 /****************************************************************************
6367 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6368 ****************************************************************************/
6370 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6371 char **pparams, int total_params, char **ppdata, int total_data,
6372 unsigned int max_data_bytes)
6374 char *pdata = *ppdata;
6375 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6377 /* check for an invalid fid before proceeding */
6380 return(ERROR_DOS(ERRDOS,ERRbadfid));
6382 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6383 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6384 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6385 if (*ppdata == NULL) {
6386 return ERROR_NT(NT_STATUS_NO_MEMORY);
6390 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6391 CAN ACCEPT THIS IN UNICODE. JRA. */
6393 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6394 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6395 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6396 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6399 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6400 return ERROR_DOS(ERRSRV,ERRerror);
6404 /****************************************************************************
6405 Reply to a SMBfindclose (stop trans2 directory search).
6406 ****************************************************************************/
6408 int reply_findclose(connection_struct *conn,
6409 char *inbuf,char *outbuf,int length,int bufsize)
6412 int dptr_num=SVALS(inbuf,smb_vwv0);
6413 START_PROFILE(SMBfindclose);
6415 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6417 dptr_close(&dptr_num);
6419 outsize = set_message(inbuf, outbuf,0,0,False);
6421 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6423 END_PROFILE(SMBfindclose);
6427 /****************************************************************************
6428 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6429 ****************************************************************************/
6431 int reply_findnclose(connection_struct *conn,
6432 char *inbuf,char *outbuf,int length,int bufsize)
6436 START_PROFILE(SMBfindnclose);
6438 dptr_num = SVAL(inbuf,smb_vwv0);
6440 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6442 /* We never give out valid handles for a
6443 findnotifyfirst - so any dptr_num is ok here.
6446 outsize = set_message(inbuf, outbuf,0,0,False);
6448 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6450 END_PROFILE(SMBfindnclose);
6454 int handle_trans2(connection_struct *conn,
6455 struct trans_state *state,
6456 char *inbuf, char *outbuf, int size, int bufsize)
6460 if (Protocol >= PROTOCOL_NT1) {
6461 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6464 /* Now we must call the relevant TRANS2 function */
6465 switch(state->call) {
6466 case TRANSACT2_OPEN:
6468 START_PROFILE(Trans2_open);
6469 outsize = call_trans2open(
6470 conn, inbuf, outbuf, bufsize,
6471 &state->param, state->total_param,
6472 &state->data, state->total_data,
6473 state->max_data_return);
6474 END_PROFILE(Trans2_open);
6478 case TRANSACT2_FINDFIRST:
6480 START_PROFILE(Trans2_findfirst);
6481 outsize = call_trans2findfirst(
6482 conn, inbuf, outbuf, bufsize,
6483 &state->param, state->total_param,
6484 &state->data, state->total_data,
6485 state->max_data_return);
6486 END_PROFILE(Trans2_findfirst);
6490 case TRANSACT2_FINDNEXT:
6492 START_PROFILE(Trans2_findnext);
6493 outsize = call_trans2findnext(
6494 conn, inbuf, outbuf, size, bufsize,
6495 &state->param, state->total_param,
6496 &state->data, state->total_data,
6497 state->max_data_return);
6498 END_PROFILE(Trans2_findnext);
6502 case TRANSACT2_QFSINFO:
6504 START_PROFILE(Trans2_qfsinfo);
6505 outsize = call_trans2qfsinfo(
6506 conn, inbuf, outbuf, size, bufsize,
6507 &state->param, state->total_param,
6508 &state->data, state->total_data,
6509 state->max_data_return);
6510 END_PROFILE(Trans2_qfsinfo);
6514 case TRANSACT2_SETFSINFO:
6516 START_PROFILE(Trans2_setfsinfo);
6517 outsize = call_trans2setfsinfo(
6518 conn, inbuf, outbuf, size, bufsize,
6519 &state->param, state->total_param,
6520 &state->data, state->total_data,
6521 state->max_data_return);
6522 END_PROFILE(Trans2_setfsinfo);
6526 case TRANSACT2_QPATHINFO:
6527 case TRANSACT2_QFILEINFO:
6529 START_PROFILE(Trans2_qpathinfo);
6530 outsize = call_trans2qfilepathinfo(
6531 conn, inbuf, outbuf, size, bufsize, state->call,
6532 &state->param, state->total_param,
6533 &state->data, state->total_data,
6534 state->max_data_return);
6535 END_PROFILE(Trans2_qpathinfo);
6539 case TRANSACT2_SETPATHINFO:
6540 case TRANSACT2_SETFILEINFO:
6542 START_PROFILE(Trans2_setpathinfo);
6543 outsize = call_trans2setfilepathinfo(
6544 conn, inbuf, outbuf, size, bufsize, state->call,
6545 &state->param, state->total_param,
6546 &state->data, state->total_data,
6547 state->max_data_return);
6548 END_PROFILE(Trans2_setpathinfo);
6552 case TRANSACT2_FINDNOTIFYFIRST:
6554 START_PROFILE(Trans2_findnotifyfirst);
6555 outsize = call_trans2findnotifyfirst(
6556 conn, inbuf, outbuf, size, bufsize,
6557 &state->param, state->total_param,
6558 &state->data, state->total_data,
6559 state->max_data_return);
6560 END_PROFILE(Trans2_findnotifyfirst);
6564 case TRANSACT2_FINDNOTIFYNEXT:
6566 START_PROFILE(Trans2_findnotifynext);
6567 outsize = call_trans2findnotifynext(
6568 conn, inbuf, outbuf, size, bufsize,
6569 &state->param, state->total_param,
6570 &state->data, state->total_data,
6571 state->max_data_return);
6572 END_PROFILE(Trans2_findnotifynext);
6576 case TRANSACT2_MKDIR:
6578 START_PROFILE(Trans2_mkdir);
6579 outsize = call_trans2mkdir(
6580 conn, inbuf, outbuf, size, bufsize,
6581 &state->param, state->total_param,
6582 &state->data, state->total_data,
6583 state->max_data_return);
6584 END_PROFILE(Trans2_mkdir);
6588 case TRANSACT2_GET_DFS_REFERRAL:
6590 START_PROFILE(Trans2_get_dfs_referral);
6591 outsize = call_trans2getdfsreferral(
6592 conn, inbuf, outbuf, size, bufsize,
6593 &state->param, state->total_param,
6594 &state->data, state->total_data,
6595 state->max_data_return);
6596 END_PROFILE(Trans2_get_dfs_referral);
6600 case TRANSACT2_IOCTL:
6602 START_PROFILE(Trans2_ioctl);
6603 outsize = call_trans2ioctl(
6604 conn, inbuf, outbuf, size, bufsize,
6605 &state->param, state->total_param,
6606 &state->data, state->total_data,
6607 state->max_data_return);
6608 END_PROFILE(Trans2_ioctl);
6613 /* Error in request */
6614 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6615 outsize = ERROR_DOS(ERRSRV,ERRerror);
6621 /****************************************************************************
6622 Reply to a SMBtrans2.
6623 ****************************************************************************/
6625 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6626 int size, int bufsize)
6629 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6630 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6631 unsigned int psoff = SVAL(inbuf, smb_psoff);
6632 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6633 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6634 struct trans_state *state;
6637 START_PROFILE(SMBtrans2);
6639 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6640 if (!NT_STATUS_IS_OK(result)) {
6641 DEBUG(2, ("Got invalid trans2 request: %s\n",
6642 nt_errstr(result)));
6643 END_PROFILE(SMBtrans2);
6644 return ERROR_NT(result);
6647 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6648 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6649 && (tran_call != TRANSACT2_QFILEINFO)) {
6650 END_PROFILE(SMBtrans2);
6651 return ERROR_DOS(ERRSRV,ERRaccess);
6654 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6655 DEBUG(0, ("talloc failed\n"));
6656 END_PROFILE(SMBtrans2);
6657 return ERROR_NT(NT_STATUS_NO_MEMORY);
6660 state->cmd = SMBtrans2;
6662 state->mid = SVAL(inbuf, smb_mid);
6663 state->vuid = SVAL(inbuf, smb_uid);
6664 state->setup_count = SVAL(inbuf, smb_suwcnt);
6665 state->setup = NULL;
6666 state->total_param = SVAL(inbuf, smb_tpscnt);
6667 state->param = NULL;
6668 state->total_data = SVAL(inbuf, smb_tdscnt);
6670 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6671 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6672 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6673 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6674 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6676 state->call = tran_call;
6678 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6679 is so as a sanity check */
6680 if (state->setup_count != 1) {
6682 * Need to have rc=0 for ioctl to get job id for OS/2.
6683 * Network printing will fail if function is not successful.
6684 * Similar function in reply.c will be used if protocol
6685 * is LANMAN1.0 instead of LM1.2X002.
6686 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6687 * outbuf doesn't have to be set(only job id is used).
6689 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6690 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6691 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6692 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6694 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6695 DEBUG(2,("Transaction is %d\n",tran_call));
6697 END_PROFILE(SMBtrans2);
6698 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6702 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6705 if (state->total_data) {
6706 /* Can't use talloc here, the core routines do realloc on the
6707 * params and data. */
6708 state->data = (char *)SMB_MALLOC(state->total_data);
6709 if (state->data == NULL) {
6710 DEBUG(0,("reply_trans2: data malloc fail for %u "
6711 "bytes !\n", (unsigned int)state->total_data));
6713 END_PROFILE(SMBtrans2);
6714 return(ERROR_DOS(ERRDOS,ERRnomem));
6716 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6718 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6719 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6722 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6725 if (state->total_param) {
6726 /* Can't use talloc here, the core routines do realloc on the
6727 * params and data. */
6728 state->param = (char *)SMB_MALLOC(state->total_param);
6729 if (state->param == NULL) {
6730 DEBUG(0,("reply_trans: param malloc fail for %u "
6731 "bytes !\n", (unsigned int)state->total_param));
6732 SAFE_FREE(state->data);
6734 END_PROFILE(SMBtrans2);
6735 return(ERROR_DOS(ERRDOS,ERRnomem));
6737 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6739 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6740 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6743 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6746 state->received_data = dscnt;
6747 state->received_param = pscnt;
6749 if ((state->received_param == state->total_param) &&
6750 (state->received_data == state->total_data)) {
6752 outsize = handle_trans2(conn, state, inbuf, outbuf,
6754 SAFE_FREE(state->data);
6755 SAFE_FREE(state->param);
6757 END_PROFILE(SMBtrans2);
6761 DLIST_ADD(conn->pending_trans, state);
6763 /* We need to send an interim response then receive the rest
6764 of the parameter/data bytes */
6765 outsize = set_message(inbuf, outbuf,0,0,False);
6767 END_PROFILE(SMBtrans2);
6772 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6773 SAFE_FREE(state->data);
6774 SAFE_FREE(state->param);
6776 END_PROFILE(SMBtrans2);
6777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6781 /****************************************************************************
6782 Reply to a SMBtranss2
6783 ****************************************************************************/
6785 int reply_transs2(connection_struct *conn,
6786 char *inbuf,char *outbuf,int size,int bufsize)
6789 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6790 struct trans_state *state;
6792 START_PROFILE(SMBtranss2);
6796 for (state = conn->pending_trans; state != NULL;
6797 state = state->next) {
6798 if (state->mid == SVAL(inbuf,smb_mid)) {
6803 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6804 END_PROFILE(SMBtranss2);
6805 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6808 /* Revise state->total_param and state->total_data in case they have
6809 changed downwards */
6811 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6812 state->total_param = SVAL(inbuf, smb_tpscnt);
6813 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6814 state->total_data = SVAL(inbuf, smb_tdscnt);
6816 pcnt = SVAL(inbuf, smb_spscnt);
6817 poff = SVAL(inbuf, smb_spsoff);
6818 pdisp = SVAL(inbuf, smb_spsdisp);
6820 dcnt = SVAL(inbuf, smb_sdscnt);
6821 doff = SVAL(inbuf, smb_sdsoff);
6822 ddisp = SVAL(inbuf, smb_sdsdisp);
6824 state->received_param += pcnt;
6825 state->received_data += dcnt;
6827 if ((state->received_data > state->total_data) ||
6828 (state->received_param > state->total_param))
6832 if (pdisp+pcnt > state->total_param)
6834 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6836 if (pdisp > state->total_param)
6838 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6839 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6841 if (state->param + pdisp < state->param)
6844 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6849 if (ddisp+dcnt > state->total_data)
6851 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6853 if (ddisp > state->total_data)
6855 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6856 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6858 if (state->data + ddisp < state->data)
6861 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6865 if ((state->received_param < state->total_param) ||
6866 (state->received_data < state->total_data)) {
6867 END_PROFILE(SMBtranss2);
6871 /* construct_reply_common has done us the favor to pre-fill the
6872 * command field with SMBtranss2 which is wrong :-)
6874 SCVAL(outbuf,smb_com,SMBtrans2);
6876 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6878 DLIST_REMOVE(conn->pending_trans, state);
6879 SAFE_FREE(state->data);
6880 SAFE_FREE(state->param);
6884 END_PROFILE(SMBtranss2);
6885 return(ERROR_DOS(ERRSRV,ERRnosupport));
6888 END_PROFILE(SMBtranss2);
6893 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6894 DLIST_REMOVE(conn->pending_trans, state);
6895 SAFE_FREE(state->data);
6896 SAFE_FREE(state->param);
6898 END_PROFILE(SMBtranss2);
6899 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);