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 /* Append the new name. */
4656 pstrcat(base_name, "/");
4657 pstrcat(base_name, newname);
4660 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4661 fsp->fnum, fsp->fsp_name, base_name ));
4662 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4664 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4666 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4672 /****************************************************************************
4673 Deal with SMB_SET_POSIX_ACL.
4674 ****************************************************************************/
4676 #if defined(HAVE_POSIX_ACLS)
4677 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4682 SMB_STRUCT_STAT *psbuf)
4684 uint16 posix_acl_version;
4685 uint16 num_file_acls;
4686 uint16 num_def_acls;
4687 BOOL valid_file_acls = True;
4688 BOOL valid_def_acls = True;
4690 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4691 return NT_STATUS_INVALID_PARAMETER;
4693 posix_acl_version = SVAL(pdata,0);
4694 num_file_acls = SVAL(pdata,2);
4695 num_def_acls = SVAL(pdata,4);
4697 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4698 valid_file_acls = False;
4702 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4703 valid_def_acls = False;
4707 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4708 return NT_STATUS_INVALID_PARAMETER;
4711 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4712 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4713 return NT_STATUS_INVALID_PARAMETER;
4716 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4717 fname ? fname : fsp->fsp_name,
4718 (unsigned int)num_file_acls,
4719 (unsigned int)num_def_acls));
4721 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4722 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4723 return map_nt_error_from_unix(errno);
4726 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4727 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4728 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4729 return map_nt_error_from_unix(errno);
4731 return NT_STATUS_OK;
4735 /****************************************************************************
4736 Deal with SMB_SET_POSIX_LOCK.
4737 ****************************************************************************/
4739 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4747 SMB_BIG_UINT offset;
4749 BOOL blocking_lock = False;
4750 enum brl_type lock_type;
4751 NTSTATUS status = NT_STATUS_OK;
4753 if (fsp == NULL || fsp->fh->fd == -1) {
4754 return NT_STATUS_INVALID_HANDLE;
4757 if (total_data != POSIX_LOCK_DATA_SIZE) {
4758 return NT_STATUS_INVALID_PARAMETER;
4761 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4762 case POSIX_LOCK_TYPE_READ:
4763 lock_type = READ_LOCK;
4765 case POSIX_LOCK_TYPE_WRITE:
4766 /* Return the right POSIX-mappable error code for files opened read-only. */
4767 if (!fsp->can_write) {
4768 return NT_STATUS_INVALID_HANDLE;
4770 lock_type = WRITE_LOCK;
4772 case POSIX_LOCK_TYPE_UNLOCK:
4773 lock_type = UNLOCK_LOCK;
4776 return NT_STATUS_INVALID_PARAMETER;
4779 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4780 blocking_lock = False;
4781 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4782 blocking_lock = True;
4784 return NT_STATUS_INVALID_PARAMETER;
4787 if (!lp_blocking_locks(SNUM(conn))) {
4788 blocking_lock = False;
4791 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4792 #if defined(HAVE_LONGLONG)
4793 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4794 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4795 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4796 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4797 #else /* HAVE_LONGLONG */
4798 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4799 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4800 #endif /* HAVE_LONGLONG */
4802 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4803 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4805 (unsigned int)lock_type,
4806 (unsigned int)lock_pid,
4810 if (lock_type == UNLOCK_LOCK) {
4811 status = do_unlock(smbd_messaging_context(),
4818 uint32 block_smbpid;
4820 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4831 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4833 * A blocking lock was requested. Package up
4834 * this smb into a queued request and push it
4835 * onto the blocking lock queue.
4837 if(push_blocking_lock_request(br_lck,
4840 -1, /* infinite timeout. */
4848 TALLOC_FREE(br_lck);
4852 TALLOC_FREE(br_lck);
4858 /****************************************************************************
4859 Deal with SMB_INFO_STANDARD.
4860 ****************************************************************************/
4862 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4867 const SMB_STRUCT_STAT *psbuf)
4869 struct timespec ts[2];
4871 if (total_data < 12) {
4872 return NT_STATUS_INVALID_PARAMETER;
4876 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4878 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4880 DEBUG(10,("smb_set_info_standard: file %s\n",
4881 fname ? fname : fsp->fsp_name ));
4883 return smb_set_file_time(conn,
4890 /****************************************************************************
4891 Deal with SMB_SET_FILE_BASIC_INFO.
4892 ****************************************************************************/
4894 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4899 SMB_STRUCT_STAT *psbuf)
4901 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4902 struct timespec write_time;
4903 struct timespec changed_time;
4905 struct timespec ts[2];
4906 NTSTATUS status = NT_STATUS_OK;
4908 if (total_data < 36) {
4909 return NT_STATUS_INVALID_PARAMETER;
4912 /* Set the attributes */
4913 dosmode = IVAL(pdata,32);
4914 status = smb_set_file_dosmode(conn,
4918 if (!NT_STATUS_IS_OK(status)) {
4922 /* Ignore create time at offset pdata. */
4925 ts[0] = interpret_long_date(pdata+8);
4927 write_time = interpret_long_date(pdata+16);
4928 changed_time = interpret_long_date(pdata+24);
4931 ts[1] = timespec_min(&write_time, &changed_time);
4933 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4937 /* Prefer a defined time to an undefined one. */
4938 if (null_timespec(ts[1])) {
4939 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4942 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4943 fname ? fname : fsp->fsp_name ));
4945 return smb_set_file_time(conn,
4952 /****************************************************************************
4953 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4954 ****************************************************************************/
4956 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4961 SMB_STRUCT_STAT *psbuf)
4963 SMB_BIG_UINT allocation_size = 0;
4964 NTSTATUS status = NT_STATUS_OK;
4965 files_struct *new_fsp = NULL;
4967 if (!VALID_STAT(*psbuf)) {
4968 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4971 if (total_data < 8) {
4972 return NT_STATUS_INVALID_PARAMETER;
4975 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4976 #ifdef LARGE_SMB_OFF_T
4977 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4978 #else /* LARGE_SMB_OFF_T */
4979 if (IVAL(pdata,4) != 0) {
4980 /* more than 32 bits? */
4981 return NT_STATUS_INVALID_PARAMETER;
4983 #endif /* LARGE_SMB_OFF_T */
4985 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4986 fname, (double)allocation_size ));
4988 if (allocation_size) {
4989 allocation_size = smb_roundup(conn, allocation_size);
4992 if(allocation_size == get_file_size(*psbuf)) {
4993 return NT_STATUS_OK;
4996 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4997 fname, (double)allocation_size ));
4999 if (fsp && fsp->fh->fd != -1) {
5000 /* Open file handle. */
5001 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5002 return map_nt_error_from_unix(errno);
5004 return NT_STATUS_OK;
5007 /* Pathname or stat or directory file. */
5009 status = open_file_ntcreate(conn, fname, psbuf,
5011 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5014 FILE_ATTRIBUTE_NORMAL,
5015 FORCE_OPLOCK_BREAK_TO_NONE,
5018 if (!NT_STATUS_IS_OK(status)) {
5019 /* NB. We check for open_was_deferred in the caller. */
5022 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5023 status = map_nt_error_from_unix(errno);
5024 close_file(new_fsp,NORMAL_CLOSE);
5028 close_file(new_fsp,NORMAL_CLOSE);
5029 return NT_STATUS_OK;
5032 /****************************************************************************
5033 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5034 ****************************************************************************/
5036 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5041 SMB_STRUCT_STAT *psbuf)
5045 if (total_data < 8) {
5046 return NT_STATUS_INVALID_PARAMETER;
5049 size = IVAL(pdata,0);
5050 #ifdef LARGE_SMB_OFF_T
5051 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5052 #else /* LARGE_SMB_OFF_T */
5053 if (IVAL(pdata,4) != 0) {
5054 /* more than 32 bits? */
5055 return NT_STATUS_INVALID_PARAMETER;
5057 #endif /* LARGE_SMB_OFF_T */
5058 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5059 "file %s to %.0f\n", fname, (double)size ));
5061 return smb_set_file_size(conn,
5068 /****************************************************************************
5069 Allow a UNIX info mknod.
5070 ****************************************************************************/
5072 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5076 SMB_STRUCT_STAT *psbuf)
5078 uint32 file_type = IVAL(pdata,56);
5079 #if defined(HAVE_MAKEDEV)
5080 uint32 dev_major = IVAL(pdata,60);
5081 uint32 dev_minor = IVAL(pdata,68);
5083 SMB_DEV_T dev = (SMB_DEV_T)0;
5084 uint32 raw_unixmode = IVAL(pdata,84);
5088 if (total_data < 100) {
5089 return NT_STATUS_INVALID_PARAMETER;
5092 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5093 if (!NT_STATUS_IS_OK(status)) {
5097 #if defined(HAVE_MAKEDEV)
5098 dev = makedev(dev_major, dev_minor);
5101 switch (file_type) {
5102 #if defined(S_IFIFO)
5103 case UNIX_TYPE_FIFO:
5104 unixmode |= S_IFIFO;
5107 #if defined(S_IFSOCK)
5108 case UNIX_TYPE_SOCKET:
5109 unixmode |= S_IFSOCK;
5112 #if defined(S_IFCHR)
5113 case UNIX_TYPE_CHARDEV:
5114 unixmode |= S_IFCHR;
5117 #if defined(S_IFBLK)
5118 case UNIX_TYPE_BLKDEV:
5119 unixmode |= S_IFBLK;
5123 return NT_STATUS_INVALID_PARAMETER;
5126 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5127 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5129 /* Ok - do the mknod. */
5130 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5131 return map_nt_error_from_unix(errno);
5134 /* If any of the other "set" calls fail we
5135 * don't want to end up with a half-constructed mknod.
5138 if (lp_inherit_perms(SNUM(conn))) {
5140 conn, parent_dirname(fname),
5144 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5145 status = map_nt_error_from_unix(errno);
5146 SMB_VFS_UNLINK(conn,fname);
5149 return NT_STATUS_OK;
5152 /****************************************************************************
5153 Deal with SMB_SET_FILE_UNIX_BASIC.
5154 ****************************************************************************/
5156 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5161 SMB_STRUCT_STAT *psbuf)
5163 struct timespec ts[2];
5164 uint32 raw_unixmode;
5167 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5168 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5169 NTSTATUS status = NT_STATUS_OK;
5170 BOOL delete_on_fail = False;
5171 enum perm_type ptype;
5173 if (total_data < 100) {
5174 return NT_STATUS_INVALID_PARAMETER;
5177 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5178 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5179 size=IVAL(pdata,0); /* first 8 Bytes are size */
5180 #ifdef LARGE_SMB_OFF_T
5181 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5182 #else /* LARGE_SMB_OFF_T */
5183 if (IVAL(pdata,4) != 0) {
5184 /* more than 32 bits? */
5185 return NT_STATUS_INVALID_PARAMETER;
5187 #endif /* LARGE_SMB_OFF_T */
5190 ts[0] = interpret_long_date(pdata+24); /* access_time */
5191 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5192 set_owner = (uid_t)IVAL(pdata,40);
5193 set_grp = (gid_t)IVAL(pdata,48);
5194 raw_unixmode = IVAL(pdata,84);
5196 if (VALID_STAT(*psbuf)) {
5197 if (S_ISDIR(psbuf->st_mode)) {
5198 ptype = PERM_EXISTING_DIR;
5200 ptype = PERM_EXISTING_FILE;
5203 ptype = PERM_NEW_FILE;
5206 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5207 if (!NT_STATUS_IS_OK(status)) {
5211 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5212 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5213 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5215 if (!VALID_STAT(*psbuf)) {
5217 * The only valid use of this is to create character and block
5218 * devices, and named pipes. This is deprecated (IMHO) and
5219 * a new info level should be used for mknod. JRA.
5222 status = smb_unix_mknod(conn,
5227 if (!NT_STATUS_IS_OK(status)) {
5231 /* Ensure we don't try and change anything else. */
5232 raw_unixmode = SMB_MODE_NO_CHANGE;
5233 size = get_file_size(*psbuf);
5234 ts[0] = get_atimespec(psbuf);
5235 ts[1] = get_mtimespec(psbuf);
5237 * We continue here as we might want to change the
5240 delete_on_fail = True;
5244 /* Horrible backwards compatibility hack as an old server bug
5245 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5249 size = get_file_size(*psbuf);
5254 * Deal with the UNIX specific mode set.
5257 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5258 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5259 (unsigned int)unixmode, fname ));
5260 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5261 return map_nt_error_from_unix(errno);
5266 * Deal with the UNIX specific uid set.
5269 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5270 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5271 (unsigned int)set_owner, fname ));
5272 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5273 status = map_nt_error_from_unix(errno);
5274 if (delete_on_fail) {
5275 SMB_VFS_UNLINK(conn,fname);
5282 * Deal with the UNIX specific gid set.
5285 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5286 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5287 (unsigned int)set_owner, fname ));
5288 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5289 status = map_nt_error_from_unix(errno);
5290 if (delete_on_fail) {
5291 SMB_VFS_UNLINK(conn,fname);
5297 /* Deal with any size changes. */
5299 status = smb_set_file_size(conn,
5304 if (!NT_STATUS_IS_OK(status)) {
5308 /* Deal with any time changes. */
5310 return smb_set_file_time(conn,
5317 /****************************************************************************
5318 Deal with SMB_SET_FILE_UNIX_INFO2.
5319 ****************************************************************************/
5321 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5326 SMB_STRUCT_STAT *psbuf)
5332 if (total_data < 116) {
5333 return NT_STATUS_INVALID_PARAMETER;
5336 /* Start by setting all the fields that are common between UNIX_BASIC
5339 status = smb_set_file_unix_basic(conn, pdata, total_data,
5341 if (!NT_STATUS_IS_OK(status)) {
5345 smb_fflags = IVAL(pdata, 108);
5346 smb_fmask = IVAL(pdata, 112);
5348 /* NB: We should only attempt to alter the file flags if the client
5349 * sends a non-zero mask.
5351 if (smb_fmask != 0) {
5352 int stat_fflags = 0;
5354 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5356 /* Client asked to alter a flag we don't understand. */
5357 return NT_STATUS_INVALID_PARAMETER;
5360 if (fsp && fsp->fh->fd != -1) {
5361 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5362 return NT_STATUS_NOT_SUPPORTED;
5364 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5365 return map_nt_error_from_unix(errno);
5370 /* XXX: need to add support for changing the create_time here. You
5371 * can do this for paths on Darwin with setattrlist(2). The right way
5372 * to hook this up is probably by extending the VFS utimes interface.
5375 return NT_STATUS_OK;
5378 /****************************************************************************
5379 Create a directory with POSIX semantics.
5380 ****************************************************************************/
5382 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5386 SMB_STRUCT_STAT *psbuf,
5387 int *pdata_return_size)
5389 NTSTATUS status = NT_STATUS_OK;
5390 uint32 raw_unixmode = 0;
5391 uint32 mod_unixmode = 0;
5392 mode_t unixmode = (mode_t)0;
5393 files_struct *fsp = NULL;
5394 uint16 info_level_return = 0;
5396 char *pdata = *ppdata;
5398 if (total_data < 18) {
5399 return NT_STATUS_INVALID_PARAMETER;
5402 raw_unixmode = IVAL(pdata,8);
5403 /* Next 4 bytes are not yet defined. */
5405 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5406 if (!NT_STATUS_IS_OK(status)) {
5410 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5412 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5413 fname, (unsigned int)unixmode ));
5415 status = open_directory(conn,
5418 FILE_READ_ATTRIBUTES, /* Just a stat open */
5419 FILE_SHARE_NONE, /* Ignored for stat opens */
5426 if (NT_STATUS_IS_OK(status)) {
5427 close_file(fsp, NORMAL_CLOSE);
5430 info_level_return = SVAL(pdata,16);
5432 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5433 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5434 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5435 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5437 *pdata_return_size = 12;
5440 /* Realloc the data size */
5441 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5442 if (*ppdata == NULL) {
5443 *pdata_return_size = 0;
5444 return NT_STATUS_NO_MEMORY;
5448 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5449 SSVAL(pdata,2,0); /* No fnum. */
5450 SIVAL(pdata,4,info); /* Was directory created. */
5452 switch (info_level_return) {
5453 case SMB_QUERY_FILE_UNIX_BASIC:
5454 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5455 SSVAL(pdata,10,0); /* Padding. */
5456 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5458 case SMB_QUERY_FILE_UNIX_INFO2:
5459 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5460 SSVAL(pdata,10,0); /* Padding. */
5461 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5464 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5465 SSVAL(pdata,10,0); /* Padding. */
5472 /****************************************************************************
5473 Open/Create a file with POSIX semantics.
5474 ****************************************************************************/
5476 static NTSTATUS smb_posix_open(connection_struct *conn,
5480 SMB_STRUCT_STAT *psbuf,
5481 int *pdata_return_size)
5483 BOOL extended_oplock_granted = False;
5484 char *pdata = *ppdata;
5486 uint32 wire_open_mode = 0;
5487 uint32 raw_unixmode = 0;
5488 uint32 mod_unixmode = 0;
5489 uint32 create_disp = 0;
5490 uint32 access_mask = 0;
5491 uint32 create_options = 0;
5492 NTSTATUS status = NT_STATUS_OK;
5493 mode_t unixmode = (mode_t)0;
5494 files_struct *fsp = NULL;
5495 int oplock_request = 0;
5497 uint16 info_level_return = 0;
5499 if (total_data < 18) {
5500 return NT_STATUS_INVALID_PARAMETER;
5503 flags = IVAL(pdata,0);
5504 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5505 if (oplock_request) {
5506 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5509 wire_open_mode = IVAL(pdata,4);
5511 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5512 return smb_posix_mkdir(conn,
5520 switch (wire_open_mode & SMB_ACCMODE) {
5522 access_mask = FILE_READ_DATA;
5525 access_mask = FILE_WRITE_DATA;
5528 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5531 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5532 (unsigned int)wire_open_mode ));
5533 return NT_STATUS_INVALID_PARAMETER;
5536 wire_open_mode &= ~SMB_ACCMODE;
5538 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5539 create_disp = FILE_CREATE;
5540 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5541 create_disp = FILE_OVERWRITE_IF;
5542 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5543 create_disp = FILE_OPEN_IF;
5545 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5546 (unsigned int)wire_open_mode ));
5547 return NT_STATUS_INVALID_PARAMETER;
5550 raw_unixmode = IVAL(pdata,8);
5551 /* Next 4 bytes are not yet defined. */
5553 status = unix_perms_from_wire(conn,
5556 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5559 if (!NT_STATUS_IS_OK(status)) {
5563 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5565 if (wire_open_mode & SMB_O_SYNC) {
5566 create_options |= FILE_WRITE_THROUGH;
5568 if (wire_open_mode & SMB_O_APPEND) {
5569 access_mask |= FILE_APPEND_DATA;
5571 if (wire_open_mode & SMB_O_DIRECT) {
5572 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5575 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5577 (unsigned int)wire_open_mode,
5578 (unsigned int)unixmode ));
5580 status = open_file_ntcreate(conn,
5584 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5586 0, /* no create options yet. */
5592 if (!NT_STATUS_IS_OK(status)) {
5596 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5597 extended_oplock_granted = True;
5600 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5601 extended_oplock_granted = True;
5604 info_level_return = SVAL(pdata,16);
5606 /* Allocate the correct return size. */
5608 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5609 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5610 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5611 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5613 *pdata_return_size = 12;
5616 /* Realloc the data size */
5617 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5618 if (*ppdata == NULL) {
5619 close_file(fsp,ERROR_CLOSE);
5620 *pdata_return_size = 0;
5621 return NT_STATUS_NO_MEMORY;
5625 if (extended_oplock_granted) {
5626 if (flags & REQUEST_BATCH_OPLOCK) {
5627 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5629 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5631 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5632 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5634 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5637 SSVAL(pdata,2,fsp->fnum);
5638 SIVAL(pdata,4,info); /* Was file created etc. */
5640 switch (info_level_return) {
5641 case SMB_QUERY_FILE_UNIX_BASIC:
5642 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5643 SSVAL(pdata,10,0); /* padding. */
5644 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5646 case SMB_QUERY_FILE_UNIX_INFO2:
5647 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5648 SSVAL(pdata,10,0); /* padding. */
5649 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5652 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5653 SSVAL(pdata,10,0); /* padding. */
5656 return NT_STATUS_OK;
5659 /****************************************************************************
5660 Delete a file with POSIX semantics.
5661 ****************************************************************************/
5663 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5667 SMB_STRUCT_STAT *psbuf)
5669 NTSTATUS status = NT_STATUS_OK;
5670 files_struct *fsp = NULL;
5674 if (total_data < 2) {
5675 return NT_STATUS_INVALID_PARAMETER;
5678 flags = SVAL(pdata,0);
5680 if (!VALID_STAT(*psbuf)) {
5681 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5684 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5685 !VALID_STAT_OF_DIR(*psbuf)) {
5686 return NT_STATUS_NOT_A_DIRECTORY;
5689 DEBUG(10,("smb_posix_unlink: %s %s\n",
5690 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5693 if (VALID_STAT_OF_DIR(*psbuf)) {
5694 status = open_directory(conn,
5698 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5700 FILE_DELETE_ON_CLOSE,
5701 FILE_FLAG_POSIX_SEMANTICS|0777,
5707 status = open_file_ntcreate(conn,
5711 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5714 FILE_FLAG_POSIX_SEMANTICS|0777,
5715 0, /* No oplock, but break existing ones. */
5719 * For file opens we must set the delete on close
5723 if (!NT_STATUS_IS_OK(status)) {
5727 status = smb_set_file_disposition_info(conn,
5735 if (!NT_STATUS_IS_OK(status)) {
5738 return close_file(fsp, NORMAL_CLOSE);
5741 /****************************************************************************
5742 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5743 ****************************************************************************/
5745 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5746 unsigned int tran_call,
5747 char **pparams, int total_params, char **ppdata, int total_data,
5748 unsigned int max_data_bytes)
5750 char *params = *pparams;
5751 char *pdata = *ppdata;
5753 SMB_STRUCT_STAT sbuf;
5755 files_struct *fsp = NULL;
5756 NTSTATUS status = NT_STATUS_OK;
5757 int data_return_size = 0;
5760 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5765 if (tran_call == TRANSACT2_SETFILEINFO) {
5766 if (total_params < 4) {
5767 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5770 fsp = file_fsp(params,0);
5771 info_level = SVAL(params,2);
5773 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5775 * This is actually a SETFILEINFO on a directory
5776 * handle (returned from an NT SMB). NT5.0 seems
5777 * to do this call. JRA.
5779 pstrcpy(fname, fsp->fsp_name);
5780 if (INFO_LEVEL_IS_UNIX(info_level)) {
5781 /* Always do lstat for UNIX calls. */
5782 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5783 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5784 return UNIXERROR(ERRDOS,ERRbadpath);
5787 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5788 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5789 return UNIXERROR(ERRDOS,ERRbadpath);
5792 } else if (fsp && fsp->print_file) {
5794 * Doing a DELETE_ON_CLOSE should cancel a print job.
5796 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5797 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5799 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5802 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5805 return (UNIXERROR(ERRDOS,ERRbadpath));
5808 * Original code - this is an open file.
5810 CHECK_FSP(fsp,conn);
5812 pstrcpy(fname, fsp->fsp_name);
5814 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5815 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5816 return(UNIXERROR(ERRDOS,ERRbadfid));
5821 if (total_params < 7) {
5822 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5825 info_level = SVAL(params,0);
5826 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5827 if (!NT_STATUS_IS_OK(status)) {
5828 return ERROR_NT(status);
5831 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5832 if (!NT_STATUS_IS_OK(status)) {
5833 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5834 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5836 return ERROR_NT(status);
5839 status = unix_convert(conn, fname, False, NULL, &sbuf);
5840 if (!NT_STATUS_IS_OK(status)) {
5841 return ERROR_NT(status);
5844 status = check_name(conn, fname);
5845 if (!NT_STATUS_IS_OK(status)) {
5846 return ERROR_NT(status);
5849 if (INFO_LEVEL_IS_UNIX(info_level)) {
5851 * For CIFS UNIX extensions the target name may not exist.
5854 /* Always do lstat for UNIX calls. */
5855 SMB_VFS_LSTAT(conn,fname,&sbuf);
5857 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5858 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5859 return UNIXERROR(ERRDOS,ERRbadpath);
5863 if (!CAN_WRITE(conn)) {
5864 return ERROR_DOS(ERRSRV,ERRaccess);
5867 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5868 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5871 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5872 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5874 /* Realloc the parameter size */
5875 *pparams = (char *)SMB_REALLOC(*pparams,2);
5876 if (*pparams == NULL) {
5877 return ERROR_NT(NT_STATUS_NO_MEMORY);
5883 if (fsp && !null_timespec(fsp->pending_modtime)) {
5884 /* the pending modtime overrides the current modtime */
5885 set_mtimespec(&sbuf, fsp->pending_modtime);
5888 switch (info_level) {
5890 case SMB_INFO_STANDARD:
5892 status = smb_set_info_standard(conn,
5901 case SMB_INFO_SET_EA:
5903 status = smb_info_set_ea(conn,
5911 case SMB_SET_FILE_BASIC_INFO:
5912 case SMB_FILE_BASIC_INFORMATION:
5914 status = smb_set_file_basic_info(conn,
5923 case SMB_FILE_ALLOCATION_INFORMATION:
5924 case SMB_SET_FILE_ALLOCATION_INFO:
5926 status = smb_set_file_allocation_info(conn,
5935 case SMB_FILE_END_OF_FILE_INFORMATION:
5936 case SMB_SET_FILE_END_OF_FILE_INFO:
5938 status = smb_set_file_end_of_file_info(conn,
5947 case SMB_FILE_DISPOSITION_INFORMATION:
5948 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5951 /* JRA - We used to just ignore this on a path ?
5952 * Shouldn't this be invalid level on a pathname
5955 if (tran_call != TRANSACT2_SETFILEINFO) {
5956 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5959 status = smb_set_file_disposition_info(conn,
5968 case SMB_FILE_POSITION_INFORMATION:
5970 status = smb_file_position_information(conn,
5977 /* From tridge Samba4 :
5978 * MODE_INFORMATION in setfileinfo (I have no
5979 * idea what "mode information" on a file is - it takes a value of 0,
5980 * 2, 4 or 6. What could it be?).
5983 case SMB_FILE_MODE_INFORMATION:
5985 status = smb_file_mode_information(conn,
5992 * CIFS UNIX extensions.
5995 case SMB_SET_FILE_UNIX_BASIC:
5997 status = smb_set_file_unix_basic(conn,
6006 case SMB_SET_FILE_UNIX_INFO2:
6008 status = smb_set_file_unix_info2(conn,
6017 case SMB_SET_FILE_UNIX_LINK:
6019 if (tran_call != TRANSACT2_SETPATHINFO) {
6020 /* We must have a pathname for this. */
6021 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6023 status = smb_set_file_unix_link(conn,
6031 case SMB_SET_FILE_UNIX_HLINK:
6033 if (tran_call != TRANSACT2_SETPATHINFO) {
6034 /* We must have a pathname for this. */
6035 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6037 status = smb_set_file_unix_hlink(conn,
6046 case SMB_FILE_RENAME_INFORMATION:
6048 status = smb_file_rename_information(conn,
6058 #if defined(HAVE_POSIX_ACLS)
6059 case SMB_SET_POSIX_ACL:
6061 status = smb_set_posix_acl(conn,
6071 case SMB_SET_POSIX_LOCK:
6073 if (tran_call != TRANSACT2_SETFILEINFO) {
6074 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6076 status = smb_set_posix_lock(conn,
6085 case SMB_POSIX_PATH_OPEN:
6087 if (tran_call != TRANSACT2_SETPATHINFO) {
6088 /* We must have a pathname for this. */
6089 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6092 status = smb_posix_open(conn,
6101 case SMB_POSIX_PATH_UNLINK:
6103 if (tran_call != TRANSACT2_SETPATHINFO) {
6104 /* We must have a pathname for this. */
6105 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6108 status = smb_posix_unlink(conn,
6117 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6121 if (!NT_STATUS_IS_OK(status)) {
6122 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6123 /* We have re-scheduled this call. */
6126 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6127 /* We have re-scheduled this call. */
6130 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6131 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6133 return ERROR_NT(status);
6137 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6142 /****************************************************************************
6143 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6144 ****************************************************************************/
6146 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6147 char **pparams, int total_params, char **ppdata, int total_data,
6148 unsigned int max_data_bytes)
6150 char *params = *pparams;
6151 char *pdata = *ppdata;
6153 SMB_STRUCT_STAT sbuf;
6154 NTSTATUS status = NT_STATUS_OK;
6155 struct ea_list *ea_list = NULL;
6157 if (!CAN_WRITE(conn))
6158 return ERROR_DOS(ERRSRV,ERRaccess);
6160 if (total_params < 5) {
6161 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6164 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6165 if (!NT_STATUS_IS_OK(status)) {
6166 return ERROR_NT(status);
6169 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6171 status = unix_convert(conn, directory, False, NULL, &sbuf);
6172 if (!NT_STATUS_IS_OK(status)) {
6173 return ERROR_NT(status);
6176 status = check_name(conn, directory);
6177 if (!NT_STATUS_IS_OK(status)) {
6178 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6179 return ERROR_NT(status);
6182 /* Any data in this call is an EA list. */
6183 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6184 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6188 * OS/2 workplace shell seems to send SET_EA requests of "null"
6189 * length (4 bytes containing IVAL 4).
6190 * They seem to have no effect. Bug #3212. JRA.
6193 if (total_data != 4) {
6194 if (total_data < 10) {
6195 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6198 if (IVAL(pdata,0) > total_data) {
6199 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6200 IVAL(pdata,0), (unsigned int)total_data));
6201 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6204 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6207 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6209 } else if (IVAL(pdata,0) != 4) {
6210 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6213 status = create_directory(conn, directory);
6215 if (!NT_STATUS_IS_OK(status)) {
6216 return ERROR_NT(status);
6219 /* Try and set any given EA. */
6221 status = set_ea(conn, NULL, directory, ea_list);
6222 if (!NT_STATUS_IS_OK(status)) {
6223 return ERROR_NT(status);
6227 /* Realloc the parameter and data sizes */
6228 *pparams = (char *)SMB_REALLOC(*pparams,2);
6229 if(*pparams == NULL) {
6230 return ERROR_NT(NT_STATUS_NO_MEMORY);
6236 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6241 /****************************************************************************
6242 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6243 We don't actually do this - we just send a null response.
6244 ****************************************************************************/
6246 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6247 char **pparams, int total_params, char **ppdata, int total_data,
6248 unsigned int max_data_bytes)
6250 static uint16 fnf_handle = 257;
6251 char *params = *pparams;
6254 if (total_params < 6) {
6255 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6258 info_level = SVAL(params,4);
6259 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6261 switch (info_level) {
6266 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6269 /* Realloc the parameter and data sizes */
6270 *pparams = (char *)SMB_REALLOC(*pparams,6);
6271 if (*pparams == NULL) {
6272 return ERROR_NT(NT_STATUS_NO_MEMORY);
6276 SSVAL(params,0,fnf_handle);
6277 SSVAL(params,2,0); /* No changes */
6278 SSVAL(params,4,0); /* No EA errors */
6285 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6290 /****************************************************************************
6291 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6292 changes). Currently this does nothing.
6293 ****************************************************************************/
6295 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6296 char **pparams, int total_params, char **ppdata, int total_data,
6297 unsigned int max_data_bytes)
6299 char *params = *pparams;
6301 DEBUG(3,("call_trans2findnotifynext\n"));
6303 /* Realloc the parameter and data sizes */
6304 *pparams = (char *)SMB_REALLOC(*pparams,4);
6305 if (*pparams == NULL) {
6306 return ERROR_NT(NT_STATUS_NO_MEMORY);
6310 SSVAL(params,0,0); /* No changes */
6311 SSVAL(params,2,0); /* No EA errors */
6313 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6318 /****************************************************************************
6319 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6320 ****************************************************************************/
6322 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6323 char **pparams, int total_params, char **ppdata, int total_data,
6324 unsigned int max_data_bytes)
6326 char *params = *pparams;
6329 int max_referral_level;
6330 NTSTATUS status = NT_STATUS_OK;
6332 DEBUG(10,("call_trans2getdfsreferral\n"));
6334 if (total_params < 3) {
6335 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6338 max_referral_level = SVAL(params,0);
6340 if(!lp_host_msdfs())
6341 return ERROR_DOS(ERRDOS,ERRbadfunc);
6343 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6344 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6345 return ERROR_NT(status);
6347 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6348 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6353 #define LMCAT_SPL 0x53
6354 #define LMFUNC_GETJOBID 0x60
6356 /****************************************************************************
6357 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6358 ****************************************************************************/
6360 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6361 char **pparams, int total_params, char **ppdata, int total_data,
6362 unsigned int max_data_bytes)
6364 char *pdata = *ppdata;
6365 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6367 /* check for an invalid fid before proceeding */
6370 return(ERROR_DOS(ERRDOS,ERRbadfid));
6372 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6373 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6374 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6375 if (*ppdata == NULL) {
6376 return ERROR_NT(NT_STATUS_NO_MEMORY);
6380 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6381 CAN ACCEPT THIS IN UNICODE. JRA. */
6383 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6384 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6385 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6386 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6389 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6390 return ERROR_DOS(ERRSRV,ERRerror);
6394 /****************************************************************************
6395 Reply to a SMBfindclose (stop trans2 directory search).
6396 ****************************************************************************/
6398 int reply_findclose(connection_struct *conn,
6399 char *inbuf,char *outbuf,int length,int bufsize)
6402 int dptr_num=SVALS(inbuf,smb_vwv0);
6403 START_PROFILE(SMBfindclose);
6405 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6407 dptr_close(&dptr_num);
6409 outsize = set_message(inbuf, outbuf,0,0,False);
6411 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6413 END_PROFILE(SMBfindclose);
6417 /****************************************************************************
6418 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6419 ****************************************************************************/
6421 int reply_findnclose(connection_struct *conn,
6422 char *inbuf,char *outbuf,int length,int bufsize)
6426 START_PROFILE(SMBfindnclose);
6428 dptr_num = SVAL(inbuf,smb_vwv0);
6430 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6432 /* We never give out valid handles for a
6433 findnotifyfirst - so any dptr_num is ok here.
6436 outsize = set_message(inbuf, outbuf,0,0,False);
6438 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6440 END_PROFILE(SMBfindnclose);
6444 int handle_trans2(connection_struct *conn,
6445 struct trans_state *state,
6446 char *inbuf, char *outbuf, int size, int bufsize)
6450 if (Protocol >= PROTOCOL_NT1) {
6451 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6454 /* Now we must call the relevant TRANS2 function */
6455 switch(state->call) {
6456 case TRANSACT2_OPEN:
6458 START_PROFILE(Trans2_open);
6459 outsize = call_trans2open(
6460 conn, inbuf, outbuf, bufsize,
6461 &state->param, state->total_param,
6462 &state->data, state->total_data,
6463 state->max_data_return);
6464 END_PROFILE(Trans2_open);
6468 case TRANSACT2_FINDFIRST:
6470 START_PROFILE(Trans2_findfirst);
6471 outsize = call_trans2findfirst(
6472 conn, inbuf, outbuf, bufsize,
6473 &state->param, state->total_param,
6474 &state->data, state->total_data,
6475 state->max_data_return);
6476 END_PROFILE(Trans2_findfirst);
6480 case TRANSACT2_FINDNEXT:
6482 START_PROFILE(Trans2_findnext);
6483 outsize = call_trans2findnext(
6484 conn, inbuf, outbuf, size, bufsize,
6485 &state->param, state->total_param,
6486 &state->data, state->total_data,
6487 state->max_data_return);
6488 END_PROFILE(Trans2_findnext);
6492 case TRANSACT2_QFSINFO:
6494 START_PROFILE(Trans2_qfsinfo);
6495 outsize = call_trans2qfsinfo(
6496 conn, inbuf, outbuf, size, bufsize,
6497 &state->param, state->total_param,
6498 &state->data, state->total_data,
6499 state->max_data_return);
6500 END_PROFILE(Trans2_qfsinfo);
6504 case TRANSACT2_SETFSINFO:
6506 START_PROFILE(Trans2_setfsinfo);
6507 outsize = call_trans2setfsinfo(
6508 conn, inbuf, outbuf, size, bufsize,
6509 &state->param, state->total_param,
6510 &state->data, state->total_data,
6511 state->max_data_return);
6512 END_PROFILE(Trans2_setfsinfo);
6516 case TRANSACT2_QPATHINFO:
6517 case TRANSACT2_QFILEINFO:
6519 START_PROFILE(Trans2_qpathinfo);
6520 outsize = call_trans2qfilepathinfo(
6521 conn, inbuf, outbuf, size, bufsize, state->call,
6522 &state->param, state->total_param,
6523 &state->data, state->total_data,
6524 state->max_data_return);
6525 END_PROFILE(Trans2_qpathinfo);
6529 case TRANSACT2_SETPATHINFO:
6530 case TRANSACT2_SETFILEINFO:
6532 START_PROFILE(Trans2_setpathinfo);
6533 outsize = call_trans2setfilepathinfo(
6534 conn, inbuf, outbuf, size, bufsize, state->call,
6535 &state->param, state->total_param,
6536 &state->data, state->total_data,
6537 state->max_data_return);
6538 END_PROFILE(Trans2_setpathinfo);
6542 case TRANSACT2_FINDNOTIFYFIRST:
6544 START_PROFILE(Trans2_findnotifyfirst);
6545 outsize = call_trans2findnotifyfirst(
6546 conn, inbuf, outbuf, size, bufsize,
6547 &state->param, state->total_param,
6548 &state->data, state->total_data,
6549 state->max_data_return);
6550 END_PROFILE(Trans2_findnotifyfirst);
6554 case TRANSACT2_FINDNOTIFYNEXT:
6556 START_PROFILE(Trans2_findnotifynext);
6557 outsize = call_trans2findnotifynext(
6558 conn, inbuf, outbuf, size, bufsize,
6559 &state->param, state->total_param,
6560 &state->data, state->total_data,
6561 state->max_data_return);
6562 END_PROFILE(Trans2_findnotifynext);
6566 case TRANSACT2_MKDIR:
6568 START_PROFILE(Trans2_mkdir);
6569 outsize = call_trans2mkdir(
6570 conn, inbuf, outbuf, size, bufsize,
6571 &state->param, state->total_param,
6572 &state->data, state->total_data,
6573 state->max_data_return);
6574 END_PROFILE(Trans2_mkdir);
6578 case TRANSACT2_GET_DFS_REFERRAL:
6580 START_PROFILE(Trans2_get_dfs_referral);
6581 outsize = call_trans2getdfsreferral(
6582 conn, inbuf, outbuf, size, bufsize,
6583 &state->param, state->total_param,
6584 &state->data, state->total_data,
6585 state->max_data_return);
6586 END_PROFILE(Trans2_get_dfs_referral);
6590 case TRANSACT2_IOCTL:
6592 START_PROFILE(Trans2_ioctl);
6593 outsize = call_trans2ioctl(
6594 conn, inbuf, outbuf, size, bufsize,
6595 &state->param, state->total_param,
6596 &state->data, state->total_data,
6597 state->max_data_return);
6598 END_PROFILE(Trans2_ioctl);
6603 /* Error in request */
6604 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6605 outsize = ERROR_DOS(ERRSRV,ERRerror);
6611 /****************************************************************************
6612 Reply to a SMBtrans2.
6613 ****************************************************************************/
6615 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6616 int size, int bufsize)
6619 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6620 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6621 unsigned int psoff = SVAL(inbuf, smb_psoff);
6622 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6623 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6624 struct trans_state *state;
6627 START_PROFILE(SMBtrans2);
6629 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6630 if (!NT_STATUS_IS_OK(result)) {
6631 DEBUG(2, ("Got invalid trans2 request: %s\n",
6632 nt_errstr(result)));
6633 END_PROFILE(SMBtrans2);
6634 return ERROR_NT(result);
6637 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6638 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6639 && (tran_call != TRANSACT2_QFILEINFO)) {
6640 END_PROFILE(SMBtrans2);
6641 return ERROR_DOS(ERRSRV,ERRaccess);
6644 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6645 DEBUG(0, ("talloc failed\n"));
6646 END_PROFILE(SMBtrans2);
6647 return ERROR_NT(NT_STATUS_NO_MEMORY);
6650 state->cmd = SMBtrans2;
6652 state->mid = SVAL(inbuf, smb_mid);
6653 state->vuid = SVAL(inbuf, smb_uid);
6654 state->setup_count = SVAL(inbuf, smb_suwcnt);
6655 state->setup = NULL;
6656 state->total_param = SVAL(inbuf, smb_tpscnt);
6657 state->param = NULL;
6658 state->total_data = SVAL(inbuf, smb_tdscnt);
6660 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6661 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6662 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6663 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6664 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6666 state->call = tran_call;
6668 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6669 is so as a sanity check */
6670 if (state->setup_count != 1) {
6672 * Need to have rc=0 for ioctl to get job id for OS/2.
6673 * Network printing will fail if function is not successful.
6674 * Similar function in reply.c will be used if protocol
6675 * is LANMAN1.0 instead of LM1.2X002.
6676 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6677 * outbuf doesn't have to be set(only job id is used).
6679 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6680 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6681 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6682 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6684 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6685 DEBUG(2,("Transaction is %d\n",tran_call));
6687 END_PROFILE(SMBtrans2);
6688 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6692 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6695 if (state->total_data) {
6696 /* Can't use talloc here, the core routines do realloc on the
6697 * params and data. */
6698 state->data = (char *)SMB_MALLOC(state->total_data);
6699 if (state->data == NULL) {
6700 DEBUG(0,("reply_trans2: data malloc fail for %u "
6701 "bytes !\n", (unsigned int)state->total_data));
6703 END_PROFILE(SMBtrans2);
6704 return(ERROR_DOS(ERRDOS,ERRnomem));
6706 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6708 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6709 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6712 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6715 if (state->total_param) {
6716 /* Can't use talloc here, the core routines do realloc on the
6717 * params and data. */
6718 state->param = (char *)SMB_MALLOC(state->total_param);
6719 if (state->param == NULL) {
6720 DEBUG(0,("reply_trans: param malloc fail for %u "
6721 "bytes !\n", (unsigned int)state->total_param));
6722 SAFE_FREE(state->data);
6724 END_PROFILE(SMBtrans2);
6725 return(ERROR_DOS(ERRDOS,ERRnomem));
6727 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6729 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6730 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6733 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6736 state->received_data = dscnt;
6737 state->received_param = pscnt;
6739 if ((state->received_param == state->total_param) &&
6740 (state->received_data == state->total_data)) {
6742 outsize = handle_trans2(conn, state, inbuf, outbuf,
6744 SAFE_FREE(state->data);
6745 SAFE_FREE(state->param);
6747 END_PROFILE(SMBtrans2);
6751 DLIST_ADD(conn->pending_trans, state);
6753 /* We need to send an interim response then receive the rest
6754 of the parameter/data bytes */
6755 outsize = set_message(inbuf, outbuf,0,0,False);
6757 END_PROFILE(SMBtrans2);
6762 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6763 SAFE_FREE(state->data);
6764 SAFE_FREE(state->param);
6766 END_PROFILE(SMBtrans2);
6767 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6771 /****************************************************************************
6772 Reply to a SMBtranss2
6773 ****************************************************************************/
6775 int reply_transs2(connection_struct *conn,
6776 char *inbuf,char *outbuf,int size,int bufsize)
6779 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6780 struct trans_state *state;
6782 START_PROFILE(SMBtranss2);
6786 for (state = conn->pending_trans; state != NULL;
6787 state = state->next) {
6788 if (state->mid == SVAL(inbuf,smb_mid)) {
6793 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6794 END_PROFILE(SMBtranss2);
6795 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6798 /* Revise state->total_param and state->total_data in case they have
6799 changed downwards */
6801 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6802 state->total_param = SVAL(inbuf, smb_tpscnt);
6803 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6804 state->total_data = SVAL(inbuf, smb_tdscnt);
6806 pcnt = SVAL(inbuf, smb_spscnt);
6807 poff = SVAL(inbuf, smb_spsoff);
6808 pdisp = SVAL(inbuf, smb_spsdisp);
6810 dcnt = SVAL(inbuf, smb_sdscnt);
6811 doff = SVAL(inbuf, smb_sdsoff);
6812 ddisp = SVAL(inbuf, smb_sdsdisp);
6814 state->received_param += pcnt;
6815 state->received_data += dcnt;
6817 if ((state->received_data > state->total_data) ||
6818 (state->received_param > state->total_param))
6822 if (pdisp+pcnt > state->total_param)
6824 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6826 if (pdisp > state->total_param)
6828 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6829 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6831 if (state->param + pdisp < state->param)
6834 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6839 if (ddisp+dcnt > state->total_data)
6841 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6843 if (ddisp > state->total_data)
6845 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6846 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6848 if (state->data + ddisp < state->data)
6851 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6855 if ((state->received_param < state->total_param) ||
6856 (state->received_data < state->total_data)) {
6857 END_PROFILE(SMBtranss2);
6861 /* construct_reply_common has done us the favor to pre-fill the
6862 * command field with SMBtranss2 which is wrong :-)
6864 SCVAL(outbuf,smb_com,SMBtrans2);
6866 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6868 DLIST_REMOVE(conn->pending_trans, state);
6869 SAFE_FREE(state->data);
6870 SAFE_FREE(state->param);
6874 END_PROFILE(SMBtranss2);
6875 return(ERROR_DOS(ERRSRV,ERRnosupport));
6878 END_PROFILE(SMBtranss2);
6883 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6884 DLIST_REMOVE(conn->pending_trans, state);
6885 SAFE_FREE(state->data);
6886 SAFE_FREE(state->param);
6888 END_PROFILE(SMBtranss2);
6889 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);