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)));
2562 case SMB_QUERY_POSIX_FS_INFO:
2565 vfs_statvfs_struct svfs;
2567 if (!lp_unix_extensions()) {
2568 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2571 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2575 SIVAL(pdata,0,svfs.OptimalTransferSize);
2576 SIVAL(pdata,4,svfs.BlockSize);
2577 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2578 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2579 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2580 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2581 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2582 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2583 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2585 } else if (rc == EOPNOTSUPP) {
2586 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2587 #endif /* EOPNOTSUPP */
2589 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2590 return ERROR_DOS(ERRSRV,ERRerror);
2595 case SMB_QUERY_POSIX_WHOAMI:
2601 if (!lp_unix_extensions()) {
2602 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2605 if (max_data_bytes < 40) {
2606 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2609 /* We ARE guest if global_sid_Builtin_Guests is
2610 * in our list of SIDs.
2612 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2613 current_user.nt_user_token)) {
2614 flags |= SMB_WHOAMI_GUEST;
2617 /* We are NOT guest if global_sid_Authenticated_Users
2618 * is in our list of SIDs.
2620 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2621 current_user.nt_user_token)) {
2622 flags &= ~SMB_WHOAMI_GUEST;
2625 /* NOTE: 8 bytes for UID/GID, irrespective of native
2626 * platform size. This matches
2627 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2629 data_len = 4 /* flags */
2636 + 4 /* pad/reserved */
2637 + (current_user.ut.ngroups * 8)
2639 + (current_user.nt_user_token->num_sids *
2643 SIVAL(pdata, 0, flags);
2644 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2645 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2646 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2649 if (data_len >= max_data_bytes) {
2650 /* Potential overflow, skip the GIDs and SIDs. */
2652 SIVAL(pdata, 24, 0); /* num_groups */
2653 SIVAL(pdata, 28, 0); /* num_sids */
2654 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2655 SIVAL(pdata, 36, 0); /* reserved */
2661 SIVAL(pdata, 24, current_user.ut.ngroups);
2663 current_user.nt_user_token->num_sids);
2665 /* We walk the SID list twice, but this call is fairly
2666 * infrequent, and I don't expect that it's performance
2667 * sensitive -- jpeach
2669 for (i = 0, sid_bytes = 0;
2670 i < current_user.nt_user_token->num_sids; ++i) {
2672 sid_size(¤t_user.nt_user_token->user_sids[i]);
2675 /* SID list byte count */
2676 SIVAL(pdata, 32, sid_bytes);
2678 /* 4 bytes pad/reserved - must be zero */
2679 SIVAL(pdata, 36, 0);
2683 for (i = 0; i < current_user.ut.ngroups; ++i) {
2684 SBIG_UINT(pdata, data_len,
2685 (SMB_BIG_UINT)current_user.ut.groups[i]);
2691 i < current_user.nt_user_token->num_sids; ++i) {
2693 sid_size(¤t_user.nt_user_token->user_sids[i]);
2695 sid_linearize(pdata + data_len, sid_len,
2696 ¤t_user.nt_user_token->user_sids[i]);
2697 data_len += sid_len;
2703 case SMB_MAC_QUERY_FS_INFO:
2705 * Thursby MAC extension... ONLY on NTFS filesystems
2706 * once we do streams then we don't need this
2708 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2710 SIVAL(pdata,84,0x100); /* Don't support mac... */
2715 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2719 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2721 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2726 /****************************************************************************
2727 Reply to a TRANS2_SETFSINFO (set filesystem info).
2728 ****************************************************************************/
2730 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2731 char **pparams, int total_params, char **ppdata, int total_data,
2732 unsigned int max_data_bytes)
2734 char *pdata = *ppdata;
2735 char *params = *pparams;
2739 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2742 if (total_params < 4) {
2743 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2745 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2748 info_level = SVAL(params,2);
2750 switch(info_level) {
2751 case SMB_SET_CIFS_UNIX_INFO:
2753 uint16 client_unix_major;
2754 uint16 client_unix_minor;
2755 uint32 client_unix_cap_low;
2756 uint32 client_unix_cap_high;
2758 if (!lp_unix_extensions()) {
2759 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2762 /* There should be 12 bytes of capabilities set. */
2763 if (total_data < 8) {
2764 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2766 client_unix_major = SVAL(pdata,0);
2767 client_unix_minor = SVAL(pdata,2);
2768 client_unix_cap_low = IVAL(pdata,4);
2769 client_unix_cap_high = IVAL(pdata,8);
2770 /* Just print these values for now. */
2771 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2772 cap_low = 0x%x, cap_high = 0x%x\n",
2773 (unsigned int)client_unix_major,
2774 (unsigned int)client_unix_minor,
2775 (unsigned int)client_unix_cap_low,
2776 (unsigned int)client_unix_cap_high ));
2778 /* Here is where we must switch to posix pathname processing... */
2779 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2780 lp_set_posix_pathnames();
2781 mangle_change_to_posix();
2784 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2785 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2786 /* Client that knows how to do posix locks,
2787 * but not posix open/mkdir operations. Set a
2788 * default type for read/write checks. */
2790 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2795 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2798 size_t param_len = 0;
2799 size_t data_len = total_data;
2801 if (!lp_unix_extensions()) {
2802 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2805 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2807 status = srv_request_encryption_setup(conn,
2808 (unsigned char **)ppdata,
2810 (unsigned char **)pparams,
2814 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2815 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2816 } else if (!NT_STATUS_IS_OK(status)) {
2817 return ERROR_NT(status);
2820 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2822 if (NT_STATUS_IS_OK(status)) {
2823 /* Server-side transport encryption is now *on*. */
2824 status = srv_encryption_start(conn);
2825 if (!NT_STATUS_IS_OK(status)) {
2826 exit_server_cleanly("Failure in setting up encrypted transport");
2831 case SMB_FS_QUOTA_INFORMATION:
2833 files_struct *fsp = NULL;
2834 SMB_NTQUOTA_STRUCT quotas;
2836 ZERO_STRUCT(quotas);
2839 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2840 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2841 lp_servicename(SNUM(conn)),conn->user));
2842 return ERROR_DOS(ERRSRV,ERRaccess);
2845 /* note: normaly there're 48 bytes,
2846 * but we didn't use the last 6 bytes for now
2849 fsp = file_fsp(params,0);
2850 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2851 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2852 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2855 if (total_data < 42) {
2856 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2861 /* unknown_1 24 NULL bytes in pdata*/
2863 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2864 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2865 #ifdef LARGE_SMB_OFF_T
2866 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2867 #else /* LARGE_SMB_OFF_T */
2868 if ((IVAL(pdata,28) != 0)&&
2869 ((quotas.softlim != 0xFFFFFFFF)||
2870 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2871 /* more than 32 bits? */
2872 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2874 #endif /* LARGE_SMB_OFF_T */
2876 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2877 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2878 #ifdef LARGE_SMB_OFF_T
2879 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2880 #else /* LARGE_SMB_OFF_T */
2881 if ((IVAL(pdata,36) != 0)&&
2882 ((quotas.hardlim != 0xFFFFFFFF)||
2883 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2884 /* more than 32 bits? */
2885 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2887 #endif /* LARGE_SMB_OFF_T */
2889 /* quota_flags 2 bytes **/
2890 quotas.qflags = SVAL(pdata,40);
2892 /* unknown_2 6 NULL bytes follow*/
2894 /* now set the quotas */
2895 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2896 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2897 return ERROR_DOS(ERRSRV,ERRerror);
2903 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2905 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2910 * sending this reply works fine,
2911 * but I'm not sure it's the same
2912 * like windows do...
2915 outsize = set_message(inbuf, outbuf,10,0,True);
2920 #if defined(HAVE_POSIX_ACLS)
2921 /****************************************************************************
2922 Utility function to count the number of entries in a POSIX acl.
2923 ****************************************************************************/
2925 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2927 unsigned int ace_count = 0;
2928 int entry_id = SMB_ACL_FIRST_ENTRY;
2929 SMB_ACL_ENTRY_T entry;
2931 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2933 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2934 entry_id = SMB_ACL_NEXT_ENTRY;
2941 /****************************************************************************
2942 Utility function to marshall a POSIX acl into wire format.
2943 ****************************************************************************/
2945 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2947 int entry_id = SMB_ACL_FIRST_ENTRY;
2948 SMB_ACL_ENTRY_T entry;
2950 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2951 SMB_ACL_TAG_T tagtype;
2952 SMB_ACL_PERMSET_T permset;
2953 unsigned char perms = 0;
2954 unsigned int own_grp;
2957 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2958 entry_id = SMB_ACL_NEXT_ENTRY;
2961 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2962 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2966 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2967 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2971 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2972 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2973 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2975 SCVAL(pdata,1,perms);
2978 case SMB_ACL_USER_OBJ:
2979 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2980 own_grp = (unsigned int)pst->st_uid;
2981 SIVAL(pdata,2,own_grp);
2986 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2988 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2990 own_grp = (unsigned int)*puid;
2991 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2992 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2993 SIVAL(pdata,2,own_grp);
2997 case SMB_ACL_GROUP_OBJ:
2998 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2999 own_grp = (unsigned int)pst->st_gid;
3000 SIVAL(pdata,2,own_grp);
3005 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3007 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3009 own_grp = (unsigned int)*pgid;
3010 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3011 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3012 SIVAL(pdata,2,own_grp);
3017 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3018 SIVAL(pdata,2,0xFFFFFFFF);
3019 SIVAL(pdata,6,0xFFFFFFFF);
3022 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3023 SIVAL(pdata,2,0xFFFFFFFF);
3024 SIVAL(pdata,6,0xFFFFFFFF);
3027 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3030 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3037 /****************************************************************************
3038 Store the FILE_UNIX_BASIC info.
3039 ****************************************************************************/
3041 static char *store_file_unix_basic(connection_struct *conn,
3044 const SMB_STRUCT_STAT *psbuf)
3046 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3047 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3049 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3052 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3055 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3056 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3057 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3060 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3064 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3068 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3071 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3075 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3079 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3082 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3086 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3093 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3094 * the chflags(2) (or equivalent) flags.
3096 * XXX: this really should be behind the VFS interface. To do this, we would
3097 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3098 * Each VFS module could then implement it's own mapping as appropriate for the
3099 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3101 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3105 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3109 { UF_IMMUTABLE, EXT_IMMUTABLE },
3113 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3117 { UF_HIDDEN, EXT_HIDDEN },
3120 /* Do not remove. We need to guarantee that this array has at least one
3121 * entry to build on HP-UX.
3127 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3128 uint32 *smb_fflags, uint32 *smb_fmask)
3130 #ifdef HAVE_STAT_ST_FLAGS
3133 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3134 *smb_fmask |= info2_flags_map[i].smb_fflag;
3135 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3136 *smb_fflags |= info2_flags_map[i].smb_fflag;
3139 #endif /* HAVE_STAT_ST_FLAGS */
3142 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3143 const uint32 smb_fflags,
3144 const uint32 smb_fmask,
3147 #ifdef HAVE_STAT_ST_FLAGS
3148 uint32 max_fmask = 0;
3151 *stat_fflags = psbuf->st_flags;
3153 /* For each flags requested in smb_fmask, check the state of the
3154 * corresponding flag in smb_fflags and set or clear the matching
3158 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3159 max_fmask |= info2_flags_map[i].smb_fflag;
3160 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3161 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3162 *stat_fflags |= info2_flags_map[i].stat_fflag;
3164 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3169 /* If smb_fmask is asking to set any bits that are not supported by
3170 * our flag mappings, we should fail.
3172 if ((smb_fmask & max_fmask) != smb_fmask) {
3179 #endif /* HAVE_STAT_ST_FLAGS */
3183 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3184 * of file flags and birth (create) time.
3186 static char *store_file_unix_basic_info2(connection_struct *conn,
3189 const SMB_STRUCT_STAT *psbuf)
3191 uint32 file_flags = 0;
3192 uint32 flags_mask = 0;
3194 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3196 /* Create (birth) time 64 bit */
3197 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3200 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3201 SIVAL(pdata, 0, file_flags); /* flags */
3202 SIVAL(pdata, 4, flags_mask); /* mask */
3208 /****************************************************************************
3209 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3210 ****************************************************************************/
3212 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3213 unsigned int tran_call,
3214 char **pparams, int total_params, char **ppdata, int total_data,
3215 unsigned int max_data_bytes)
3217 char *params = *pparams;
3218 char *pdata = *ppdata;
3219 unsigned int data_size = 0;
3220 unsigned int param_size = 2;
3222 smb_np_struct *p_pipe = NULL;
3225 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3228 if (total_params < 4) {
3229 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3232 p_pipe = get_rpc_pipe_p(params,0);
3233 if (p_pipe == NULL) {
3234 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3237 info_level = SVAL(params,2);
3239 *pparams = (char *)SMB_REALLOC(*pparams,2);
3240 if (*pparams == NULL) {
3241 return ERROR_NT(NT_STATUS_NO_MEMORY);
3245 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3246 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3247 if (*ppdata == NULL ) {
3248 return ERROR_NT(NT_STATUS_NO_MEMORY);
3252 switch (info_level) {
3253 case SMB_FILE_STANDARD_INFORMATION:
3255 SOFF_T(pdata,0,4096LL);
3262 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3265 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3270 /****************************************************************************
3271 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3272 file name or file id).
3273 ****************************************************************************/
3275 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3276 unsigned int tran_call,
3277 char **pparams, int total_params, char **ppdata, int total_data,
3278 unsigned int max_data_bytes)
3280 char *params = *pparams;
3281 char *pdata = *ppdata;
3285 SMB_OFF_T file_size=0;
3286 SMB_BIG_UINT allocation_size=0;
3287 unsigned int data_size = 0;
3288 unsigned int param_size = 2;
3289 SMB_STRUCT_STAT sbuf;
3290 pstring fname, dos_fname;
3295 BOOL delete_pending = False;
3297 time_t create_time, mtime, atime;
3298 struct timespec create_time_ts, mtime_ts, atime_ts;
3299 files_struct *fsp = NULL;
3300 TALLOC_CTX *data_ctx = NULL;
3301 struct ea_list *ea_list = NULL;
3302 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3303 char *lock_data = NULL;
3306 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3310 if (tran_call == TRANSACT2_QFILEINFO) {
3311 if (total_params < 4) {
3312 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3316 return call_trans2qpipeinfo(conn,
3329 fsp = file_fsp(params,0);
3330 info_level = SVAL(params,2);
3332 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3334 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3335 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3338 if(fsp && (fsp->fake_file_handle)) {
3340 * This is actually for the QUOTA_FAKE_FILE --metze
3343 pstrcpy(fname, fsp->fsp_name);
3344 /* We know this name is ok, it's already passed the checks. */
3346 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3348 * This is actually a QFILEINFO on a directory
3349 * handle (returned from an NT SMB). NT5.0 seems
3350 * to do this call. JRA.
3352 /* We know this name is ok, it's already passed the checks. */
3353 pstrcpy(fname, fsp->fsp_name);
3355 if (INFO_LEVEL_IS_UNIX(info_level)) {
3356 /* Always do lstat for UNIX calls. */
3357 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3358 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3359 return UNIXERROR(ERRDOS,ERRbadpath);
3361 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3362 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3363 return UNIXERROR(ERRDOS,ERRbadpath);
3366 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3369 * Original code - this is an open file.
3371 CHECK_FSP(fsp,conn);
3373 pstrcpy(fname, fsp->fsp_name);
3374 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3375 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3376 return(UNIXERROR(ERRDOS,ERRbadfid));
3378 pos = fsp->fh->position_information;
3379 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3380 access_mask = fsp->access_mask;
3383 NTSTATUS status = NT_STATUS_OK;
3386 if (total_params < 7) {
3387 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3390 info_level = SVAL(params,0);
3392 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3394 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3395 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3398 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3399 if (!NT_STATUS_IS_OK(status)) {
3400 return ERROR_NT(status);
3403 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3404 if (!NT_STATUS_IS_OK(status)) {
3405 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3406 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3408 return ERROR_NT(status);
3411 status = unix_convert(conn, fname, False, NULL, &sbuf);
3412 if (!NT_STATUS_IS_OK(status)) {
3413 return ERROR_NT(status);
3415 status = check_name(conn, fname);
3416 if (!NT_STATUS_IS_OK(status)) {
3417 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3418 return ERROR_NT(status);
3421 if (INFO_LEVEL_IS_UNIX(info_level)) {
3422 /* Always do lstat for UNIX calls. */
3423 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3424 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3425 return UNIXERROR(ERRDOS,ERRbadpath);
3427 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3428 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3429 return UNIXERROR(ERRDOS,ERRbadpath);
3432 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3433 if (delete_pending) {
3434 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3438 nlink = sbuf.st_nlink;
3440 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3441 /* NTFS does not seem to count ".." */
3445 if ((nlink > 0) && delete_pending) {
3449 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3450 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3453 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3454 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3456 p = strrchr_m(fname,'/');
3462 mode = dos_mode(conn,fname,&sbuf);
3464 mode = FILE_ATTRIBUTE_NORMAL;
3466 fullpathname = fname;
3468 file_size = get_file_size(sbuf);
3470 /* Pull out any data sent here before we realloc. */
3471 switch (info_level) {
3472 case SMB_INFO_QUERY_EAS_FROM_LIST:
3474 /* Pull any EA list from the data portion. */
3477 if (total_data < 4) {
3478 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3480 ea_size = IVAL(pdata,0);
3482 if (total_data > 0 && ea_size != total_data) {
3483 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3484 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3485 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3488 if (!lp_ea_support(SNUM(conn))) {
3489 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3492 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3493 return ERROR_NT(NT_STATUS_NO_MEMORY);
3496 /* Pull out the list of names. */
3497 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3499 talloc_destroy(data_ctx);
3500 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3505 case SMB_QUERY_POSIX_LOCK:
3507 if (fsp == NULL || fsp->fh->fd == -1) {
3508 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3511 if (total_data != POSIX_LOCK_DATA_SIZE) {
3512 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3515 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3516 return ERROR_NT(NT_STATUS_NO_MEMORY);
3519 /* Copy the lock range data. */
3520 lock_data = (char *)talloc_memdup(
3521 data_ctx, pdata, total_data);
3523 talloc_destroy(data_ctx);
3524 return ERROR_NT(NT_STATUS_NO_MEMORY);
3531 *pparams = (char *)SMB_REALLOC(*pparams,2);
3532 if (*pparams == NULL) {
3533 talloc_destroy(data_ctx);
3534 return ERROR_NT(NT_STATUS_NO_MEMORY);
3538 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3539 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3540 if (*ppdata == NULL ) {
3541 talloc_destroy(data_ctx);
3542 return ERROR_NT(NT_STATUS_NO_MEMORY);
3546 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3547 mtime_ts = get_mtimespec(&sbuf);
3548 atime_ts = get_atimespec(&sbuf);
3550 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3553 if (!null_timespec(fsp->pending_modtime)) {
3554 /* the pending modtime overrides the current modtime */
3555 mtime_ts = fsp->pending_modtime;
3558 /* Do we have this path open ? */
3559 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3560 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3561 /* the pending modtime overrides the current modtime */
3562 mtime_ts = fsp1->pending_modtime;
3564 if (fsp1 && fsp1->initial_allocation_size) {
3565 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3569 if (lp_dos_filetime_resolution(SNUM(conn))) {
3570 dos_filetime_timespec(&create_time_ts);
3571 dos_filetime_timespec(&mtime_ts);
3572 dos_filetime_timespec(&atime_ts);
3575 create_time = convert_timespec_to_time_t(create_time_ts);
3576 mtime = convert_timespec_to_time_t(mtime_ts);
3577 atime = convert_timespec_to_time_t(atime_ts);
3579 /* NT expects the name to be in an exact form of the *full*
3580 filename. See the trans2 torture test */
3581 if (strequal(base_name,".")) {
3582 pstrcpy(dos_fname, "\\");
3584 pstr_sprintf(dos_fname, "\\%s", fname);
3585 string_replace(dos_fname, '/', '\\');
3588 switch (info_level) {
3589 case SMB_INFO_STANDARD:
3590 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3592 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3593 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3594 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3595 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3596 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3597 SSVAL(pdata,l1_attrFile,mode);
3600 case SMB_INFO_QUERY_EA_SIZE:
3602 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3603 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3605 srv_put_dos_date2(pdata,0,create_time);
3606 srv_put_dos_date2(pdata,4,atime);
3607 srv_put_dos_date2(pdata,8,mtime); /* write time */
3608 SIVAL(pdata,12,(uint32)file_size);
3609 SIVAL(pdata,16,(uint32)allocation_size);
3610 SSVAL(pdata,20,mode);
3611 SIVAL(pdata,22,ea_size);
3615 case SMB_INFO_IS_NAME_VALID:
3616 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3617 if (tran_call == TRANSACT2_QFILEINFO) {
3618 /* os/2 needs this ? really ?*/
3619 return ERROR_DOS(ERRDOS,ERRbadfunc);
3625 case SMB_INFO_QUERY_EAS_FROM_LIST:
3627 size_t total_ea_len = 0;
3628 struct ea_list *ea_file_list = NULL;
3630 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3632 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3633 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3635 if (!ea_list || (total_ea_len > data_size)) {
3636 talloc_destroy(data_ctx);
3638 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3642 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3643 talloc_destroy(data_ctx);
3647 case SMB_INFO_QUERY_ALL_EAS:
3649 /* We have data_size bytes to put EA's into. */
3650 size_t total_ea_len = 0;
3652 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3654 data_ctx = talloc_init("ea_ctx");
3656 return ERROR_NT(NT_STATUS_NO_MEMORY);
3659 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3660 if (!ea_list || (total_ea_len > data_size)) {
3661 talloc_destroy(data_ctx);
3663 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3667 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3668 talloc_destroy(data_ctx);
3672 case SMB_FILE_BASIC_INFORMATION:
3673 case SMB_QUERY_FILE_BASIC_INFO:
3675 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3676 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3677 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3679 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3683 put_long_date_timespec(pdata,create_time_ts);
3684 put_long_date_timespec(pdata+8,atime_ts);
3685 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3686 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3687 SIVAL(pdata,32,mode);
3689 DEBUG(5,("SMB_QFBI - "));
3690 DEBUG(5,("create: %s ", ctime(&create_time)));
3691 DEBUG(5,("access: %s ", ctime(&atime)));
3692 DEBUG(5,("write: %s ", ctime(&mtime)));
3693 DEBUG(5,("change: %s ", ctime(&mtime)));
3694 DEBUG(5,("mode: %x\n", mode));
3697 case SMB_FILE_STANDARD_INFORMATION:
3698 case SMB_QUERY_FILE_STANDARD_INFO:
3700 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3702 SOFF_T(pdata,0,allocation_size);
3703 SOFF_T(pdata,8,file_size);
3704 SIVAL(pdata,16,nlink);
3705 SCVAL(pdata,20,delete_pending?1:0);
3706 SCVAL(pdata,21,(mode&aDIR)?1:0);
3707 SSVAL(pdata,22,0); /* Padding. */
3710 case SMB_FILE_EA_INFORMATION:
3711 case SMB_QUERY_FILE_EA_INFO:
3713 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3714 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3716 SIVAL(pdata,0,ea_size);
3720 /* Get the 8.3 name - used if NT SMB was negotiated. */
3721 case SMB_QUERY_FILE_ALT_NAME_INFO:
3722 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3726 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3727 pstrcpy(short_name,base_name);
3728 /* Mangle if not already 8.3 */
3729 if(!mangle_is_8_3(short_name, True, conn->params)) {
3730 mangle_map(short_name,True,True,conn->params);
3732 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3733 data_size = 4 + len;
3738 case SMB_QUERY_FILE_NAME_INFO:
3740 this must be *exactly* right for ACLs on mapped drives to work
3742 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3743 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3744 data_size = 4 + len;
3748 case SMB_FILE_ALLOCATION_INFORMATION:
3749 case SMB_QUERY_FILE_ALLOCATION_INFO:
3750 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3752 SOFF_T(pdata,0,allocation_size);
3755 case SMB_FILE_END_OF_FILE_INFORMATION:
3756 case SMB_QUERY_FILE_END_OF_FILEINFO:
3757 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3759 SOFF_T(pdata,0,file_size);
3762 case SMB_QUERY_FILE_ALL_INFO:
3763 case SMB_FILE_ALL_INFORMATION:
3765 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3766 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3767 put_long_date_timespec(pdata,create_time_ts);
3768 put_long_date_timespec(pdata+8,atime_ts);
3769 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3770 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3771 SIVAL(pdata,32,mode);
3772 SIVAL(pdata,36,0); /* padding. */
3774 SOFF_T(pdata,0,allocation_size);
3775 SOFF_T(pdata,8,file_size);
3776 SIVAL(pdata,16,nlink);
3777 SCVAL(pdata,20,delete_pending);
3778 SCVAL(pdata,21,(mode&aDIR)?1:0);
3781 SIVAL(pdata,0,ea_size);
3782 pdata += 4; /* EA info */
3783 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3786 data_size = PTR_DIFF(pdata,(*ppdata));
3789 case SMB_FILE_INTERNAL_INFORMATION:
3790 /* This should be an index number - looks like
3793 I think this causes us to fail the IFSKIT
3794 BasicFileInformationTest. -tpot */
3796 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3797 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3798 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3802 case SMB_FILE_ACCESS_INFORMATION:
3803 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3804 SIVAL(pdata,0,access_mask);
3808 case SMB_FILE_NAME_INFORMATION:
3809 /* Pathname with leading '\'. */
3812 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3813 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3814 SIVAL(pdata,0,byte_len);
3815 data_size = 4 + byte_len;
3819 case SMB_FILE_DISPOSITION_INFORMATION:
3820 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3822 SCVAL(pdata,0,delete_pending);
3825 case SMB_FILE_POSITION_INFORMATION:
3826 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3828 SOFF_T(pdata,0,pos);
3831 case SMB_FILE_MODE_INFORMATION:
3832 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3833 SIVAL(pdata,0,mode);
3837 case SMB_FILE_ALIGNMENT_INFORMATION:
3838 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3839 SIVAL(pdata,0,0); /* No alignment needed. */
3845 * NT4 server just returns "invalid query" to this - if we try to answer
3846 * it then NTws gets a BSOD! (tridge).
3847 * W2K seems to want this. JRA.
3849 case SMB_QUERY_FILE_STREAM_INFO:
3851 case SMB_FILE_STREAM_INFORMATION:
3852 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3856 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3857 SIVAL(pdata,0,0); /* ??? */
3858 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3859 SOFF_T(pdata,8,file_size);
3860 SOFF_T(pdata,16,allocation_size);
3861 data_size = 24 + byte_len;
3865 case SMB_QUERY_COMPRESSION_INFO:
3866 case SMB_FILE_COMPRESSION_INFORMATION:
3867 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3868 SOFF_T(pdata,0,file_size);
3869 SIVAL(pdata,8,0); /* ??? */
3870 SIVAL(pdata,12,0); /* ??? */
3874 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3875 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3876 put_long_date_timespec(pdata,create_time_ts);
3877 put_long_date_timespec(pdata+8,atime_ts);
3878 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3879 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3880 SOFF_T(pdata,32,allocation_size);
3881 SOFF_T(pdata,40,file_size);
3882 SIVAL(pdata,48,mode);
3883 SIVAL(pdata,52,0); /* ??? */
3887 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3888 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3889 SIVAL(pdata,0,mode);
3895 * CIFS UNIX Extensions.
3898 case SMB_QUERY_FILE_UNIX_BASIC:
3900 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3901 data_size = PTR_DIFF(pdata,(*ppdata));
3905 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3907 for (i=0; i<100; i++)
3908 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3914 case SMB_QUERY_FILE_UNIX_INFO2:
3916 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3917 data_size = PTR_DIFF(pdata,(*ppdata));
3921 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3923 for (i=0; i<100; i++)
3924 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3930 case SMB_QUERY_FILE_UNIX_LINK:
3934 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3936 if(!S_ISLNK(sbuf.st_mode))
3937 return(UNIXERROR(ERRSRV,ERRbadlink));
3939 return(UNIXERROR(ERRDOS,ERRbadlink));
3941 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3943 return(UNIXERROR(ERRDOS,ERRnoaccess));
3945 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3947 data_size = PTR_DIFF(pdata,(*ppdata));
3952 #if defined(HAVE_POSIX_ACLS)
3953 case SMB_QUERY_POSIX_ACL:
3955 SMB_ACL_T file_acl = NULL;
3956 SMB_ACL_T def_acl = NULL;
3957 uint16 num_file_acls = 0;
3958 uint16 num_def_acls = 0;
3960 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3961 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3963 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3966 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3967 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3969 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3972 if (S_ISDIR(sbuf.st_mode)) {
3973 if (fsp && fsp->is_directory) {
3974 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3976 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3978 def_acl = free_empty_sys_acl(conn, def_acl);
3981 num_file_acls = count_acl_entries(conn, file_acl);
3982 num_def_acls = count_acl_entries(conn, def_acl);
3984 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3985 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3987 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3988 SMB_POSIX_ACL_HEADER_SIZE) ));
3990 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3993 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3995 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3998 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3999 SSVAL(pdata,2,num_file_acls);
4000 SSVAL(pdata,4,num_def_acls);
4001 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4003 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4006 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4008 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4010 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4012 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4015 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4017 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4021 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4024 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4026 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4032 case SMB_QUERY_POSIX_LOCK:
4034 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4036 SMB_BIG_UINT offset;
4038 enum brl_type lock_type;
4040 if (total_data != POSIX_LOCK_DATA_SIZE) {
4041 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4044 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4045 case POSIX_LOCK_TYPE_READ:
4046 lock_type = READ_LOCK;
4048 case POSIX_LOCK_TYPE_WRITE:
4049 lock_type = WRITE_LOCK;
4051 case POSIX_LOCK_TYPE_UNLOCK:
4053 /* There's no point in asking for an unlock... */
4054 talloc_destroy(data_ctx);
4055 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4058 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4059 #if defined(HAVE_LONGLONG)
4060 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4061 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4062 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4063 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4064 #else /* HAVE_LONGLONG */
4065 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4066 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4067 #endif /* HAVE_LONGLONG */
4069 status = query_lock(fsp,
4076 if (ERROR_WAS_LOCK_DENIED(status)) {
4077 /* Here we need to report who has it locked... */
4078 data_size = POSIX_LOCK_DATA_SIZE;
4080 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4081 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4082 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4083 #if defined(HAVE_LONGLONG)
4084 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4085 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4086 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4087 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4088 #else /* HAVE_LONGLONG */
4089 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4090 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4091 #endif /* HAVE_LONGLONG */
4093 } else if (NT_STATUS_IS_OK(status)) {
4094 /* For success we just return a copy of what we sent
4095 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4096 data_size = POSIX_LOCK_DATA_SIZE;
4097 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4098 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4100 return ERROR_NT(status);
4106 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4109 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4114 /****************************************************************************
4115 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4117 ****************************************************************************/
4119 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4121 SMB_STRUCT_STAT sbuf1, sbuf2;
4122 pstring last_component_oldname;
4123 pstring last_component_newname;
4124 NTSTATUS status = NT_STATUS_OK;
4129 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4130 if (!NT_STATUS_IS_OK(status)) {
4134 status = check_name(conn, oldname);
4135 if (!NT_STATUS_IS_OK(status)) {
4139 /* source must already exist. */
4140 if (!VALID_STAT(sbuf1)) {
4141 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4144 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4145 if (!NT_STATUS_IS_OK(status)) {
4149 status = check_name(conn, newname);
4150 if (!NT_STATUS_IS_OK(status)) {
4154 /* Disallow if newname already exists. */
4155 if (VALID_STAT(sbuf2)) {
4156 return NT_STATUS_OBJECT_NAME_COLLISION;
4159 /* No links from a directory. */
4160 if (S_ISDIR(sbuf1.st_mode)) {
4161 return NT_STATUS_FILE_IS_A_DIRECTORY;
4164 /* Ensure this is within the share. */
4165 status = reduce_name(conn, oldname);
4166 if (!NT_STATUS_IS_OK(status)) {
4170 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4172 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4173 status = map_nt_error_from_unix(errno);
4174 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4175 nt_errstr(status), newname, oldname));
4181 /****************************************************************************
4182 Deal with setting the time from any of the setfilepathinfo functions.
4183 ****************************************************************************/
4185 static NTSTATUS smb_set_file_time(connection_struct *conn,
4188 const SMB_STRUCT_STAT *psbuf,
4189 struct timespec ts[2])
4192 FILE_NOTIFY_CHANGE_LAST_ACCESS
4193 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4196 if (!VALID_STAT(*psbuf)) {
4197 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4200 /* get some defaults (no modifications) if any info is zero or -1. */
4201 if (null_timespec(ts[0])) {
4202 ts[0] = get_atimespec(psbuf);
4203 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4206 if (null_timespec(ts[1])) {
4207 ts[1] = get_mtimespec(psbuf);
4208 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4211 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4212 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4215 * Try and set the times of this file if
4216 * they are different from the current values.
4220 struct timespec mts = get_mtimespec(psbuf);
4221 struct timespec ats = get_atimespec(psbuf);
4222 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4223 return NT_STATUS_OK;
4229 * This was a setfileinfo on an open file.
4230 * NT does this a lot. We also need to
4231 * set the time here, as it can be read by
4232 * FindFirst/FindNext and with the patch for bug #2045
4233 * in smbd/fileio.c it ensures that this timestamp is
4234 * kept sticky even after a write. We save the request
4235 * away and will set it on file close and after a write. JRA.
4238 if (!null_timespec(ts[1])) {
4239 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4240 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4241 fsp_set_pending_modtime(fsp, ts[1]);
4245 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4247 if(file_ntimes(conn, fname, ts)!=0) {
4248 return map_nt_error_from_unix(errno);
4251 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4253 return NT_STATUS_OK;
4256 /****************************************************************************
4257 Deal with setting the dosmode from any of the setfilepathinfo functions.
4258 ****************************************************************************/
4260 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4262 SMB_STRUCT_STAT *psbuf,
4265 if (!VALID_STAT(*psbuf)) {
4266 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4270 if (S_ISDIR(psbuf->st_mode)) {
4277 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4279 /* check the mode isn't different, before changing it */
4280 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4282 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4283 fname, (unsigned int)dosmode ));
4285 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4286 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4287 fname, strerror(errno)));
4288 return map_nt_error_from_unix(errno);
4291 return NT_STATUS_OK;
4294 /****************************************************************************
4295 Deal with setting the size from any of the setfilepathinfo functions.
4296 ****************************************************************************/
4298 static NTSTATUS smb_set_file_size(connection_struct *conn,
4301 SMB_STRUCT_STAT *psbuf,
4304 NTSTATUS status = NT_STATUS_OK;
4305 files_struct *new_fsp = NULL;
4307 if (!VALID_STAT(*psbuf)) {
4308 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4311 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4313 if (size == get_file_size(*psbuf)) {
4314 return NT_STATUS_OK;
4317 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4318 fname, (double)size ));
4320 if (fsp && fsp->fh->fd != -1) {
4321 /* Handle based call. */
4322 if (vfs_set_filelen(fsp, size) == -1) {
4323 return map_nt_error_from_unix(errno);
4325 return NT_STATUS_OK;
4328 status = open_file_ntcreate(conn, fname, psbuf,
4330 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4333 FILE_ATTRIBUTE_NORMAL,
4334 FORCE_OPLOCK_BREAK_TO_NONE,
4337 if (!NT_STATUS_IS_OK(status)) {
4338 /* NB. We check for open_was_deferred in the caller. */
4342 if (vfs_set_filelen(new_fsp, size) == -1) {
4343 status = map_nt_error_from_unix(errno);
4344 close_file(new_fsp,NORMAL_CLOSE);
4348 close_file(new_fsp,NORMAL_CLOSE);
4349 return NT_STATUS_OK;
4352 /****************************************************************************
4353 Deal with SMB_INFO_SET_EA.
4354 ****************************************************************************/
4356 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4362 struct ea_list *ea_list = NULL;
4363 TALLOC_CTX *ctx = NULL;
4364 NTSTATUS status = NT_STATUS_OK;
4366 if (total_data < 10) {
4368 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4369 length. They seem to have no effect. Bug #3212. JRA */
4371 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4372 /* We're done. We only get EA info in this call. */
4373 return NT_STATUS_OK;
4376 return NT_STATUS_INVALID_PARAMETER;
4379 if (IVAL(pdata,0) > total_data) {
4380 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4381 IVAL(pdata,0), (unsigned int)total_data));
4382 return NT_STATUS_INVALID_PARAMETER;
4385 ctx = talloc_init("SMB_INFO_SET_EA");
4387 return NT_STATUS_NO_MEMORY;
4389 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4391 talloc_destroy(ctx);
4392 return NT_STATUS_INVALID_PARAMETER;
4394 status = set_ea(conn, fsp, fname, ea_list);
4395 talloc_destroy(ctx);
4400 /****************************************************************************
4401 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4402 ****************************************************************************/
4404 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4409 SMB_STRUCT_STAT *psbuf)
4411 NTSTATUS status = NT_STATUS_OK;
4412 BOOL delete_on_close;
4415 if (total_data < 1) {
4416 return NT_STATUS_INVALID_PARAMETER;
4420 return NT_STATUS_INVALID_HANDLE;
4423 delete_on_close = (CVAL(pdata,0) ? True : False);
4424 dosmode = dos_mode(conn, fname, psbuf);
4426 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4427 "delete_on_close = %u\n",
4429 (unsigned int)dosmode,
4430 (unsigned int)delete_on_close ));
4432 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4434 if (!NT_STATUS_IS_OK(status)) {
4438 /* The set is across all open files on this dev/inode pair. */
4439 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4440 return NT_STATUS_ACCESS_DENIED;
4442 return NT_STATUS_OK;
4445 /****************************************************************************
4446 Deal with SMB_FILE_POSITION_INFORMATION.
4447 ****************************************************************************/
4449 static NTSTATUS smb_file_position_information(connection_struct *conn,
4454 SMB_BIG_UINT position_information;
4456 if (total_data < 8) {
4457 return NT_STATUS_INVALID_PARAMETER;
4461 /* Ignore on pathname based set. */
4462 return NT_STATUS_OK;
4465 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4466 #ifdef LARGE_SMB_OFF_T
4467 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4468 #else /* LARGE_SMB_OFF_T */
4469 if (IVAL(pdata,4) != 0) {
4470 /* more than 32 bits? */
4471 return NT_STATUS_INVALID_PARAMETER;
4473 #endif /* LARGE_SMB_OFF_T */
4475 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4476 fsp->fsp_name, (double)position_information ));
4477 fsp->fh->position_information = position_information;
4478 return NT_STATUS_OK;
4481 /****************************************************************************
4482 Deal with SMB_FILE_MODE_INFORMATION.
4483 ****************************************************************************/
4485 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4491 if (total_data < 4) {
4492 return NT_STATUS_INVALID_PARAMETER;
4494 mode = IVAL(pdata,0);
4495 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4496 return NT_STATUS_INVALID_PARAMETER;
4498 return NT_STATUS_OK;
4501 /****************************************************************************
4502 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4503 ****************************************************************************/
4505 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4511 pstring link_target;
4512 const char *newname = fname;
4513 NTSTATUS status = NT_STATUS_OK;
4515 /* Set a symbolic link. */
4516 /* Don't allow this if follow links is false. */
4518 if (total_data == 0) {
4519 return NT_STATUS_INVALID_PARAMETER;
4522 if (!lp_symlinks(SNUM(conn))) {
4523 return NT_STATUS_ACCESS_DENIED;
4526 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4528 /* !widelinks forces the target path to be within the share. */
4529 /* This means we can interpret the target as a pathname. */
4530 if (!lp_widelinks(SNUM(conn))) {
4532 char *last_dirp = NULL;
4534 if (*link_target == '/') {
4535 /* No absolute paths allowed. */
4536 return NT_STATUS_ACCESS_DENIED;
4538 pstrcpy(rel_name, newname);
4539 last_dirp = strrchr_m(rel_name, '/');
4541 last_dirp[1] = '\0';
4543 pstrcpy(rel_name, "./");
4545 pstrcat(rel_name, link_target);
4547 status = check_name(conn, rel_name);
4548 if (!NT_STATUS_IS_OK(status)) {
4553 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4554 newname, link_target ));
4556 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4557 return map_nt_error_from_unix(errno);
4560 return NT_STATUS_OK;
4563 /****************************************************************************
4564 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4565 ****************************************************************************/
4567 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4575 NTSTATUS status = NT_STATUS_OK;
4577 /* Set a hard link. */
4578 if (total_data == 0) {
4579 return NT_STATUS_INVALID_PARAMETER;
4582 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4583 if (!NT_STATUS_IS_OK(status)) {
4587 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4588 if (!NT_STATUS_IS_OK(status)) {
4592 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4595 return hardlink_internals(conn, oldname, fname);
4598 /****************************************************************************
4599 Deal with SMB_FILE_RENAME_INFORMATION.
4600 ****************************************************************************/
4602 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4611 /* uint32 root_fid; */ /* Not used */
4615 BOOL dest_has_wcard = False;
4616 NTSTATUS status = NT_STATUS_OK;
4619 if (total_data < 13) {
4620 return NT_STATUS_INVALID_PARAMETER;
4623 overwrite = (CVAL(pdata,0) ? True : False);
4624 /* root_fid = IVAL(pdata,4); */
4625 len = IVAL(pdata,8);
4627 if (len > (total_data - 12) || (len == 0)) {
4628 return NT_STATUS_INVALID_PARAMETER;
4631 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4632 if (!NT_STATUS_IS_OK(status)) {
4636 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4637 if (!NT_STATUS_IS_OK(status)) {
4641 /* Check the new name has no '/' characters. */
4642 if (strchr_m(newname, '/')) {
4643 return NT_STATUS_NOT_SUPPORTED;
4646 /* Create the base directory. */
4647 pstrcpy(base_name, fname);
4648 p = strrchr_m(base_name, '/');
4652 /* Append the new name. */
4653 pstrcat(base_name, "/");
4654 pstrcat(base_name, newname);
4657 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4658 fsp->fnum, fsp->fsp_name, base_name ));
4659 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4661 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4663 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4669 /****************************************************************************
4670 Deal with SMB_SET_POSIX_ACL.
4671 ****************************************************************************/
4673 #if defined(HAVE_POSIX_ACLS)
4674 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4679 SMB_STRUCT_STAT *psbuf)
4681 uint16 posix_acl_version;
4682 uint16 num_file_acls;
4683 uint16 num_def_acls;
4684 BOOL valid_file_acls = True;
4685 BOOL valid_def_acls = True;
4687 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4688 return NT_STATUS_INVALID_PARAMETER;
4690 posix_acl_version = SVAL(pdata,0);
4691 num_file_acls = SVAL(pdata,2);
4692 num_def_acls = SVAL(pdata,4);
4694 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4695 valid_file_acls = False;
4699 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4700 valid_def_acls = False;
4704 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4705 return NT_STATUS_INVALID_PARAMETER;
4708 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4709 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4710 return NT_STATUS_INVALID_PARAMETER;
4713 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4714 fname ? fname : fsp->fsp_name,
4715 (unsigned int)num_file_acls,
4716 (unsigned int)num_def_acls));
4718 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4719 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4720 return map_nt_error_from_unix(errno);
4723 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4724 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4725 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4726 return map_nt_error_from_unix(errno);
4728 return NT_STATUS_OK;
4732 /****************************************************************************
4733 Deal with SMB_SET_POSIX_LOCK.
4734 ****************************************************************************/
4736 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4744 SMB_BIG_UINT offset;
4746 BOOL blocking_lock = False;
4747 enum brl_type lock_type;
4748 NTSTATUS status = NT_STATUS_OK;
4750 if (fsp == NULL || fsp->fh->fd == -1) {
4751 return NT_STATUS_INVALID_HANDLE;
4754 if (total_data != POSIX_LOCK_DATA_SIZE) {
4755 return NT_STATUS_INVALID_PARAMETER;
4758 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4759 case POSIX_LOCK_TYPE_READ:
4760 lock_type = READ_LOCK;
4762 case POSIX_LOCK_TYPE_WRITE:
4763 /* Return the right POSIX-mappable error code for files opened read-only. */
4764 if (!fsp->can_write) {
4765 return NT_STATUS_INVALID_HANDLE;
4767 lock_type = WRITE_LOCK;
4769 case POSIX_LOCK_TYPE_UNLOCK:
4770 lock_type = UNLOCK_LOCK;
4773 return NT_STATUS_INVALID_PARAMETER;
4776 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4777 blocking_lock = False;
4778 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4779 blocking_lock = True;
4781 return NT_STATUS_INVALID_PARAMETER;
4784 if (!lp_blocking_locks(SNUM(conn))) {
4785 blocking_lock = False;
4788 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4789 #if defined(HAVE_LONGLONG)
4790 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4791 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4792 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4793 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4794 #else /* HAVE_LONGLONG */
4795 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4796 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4797 #endif /* HAVE_LONGLONG */
4799 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4800 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4802 (unsigned int)lock_type,
4803 (unsigned int)lock_pid,
4807 if (lock_type == UNLOCK_LOCK) {
4808 status = do_unlock(fsp,
4814 struct byte_range_lock *br_lck = do_lock(fsp,
4823 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4825 * A blocking lock was requested. Package up
4826 * this smb into a queued request and push it
4827 * onto the blocking lock queue.
4829 if(push_blocking_lock_request(br_lck,
4832 -1, /* infinite timeout. */
4839 TALLOC_FREE(br_lck);
4843 TALLOC_FREE(br_lck);
4849 /****************************************************************************
4850 Deal with SMB_INFO_STANDARD.
4851 ****************************************************************************/
4853 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4858 const SMB_STRUCT_STAT *psbuf)
4860 struct timespec ts[2];
4862 if (total_data < 12) {
4863 return NT_STATUS_INVALID_PARAMETER;
4867 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4869 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4871 DEBUG(10,("smb_set_info_standard: file %s\n",
4872 fname ? fname : fsp->fsp_name ));
4874 return smb_set_file_time(conn,
4881 /****************************************************************************
4882 Deal with SMB_SET_FILE_BASIC_INFO.
4883 ****************************************************************************/
4885 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4890 SMB_STRUCT_STAT *psbuf)
4892 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4893 struct timespec write_time;
4894 struct timespec changed_time;
4896 struct timespec ts[2];
4897 NTSTATUS status = NT_STATUS_OK;
4899 if (total_data < 36) {
4900 return NT_STATUS_INVALID_PARAMETER;
4903 /* Set the attributes */
4904 dosmode = IVAL(pdata,32);
4905 status = smb_set_file_dosmode(conn,
4909 if (!NT_STATUS_IS_OK(status)) {
4913 /* Ignore create time at offset pdata. */
4916 ts[0] = interpret_long_date(pdata+8);
4918 write_time = interpret_long_date(pdata+16);
4919 changed_time = interpret_long_date(pdata+24);
4922 ts[1] = timespec_min(&write_time, &changed_time);
4924 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4928 /* Prefer a defined time to an undefined one. */
4929 if (null_timespec(ts[1])) {
4930 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4933 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4934 fname ? fname : fsp->fsp_name ));
4936 return smb_set_file_time(conn,
4943 /****************************************************************************
4944 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4945 ****************************************************************************/
4947 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4952 SMB_STRUCT_STAT *psbuf)
4954 SMB_BIG_UINT allocation_size = 0;
4955 NTSTATUS status = NT_STATUS_OK;
4956 files_struct *new_fsp = NULL;
4958 if (!VALID_STAT(*psbuf)) {
4959 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4962 if (total_data < 8) {
4963 return NT_STATUS_INVALID_PARAMETER;
4966 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4967 #ifdef LARGE_SMB_OFF_T
4968 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4969 #else /* LARGE_SMB_OFF_T */
4970 if (IVAL(pdata,4) != 0) {
4971 /* more than 32 bits? */
4972 return NT_STATUS_INVALID_PARAMETER;
4974 #endif /* LARGE_SMB_OFF_T */
4976 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4977 fname, (double)allocation_size ));
4979 if (allocation_size) {
4980 allocation_size = smb_roundup(conn, allocation_size);
4983 if(allocation_size == get_file_size(*psbuf)) {
4984 return NT_STATUS_OK;
4987 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4988 fname, (double)allocation_size ));
4990 if (fsp && fsp->fh->fd != -1) {
4991 /* Open file handle. */
4992 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4993 return map_nt_error_from_unix(errno);
4995 return NT_STATUS_OK;
4998 /* Pathname or stat or directory file. */
5000 status = open_file_ntcreate(conn, fname, psbuf,
5002 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5005 FILE_ATTRIBUTE_NORMAL,
5006 FORCE_OPLOCK_BREAK_TO_NONE,
5009 if (!NT_STATUS_IS_OK(status)) {
5010 /* NB. We check for open_was_deferred in the caller. */
5013 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5014 status = map_nt_error_from_unix(errno);
5015 close_file(new_fsp,NORMAL_CLOSE);
5019 close_file(new_fsp,NORMAL_CLOSE);
5020 return NT_STATUS_OK;
5023 /****************************************************************************
5024 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5025 ****************************************************************************/
5027 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5032 SMB_STRUCT_STAT *psbuf)
5036 if (total_data < 8) {
5037 return NT_STATUS_INVALID_PARAMETER;
5040 size = IVAL(pdata,0);
5041 #ifdef LARGE_SMB_OFF_T
5042 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5043 #else /* LARGE_SMB_OFF_T */
5044 if (IVAL(pdata,4) != 0) {
5045 /* more than 32 bits? */
5046 return NT_STATUS_INVALID_PARAMETER;
5048 #endif /* LARGE_SMB_OFF_T */
5049 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5050 "file %s to %.0f\n", fname, (double)size ));
5052 return smb_set_file_size(conn,
5059 /****************************************************************************
5060 Allow a UNIX info mknod.
5061 ****************************************************************************/
5063 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5067 SMB_STRUCT_STAT *psbuf)
5069 uint32 file_type = IVAL(pdata,56);
5070 #if defined(HAVE_MAKEDEV)
5071 uint32 dev_major = IVAL(pdata,60);
5072 uint32 dev_minor = IVAL(pdata,68);
5074 SMB_DEV_T dev = (SMB_DEV_T)0;
5075 uint32 raw_unixmode = IVAL(pdata,84);
5079 if (total_data < 100) {
5080 return NT_STATUS_INVALID_PARAMETER;
5083 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5084 if (!NT_STATUS_IS_OK(status)) {
5088 #if defined(HAVE_MAKEDEV)
5089 dev = makedev(dev_major, dev_minor);
5092 switch (file_type) {
5093 #if defined(S_IFIFO)
5094 case UNIX_TYPE_FIFO:
5095 unixmode |= S_IFIFO;
5098 #if defined(S_IFSOCK)
5099 case UNIX_TYPE_SOCKET:
5100 unixmode |= S_IFSOCK;
5103 #if defined(S_IFCHR)
5104 case UNIX_TYPE_CHARDEV:
5105 unixmode |= S_IFCHR;
5108 #if defined(S_IFBLK)
5109 case UNIX_TYPE_BLKDEV:
5110 unixmode |= S_IFBLK;
5114 return NT_STATUS_INVALID_PARAMETER;
5117 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5118 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5120 /* Ok - do the mknod. */
5121 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5122 return map_nt_error_from_unix(errno);
5125 /* If any of the other "set" calls fail we
5126 * don't want to end up with a half-constructed mknod.
5129 if (lp_inherit_perms(SNUM(conn))) {
5131 conn, parent_dirname(fname),
5135 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5136 status = map_nt_error_from_unix(errno);
5137 SMB_VFS_UNLINK(conn,fname);
5140 return NT_STATUS_OK;
5143 /****************************************************************************
5144 Deal with SMB_SET_FILE_UNIX_BASIC.
5145 ****************************************************************************/
5147 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5152 SMB_STRUCT_STAT *psbuf)
5154 struct timespec ts[2];
5155 uint32 raw_unixmode;
5158 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5159 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5160 NTSTATUS status = NT_STATUS_OK;
5161 BOOL delete_on_fail = False;
5162 enum perm_type ptype;
5164 if (total_data < 100) {
5165 return NT_STATUS_INVALID_PARAMETER;
5168 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5169 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5170 size=IVAL(pdata,0); /* first 8 Bytes are size */
5171 #ifdef LARGE_SMB_OFF_T
5172 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5173 #else /* LARGE_SMB_OFF_T */
5174 if (IVAL(pdata,4) != 0) {
5175 /* more than 32 bits? */
5176 return NT_STATUS_INVALID_PARAMETER;
5178 #endif /* LARGE_SMB_OFF_T */
5181 ts[0] = interpret_long_date(pdata+24); /* access_time */
5182 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5183 set_owner = (uid_t)IVAL(pdata,40);
5184 set_grp = (gid_t)IVAL(pdata,48);
5185 raw_unixmode = IVAL(pdata,84);
5187 if (VALID_STAT(*psbuf)) {
5188 if (S_ISDIR(psbuf->st_mode)) {
5189 ptype = PERM_EXISTING_DIR;
5191 ptype = PERM_EXISTING_FILE;
5194 ptype = PERM_NEW_FILE;
5197 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5198 if (!NT_STATUS_IS_OK(status)) {
5202 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5203 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5204 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5206 if (!VALID_STAT(*psbuf)) {
5208 * The only valid use of this is to create character and block
5209 * devices, and named pipes. This is deprecated (IMHO) and
5210 * a new info level should be used for mknod. JRA.
5213 status = smb_unix_mknod(conn,
5218 if (!NT_STATUS_IS_OK(status)) {
5222 /* Ensure we don't try and change anything else. */
5223 raw_unixmode = SMB_MODE_NO_CHANGE;
5224 size = get_file_size(*psbuf);
5225 ts[0] = get_atimespec(psbuf);
5226 ts[1] = get_mtimespec(psbuf);
5228 * We continue here as we might want to change the
5231 delete_on_fail = True;
5235 /* Horrible backwards compatibility hack as an old server bug
5236 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5240 size = get_file_size(*psbuf);
5245 * Deal with the UNIX specific mode set.
5248 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5249 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5250 (unsigned int)unixmode, fname ));
5251 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5252 return map_nt_error_from_unix(errno);
5257 * Deal with the UNIX specific uid set.
5260 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5261 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5262 (unsigned int)set_owner, fname ));
5263 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5264 status = map_nt_error_from_unix(errno);
5265 if (delete_on_fail) {
5266 SMB_VFS_UNLINK(conn,fname);
5273 * Deal with the UNIX specific gid set.
5276 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5277 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5278 (unsigned int)set_owner, fname ));
5279 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5280 status = map_nt_error_from_unix(errno);
5281 if (delete_on_fail) {
5282 SMB_VFS_UNLINK(conn,fname);
5288 /* Deal with any size changes. */
5290 status = smb_set_file_size(conn,
5295 if (!NT_STATUS_IS_OK(status)) {
5299 /* Deal with any time changes. */
5301 return smb_set_file_time(conn,
5308 /****************************************************************************
5309 Deal with SMB_SET_FILE_UNIX_INFO2.
5310 ****************************************************************************/
5312 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5317 SMB_STRUCT_STAT *psbuf)
5323 if (total_data < 116) {
5324 return NT_STATUS_INVALID_PARAMETER;
5327 /* Start by setting all the fields that are common between UNIX_BASIC
5330 status = smb_set_file_unix_basic(conn, pdata, total_data,
5332 if (!NT_STATUS_IS_OK(status)) {
5336 smb_fflags = IVAL(pdata, 108);
5337 smb_fmask = IVAL(pdata, 112);
5339 /* NB: We should only attempt to alter the file flags if the client
5340 * sends a non-zero mask.
5342 if (smb_fmask != 0) {
5343 int stat_fflags = 0;
5345 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5347 /* Client asked to alter a flag we don't understand. */
5348 return NT_STATUS_INVALID_PARAMETER;
5351 if (fsp && fsp->fh->fd != -1) {
5352 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5353 return NT_STATUS_NOT_SUPPORTED;
5355 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5356 return map_nt_error_from_unix(errno);
5361 /* XXX: need to add support for changing the create_time here. You
5362 * can do this for paths on Darwin with setattrlist(2). The right way
5363 * to hook this up is probably by extending the VFS utimes interface.
5366 return NT_STATUS_OK;
5369 /****************************************************************************
5370 Create a directory with POSIX semantics.
5371 ****************************************************************************/
5373 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5377 SMB_STRUCT_STAT *psbuf,
5378 int *pdata_return_size)
5380 NTSTATUS status = NT_STATUS_OK;
5381 uint32 raw_unixmode = 0;
5382 uint32 mod_unixmode = 0;
5383 mode_t unixmode = (mode_t)0;
5384 files_struct *fsp = NULL;
5385 uint16 info_level_return = 0;
5387 char *pdata = *ppdata;
5389 if (total_data < 18) {
5390 return NT_STATUS_INVALID_PARAMETER;
5393 raw_unixmode = IVAL(pdata,8);
5394 /* Next 4 bytes are not yet defined. */
5396 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5397 if (!NT_STATUS_IS_OK(status)) {
5401 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5403 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5404 fname, (unsigned int)unixmode ));
5406 status = open_directory(conn,
5409 FILE_READ_ATTRIBUTES, /* Just a stat open */
5410 FILE_SHARE_NONE, /* Ignored for stat opens */
5417 if (NT_STATUS_IS_OK(status)) {
5418 close_file(fsp, NORMAL_CLOSE);
5421 info_level_return = SVAL(pdata,16);
5423 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5424 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5425 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5426 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5428 *pdata_return_size = 12;
5431 /* Realloc the data size */
5432 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5433 if (*ppdata == NULL) {
5434 *pdata_return_size = 0;
5435 return NT_STATUS_NO_MEMORY;
5439 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5440 SSVAL(pdata,2,0); /* No fnum. */
5441 SIVAL(pdata,4,info); /* Was directory created. */
5443 switch (info_level_return) {
5444 case SMB_QUERY_FILE_UNIX_BASIC:
5445 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5446 SSVAL(pdata,10,0); /* Padding. */
5447 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5449 case SMB_QUERY_FILE_UNIX_INFO2:
5450 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5451 SSVAL(pdata,10,0); /* Padding. */
5452 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5455 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5456 SSVAL(pdata,10,0); /* Padding. */
5463 /****************************************************************************
5464 Open/Create a file with POSIX semantics.
5465 ****************************************************************************/
5467 static NTSTATUS smb_posix_open(connection_struct *conn,
5471 SMB_STRUCT_STAT *psbuf,
5472 int *pdata_return_size)
5474 BOOL extended_oplock_granted = False;
5475 char *pdata = *ppdata;
5477 uint32 wire_open_mode = 0;
5478 uint32 raw_unixmode = 0;
5479 uint32 mod_unixmode = 0;
5480 uint32 create_disp = 0;
5481 uint32 access_mask = 0;
5482 uint32 create_options = 0;
5483 NTSTATUS status = NT_STATUS_OK;
5484 mode_t unixmode = (mode_t)0;
5485 files_struct *fsp = NULL;
5486 int oplock_request = 0;
5488 uint16 info_level_return = 0;
5490 if (total_data < 18) {
5491 return NT_STATUS_INVALID_PARAMETER;
5494 flags = IVAL(pdata,0);
5495 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5496 if (oplock_request) {
5497 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5500 wire_open_mode = IVAL(pdata,4);
5502 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5503 return smb_posix_mkdir(conn,
5511 switch (wire_open_mode & SMB_ACCMODE) {
5513 access_mask = FILE_READ_DATA;
5516 access_mask = FILE_WRITE_DATA;
5519 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5522 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5523 (unsigned int)wire_open_mode ));
5524 return NT_STATUS_INVALID_PARAMETER;
5527 wire_open_mode &= ~SMB_ACCMODE;
5529 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5530 create_disp = FILE_CREATE;
5531 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5532 create_disp = FILE_OVERWRITE_IF;
5533 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5534 create_disp = FILE_OPEN_IF;
5536 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5537 (unsigned int)wire_open_mode ));
5538 return NT_STATUS_INVALID_PARAMETER;
5541 raw_unixmode = IVAL(pdata,8);
5542 /* Next 4 bytes are not yet defined. */
5544 status = unix_perms_from_wire(conn,
5547 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5550 if (!NT_STATUS_IS_OK(status)) {
5554 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5556 if (wire_open_mode & SMB_O_SYNC) {
5557 create_options |= FILE_WRITE_THROUGH;
5559 if (wire_open_mode & SMB_O_APPEND) {
5560 access_mask |= FILE_APPEND_DATA;
5562 if (wire_open_mode & SMB_O_DIRECT) {
5563 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5566 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5568 (unsigned int)wire_open_mode,
5569 (unsigned int)unixmode ));
5571 status = open_file_ntcreate(conn,
5575 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5577 0, /* no create options yet. */
5583 if (!NT_STATUS_IS_OK(status)) {
5587 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5588 extended_oplock_granted = True;
5591 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5592 extended_oplock_granted = True;
5595 info_level_return = SVAL(pdata,16);
5597 /* Allocate the correct return size. */
5599 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5600 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5601 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5602 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5604 *pdata_return_size = 12;
5607 /* Realloc the data size */
5608 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5609 if (*ppdata == NULL) {
5610 close_file(fsp,ERROR_CLOSE);
5611 *pdata_return_size = 0;
5612 return NT_STATUS_NO_MEMORY;
5616 if (extended_oplock_granted) {
5617 if (flags & REQUEST_BATCH_OPLOCK) {
5618 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5620 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5622 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5623 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5625 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5628 SSVAL(pdata,2,fsp->fnum);
5629 SIVAL(pdata,4,info); /* Was file created etc. */
5631 switch (info_level_return) {
5632 case SMB_QUERY_FILE_UNIX_BASIC:
5633 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5634 SSVAL(pdata,10,0); /* padding. */
5635 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5637 case SMB_QUERY_FILE_UNIX_INFO2:
5638 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5639 SSVAL(pdata,10,0); /* padding. */
5640 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5643 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5644 SSVAL(pdata,10,0); /* padding. */
5647 return NT_STATUS_OK;
5650 /****************************************************************************
5651 Delete a file with POSIX semantics.
5652 ****************************************************************************/
5654 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5658 SMB_STRUCT_STAT *psbuf)
5660 NTSTATUS status = NT_STATUS_OK;
5661 files_struct *fsp = NULL;
5665 if (total_data < 2) {
5666 return NT_STATUS_INVALID_PARAMETER;
5669 flags = SVAL(pdata,0);
5671 if (!VALID_STAT(*psbuf)) {
5672 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5675 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5676 !VALID_STAT_OF_DIR(*psbuf)) {
5677 return NT_STATUS_NOT_A_DIRECTORY;
5680 DEBUG(10,("smb_posix_unlink: %s %s\n",
5681 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5684 if (VALID_STAT_OF_DIR(*psbuf)) {
5685 status = open_directory(conn,
5689 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5691 FILE_DELETE_ON_CLOSE,
5692 FILE_FLAG_POSIX_SEMANTICS|0777,
5698 status = open_file_ntcreate(conn,
5702 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5705 FILE_FLAG_POSIX_SEMANTICS|0777,
5706 0, /* No oplock, but break existing ones. */
5710 * For file opens we must set the delete on close
5714 if (!NT_STATUS_IS_OK(status)) {
5718 status = smb_set_file_disposition_info(conn,
5726 if (!NT_STATUS_IS_OK(status)) {
5729 return close_file(fsp, NORMAL_CLOSE);
5732 /****************************************************************************
5733 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5734 ****************************************************************************/
5736 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5737 unsigned int tran_call,
5738 char **pparams, int total_params, char **ppdata, int total_data,
5739 unsigned int max_data_bytes)
5741 char *params = *pparams;
5742 char *pdata = *ppdata;
5744 SMB_STRUCT_STAT sbuf;
5746 files_struct *fsp = NULL;
5747 NTSTATUS status = NT_STATUS_OK;
5748 int data_return_size = 0;
5751 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5756 if (tran_call == TRANSACT2_SETFILEINFO) {
5757 if (total_params < 4) {
5758 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5761 fsp = file_fsp(params,0);
5762 info_level = SVAL(params,2);
5764 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5766 * This is actually a SETFILEINFO on a directory
5767 * handle (returned from an NT SMB). NT5.0 seems
5768 * to do this call. JRA.
5770 pstrcpy(fname, fsp->fsp_name);
5771 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5772 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5773 return UNIXERROR(ERRDOS,ERRbadpath);
5775 } else if (fsp && fsp->print_file) {
5777 * Doing a DELETE_ON_CLOSE should cancel a print job.
5779 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5780 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5782 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5785 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5788 return (UNIXERROR(ERRDOS,ERRbadpath));
5791 * Original code - this is an open file.
5793 CHECK_FSP(fsp,conn);
5795 pstrcpy(fname, fsp->fsp_name);
5797 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5798 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5799 return(UNIXERROR(ERRDOS,ERRbadfid));
5804 if (total_params < 7) {
5805 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5808 info_level = SVAL(params,0);
5809 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5810 if (!NT_STATUS_IS_OK(status)) {
5811 return ERROR_NT(status);
5814 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5815 if (!NT_STATUS_IS_OK(status)) {
5816 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5817 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5819 return ERROR_NT(status);
5822 status = unix_convert(conn, fname, False, NULL, &sbuf);
5823 if (!NT_STATUS_IS_OK(status)) {
5824 return ERROR_NT(status);
5827 status = check_name(conn, fname);
5828 if (!NT_STATUS_IS_OK(status)) {
5829 return ERROR_NT(status);
5833 * For CIFS UNIX extensions the target name may not exist.
5836 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5837 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5838 return UNIXERROR(ERRDOS,ERRbadpath);
5842 if (!CAN_WRITE(conn)) {
5843 return ERROR_DOS(ERRSRV,ERRaccess);
5846 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5847 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5850 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5851 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5853 /* Realloc the parameter size */
5854 *pparams = (char *)SMB_REALLOC(*pparams,2);
5855 if (*pparams == NULL) {
5856 return ERROR_NT(NT_STATUS_NO_MEMORY);
5862 if (fsp && !null_timespec(fsp->pending_modtime)) {
5863 /* the pending modtime overrides the current modtime */
5864 set_mtimespec(&sbuf, fsp->pending_modtime);
5867 switch (info_level) {
5869 case SMB_INFO_STANDARD:
5871 status = smb_set_info_standard(conn,
5880 case SMB_INFO_SET_EA:
5882 status = smb_info_set_ea(conn,
5890 case SMB_SET_FILE_BASIC_INFO:
5891 case SMB_FILE_BASIC_INFORMATION:
5893 status = smb_set_file_basic_info(conn,
5902 case SMB_FILE_ALLOCATION_INFORMATION:
5903 case SMB_SET_FILE_ALLOCATION_INFO:
5905 status = smb_set_file_allocation_info(conn,
5914 case SMB_FILE_END_OF_FILE_INFORMATION:
5915 case SMB_SET_FILE_END_OF_FILE_INFO:
5917 status = smb_set_file_end_of_file_info(conn,
5926 case SMB_FILE_DISPOSITION_INFORMATION:
5927 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5930 /* JRA - We used to just ignore this on a path ?
5931 * Shouldn't this be invalid level on a pathname
5934 if (tran_call != TRANSACT2_SETFILEINFO) {
5935 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5938 status = smb_set_file_disposition_info(conn,
5947 case SMB_FILE_POSITION_INFORMATION:
5949 status = smb_file_position_information(conn,
5956 /* From tridge Samba4 :
5957 * MODE_INFORMATION in setfileinfo (I have no
5958 * idea what "mode information" on a file is - it takes a value of 0,
5959 * 2, 4 or 6. What could it be?).
5962 case SMB_FILE_MODE_INFORMATION:
5964 status = smb_file_mode_information(conn,
5971 * CIFS UNIX extensions.
5974 case SMB_SET_FILE_UNIX_BASIC:
5976 status = smb_set_file_unix_basic(conn,
5985 case SMB_SET_FILE_UNIX_INFO2:
5987 status = smb_set_file_unix_info2(conn,
5996 case SMB_SET_FILE_UNIX_LINK:
5998 if (tran_call != TRANSACT2_SETPATHINFO) {
5999 /* We must have a pathname for this. */
6000 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6002 status = smb_set_file_unix_link(conn,
6010 case SMB_SET_FILE_UNIX_HLINK:
6012 if (tran_call != TRANSACT2_SETPATHINFO) {
6013 /* We must have a pathname for this. */
6014 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6016 status = smb_set_file_unix_hlink(conn,
6025 case SMB_FILE_RENAME_INFORMATION:
6027 status = smb_file_rename_information(conn,
6037 #if defined(HAVE_POSIX_ACLS)
6038 case SMB_SET_POSIX_ACL:
6040 status = smb_set_posix_acl(conn,
6050 case SMB_SET_POSIX_LOCK:
6052 if (tran_call != TRANSACT2_SETFILEINFO) {
6053 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6055 status = smb_set_posix_lock(conn,
6064 case SMB_POSIX_PATH_OPEN:
6066 if (tran_call != TRANSACT2_SETPATHINFO) {
6067 /* We must have a pathname for this. */
6068 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6071 status = smb_posix_open(conn,
6080 case SMB_POSIX_PATH_UNLINK:
6082 if (tran_call != TRANSACT2_SETPATHINFO) {
6083 /* We must have a pathname for this. */
6084 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6087 status = smb_posix_unlink(conn,
6096 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6100 if (!NT_STATUS_IS_OK(status)) {
6101 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6102 /* We have re-scheduled this call. */
6105 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6106 /* We have re-scheduled this call. */
6109 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6110 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6112 return ERROR_NT(status);
6116 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6121 /****************************************************************************
6122 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6123 ****************************************************************************/
6125 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6126 char **pparams, int total_params, char **ppdata, int total_data,
6127 unsigned int max_data_bytes)
6129 char *params = *pparams;
6130 char *pdata = *ppdata;
6132 SMB_STRUCT_STAT sbuf;
6133 NTSTATUS status = NT_STATUS_OK;
6134 struct ea_list *ea_list = NULL;
6136 if (!CAN_WRITE(conn))
6137 return ERROR_DOS(ERRSRV,ERRaccess);
6139 if (total_params < 5) {
6140 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6143 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6144 if (!NT_STATUS_IS_OK(status)) {
6145 return ERROR_NT(status);
6148 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6150 status = unix_convert(conn, directory, False, NULL, &sbuf);
6151 if (!NT_STATUS_IS_OK(status)) {
6152 return ERROR_NT(status);
6155 status = check_name(conn, directory);
6156 if (!NT_STATUS_IS_OK(status)) {
6157 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6158 return ERROR_NT(status);
6161 /* Any data in this call is an EA list. */
6162 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6163 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6167 * OS/2 workplace shell seems to send SET_EA requests of "null"
6168 * length (4 bytes containing IVAL 4).
6169 * They seem to have no effect. Bug #3212. JRA.
6172 if (total_data != 4) {
6173 if (total_data < 10) {
6174 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6177 if (IVAL(pdata,0) > total_data) {
6178 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6179 IVAL(pdata,0), (unsigned int)total_data));
6180 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6183 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6186 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6188 } else if (IVAL(pdata,0) != 4) {
6189 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6192 status = create_directory(conn, directory);
6194 if (!NT_STATUS_IS_OK(status)) {
6195 return ERROR_NT(status);
6198 /* Try and set any given EA. */
6200 status = set_ea(conn, NULL, directory, ea_list);
6201 if (!NT_STATUS_IS_OK(status)) {
6202 return ERROR_NT(status);
6206 /* Realloc the parameter and data sizes */
6207 *pparams = (char *)SMB_REALLOC(*pparams,2);
6208 if(*pparams == NULL) {
6209 return ERROR_NT(NT_STATUS_NO_MEMORY);
6215 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6220 /****************************************************************************
6221 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6222 We don't actually do this - we just send a null response.
6223 ****************************************************************************/
6225 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6226 char **pparams, int total_params, char **ppdata, int total_data,
6227 unsigned int max_data_bytes)
6229 static uint16 fnf_handle = 257;
6230 char *params = *pparams;
6233 if (total_params < 6) {
6234 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6237 info_level = SVAL(params,4);
6238 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6240 switch (info_level) {
6245 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6248 /* Realloc the parameter and data sizes */
6249 *pparams = (char *)SMB_REALLOC(*pparams,6);
6250 if (*pparams == NULL) {
6251 return ERROR_NT(NT_STATUS_NO_MEMORY);
6255 SSVAL(params,0,fnf_handle);
6256 SSVAL(params,2,0); /* No changes */
6257 SSVAL(params,4,0); /* No EA errors */
6264 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6269 /****************************************************************************
6270 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6271 changes). Currently this does nothing.
6272 ****************************************************************************/
6274 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6275 char **pparams, int total_params, char **ppdata, int total_data,
6276 unsigned int max_data_bytes)
6278 char *params = *pparams;
6280 DEBUG(3,("call_trans2findnotifynext\n"));
6282 /* Realloc the parameter and data sizes */
6283 *pparams = (char *)SMB_REALLOC(*pparams,4);
6284 if (*pparams == NULL) {
6285 return ERROR_NT(NT_STATUS_NO_MEMORY);
6289 SSVAL(params,0,0); /* No changes */
6290 SSVAL(params,2,0); /* No EA errors */
6292 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6297 /****************************************************************************
6298 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6299 ****************************************************************************/
6301 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6302 char **pparams, int total_params, char **ppdata, int total_data,
6303 unsigned int max_data_bytes)
6305 char *params = *pparams;
6308 int max_referral_level;
6309 NTSTATUS status = NT_STATUS_OK;
6311 DEBUG(10,("call_trans2getdfsreferral\n"));
6313 if (total_params < 3) {
6314 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6317 max_referral_level = SVAL(params,0);
6319 if(!lp_host_msdfs())
6320 return ERROR_DOS(ERRDOS,ERRbadfunc);
6322 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6323 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6324 return ERROR_NT(status);
6326 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6327 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6332 #define LMCAT_SPL 0x53
6333 #define LMFUNC_GETJOBID 0x60
6335 /****************************************************************************
6336 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6337 ****************************************************************************/
6339 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6340 char **pparams, int total_params, char **ppdata, int total_data,
6341 unsigned int max_data_bytes)
6343 char *pdata = *ppdata;
6344 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6346 /* check for an invalid fid before proceeding */
6349 return(ERROR_DOS(ERRDOS,ERRbadfid));
6351 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6352 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6353 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6354 if (*ppdata == NULL) {
6355 return ERROR_NT(NT_STATUS_NO_MEMORY);
6359 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6360 CAN ACCEPT THIS IN UNICODE. JRA. */
6362 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6363 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6364 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6365 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6368 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6369 return ERROR_DOS(ERRSRV,ERRerror);
6373 /****************************************************************************
6374 Reply to a SMBfindclose (stop trans2 directory search).
6375 ****************************************************************************/
6377 int reply_findclose(connection_struct *conn,
6378 char *inbuf,char *outbuf,int length,int bufsize)
6381 int dptr_num=SVALS(inbuf,smb_vwv0);
6382 START_PROFILE(SMBfindclose);
6384 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6386 dptr_close(&dptr_num);
6388 outsize = set_message(inbuf, outbuf,0,0,False);
6390 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6392 END_PROFILE(SMBfindclose);
6396 /****************************************************************************
6397 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6398 ****************************************************************************/
6400 int reply_findnclose(connection_struct *conn,
6401 char *inbuf,char *outbuf,int length,int bufsize)
6405 START_PROFILE(SMBfindnclose);
6407 dptr_num = SVAL(inbuf,smb_vwv0);
6409 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6411 /* We never give out valid handles for a
6412 findnotifyfirst - so any dptr_num is ok here.
6415 outsize = set_message(inbuf, outbuf,0,0,False);
6417 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6419 END_PROFILE(SMBfindnclose);
6423 int handle_trans2(connection_struct *conn,
6424 struct trans_state *state,
6425 char *inbuf, char *outbuf, int size, int bufsize)
6429 if (Protocol >= PROTOCOL_NT1) {
6430 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6433 /* Now we must call the relevant TRANS2 function */
6434 switch(state->call) {
6435 case TRANSACT2_OPEN:
6437 START_PROFILE(Trans2_open);
6438 outsize = call_trans2open(
6439 conn, inbuf, outbuf, bufsize,
6440 &state->param, state->total_param,
6441 &state->data, state->total_data,
6442 state->max_data_return);
6443 END_PROFILE(Trans2_open);
6447 case TRANSACT2_FINDFIRST:
6449 START_PROFILE(Trans2_findfirst);
6450 outsize = call_trans2findfirst(
6451 conn, inbuf, outbuf, bufsize,
6452 &state->param, state->total_param,
6453 &state->data, state->total_data,
6454 state->max_data_return);
6455 END_PROFILE(Trans2_findfirst);
6459 case TRANSACT2_FINDNEXT:
6461 START_PROFILE(Trans2_findnext);
6462 outsize = call_trans2findnext(
6463 conn, inbuf, outbuf, size, bufsize,
6464 &state->param, state->total_param,
6465 &state->data, state->total_data,
6466 state->max_data_return);
6467 END_PROFILE(Trans2_findnext);
6471 case TRANSACT2_QFSINFO:
6473 START_PROFILE(Trans2_qfsinfo);
6474 outsize = call_trans2qfsinfo(
6475 conn, inbuf, outbuf, size, bufsize,
6476 &state->param, state->total_param,
6477 &state->data, state->total_data,
6478 state->max_data_return);
6479 END_PROFILE(Trans2_qfsinfo);
6483 case TRANSACT2_SETFSINFO:
6485 START_PROFILE(Trans2_setfsinfo);
6486 outsize = call_trans2setfsinfo(
6487 conn, inbuf, outbuf, size, bufsize,
6488 &state->param, state->total_param,
6489 &state->data, state->total_data,
6490 state->max_data_return);
6491 END_PROFILE(Trans2_setfsinfo);
6495 case TRANSACT2_QPATHINFO:
6496 case TRANSACT2_QFILEINFO:
6498 START_PROFILE(Trans2_qpathinfo);
6499 outsize = call_trans2qfilepathinfo(
6500 conn, inbuf, outbuf, size, bufsize, state->call,
6501 &state->param, state->total_param,
6502 &state->data, state->total_data,
6503 state->max_data_return);
6504 END_PROFILE(Trans2_qpathinfo);
6508 case TRANSACT2_SETPATHINFO:
6509 case TRANSACT2_SETFILEINFO:
6511 START_PROFILE(Trans2_setpathinfo);
6512 outsize = call_trans2setfilepathinfo(
6513 conn, inbuf, outbuf, size, bufsize, state->call,
6514 &state->param, state->total_param,
6515 &state->data, state->total_data,
6516 state->max_data_return);
6517 END_PROFILE(Trans2_setpathinfo);
6521 case TRANSACT2_FINDNOTIFYFIRST:
6523 START_PROFILE(Trans2_findnotifyfirst);
6524 outsize = call_trans2findnotifyfirst(
6525 conn, inbuf, outbuf, size, bufsize,
6526 &state->param, state->total_param,
6527 &state->data, state->total_data,
6528 state->max_data_return);
6529 END_PROFILE(Trans2_findnotifyfirst);
6533 case TRANSACT2_FINDNOTIFYNEXT:
6535 START_PROFILE(Trans2_findnotifynext);
6536 outsize = call_trans2findnotifynext(
6537 conn, inbuf, outbuf, size, bufsize,
6538 &state->param, state->total_param,
6539 &state->data, state->total_data,
6540 state->max_data_return);
6541 END_PROFILE(Trans2_findnotifynext);
6545 case TRANSACT2_MKDIR:
6547 START_PROFILE(Trans2_mkdir);
6548 outsize = call_trans2mkdir(
6549 conn, inbuf, outbuf, size, bufsize,
6550 &state->param, state->total_param,
6551 &state->data, state->total_data,
6552 state->max_data_return);
6553 END_PROFILE(Trans2_mkdir);
6557 case TRANSACT2_GET_DFS_REFERRAL:
6559 START_PROFILE(Trans2_get_dfs_referral);
6560 outsize = call_trans2getdfsreferral(
6561 conn, inbuf, outbuf, size, bufsize,
6562 &state->param, state->total_param,
6563 &state->data, state->total_data,
6564 state->max_data_return);
6565 END_PROFILE(Trans2_get_dfs_referral);
6569 case TRANSACT2_IOCTL:
6571 START_PROFILE(Trans2_ioctl);
6572 outsize = call_trans2ioctl(
6573 conn, inbuf, outbuf, size, bufsize,
6574 &state->param, state->total_param,
6575 &state->data, state->total_data,
6576 state->max_data_return);
6577 END_PROFILE(Trans2_ioctl);
6582 /* Error in request */
6583 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6584 outsize = ERROR_DOS(ERRSRV,ERRerror);
6590 /****************************************************************************
6591 Reply to a SMBtrans2.
6592 ****************************************************************************/
6594 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6595 int size, int bufsize)
6598 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6599 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6600 unsigned int psoff = SVAL(inbuf, smb_psoff);
6601 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6602 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6603 struct trans_state *state;
6606 START_PROFILE(SMBtrans2);
6608 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6609 if (!NT_STATUS_IS_OK(result)) {
6610 DEBUG(2, ("Got invalid trans2 request: %s\n",
6611 nt_errstr(result)));
6612 END_PROFILE(SMBtrans2);
6613 return ERROR_NT(result);
6616 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6617 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6618 && (tran_call != TRANSACT2_QFILEINFO)) {
6619 END_PROFILE(SMBtrans2);
6620 return ERROR_DOS(ERRSRV,ERRaccess);
6623 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6624 DEBUG(0, ("talloc failed\n"));
6625 END_PROFILE(SMBtrans2);
6626 return ERROR_NT(NT_STATUS_NO_MEMORY);
6629 state->cmd = SMBtrans2;
6631 state->mid = SVAL(inbuf, smb_mid);
6632 state->vuid = SVAL(inbuf, smb_uid);
6633 state->setup_count = SVAL(inbuf, smb_suwcnt);
6634 state->setup = NULL;
6635 state->total_param = SVAL(inbuf, smb_tpscnt);
6636 state->param = NULL;
6637 state->total_data = SVAL(inbuf, smb_tdscnt);
6639 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6640 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6641 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6642 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6643 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6645 state->call = tran_call;
6647 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6648 is so as a sanity check */
6649 if (state->setup_count != 1) {
6651 * Need to have rc=0 for ioctl to get job id for OS/2.
6652 * Network printing will fail if function is not successful.
6653 * Similar function in reply.c will be used if protocol
6654 * is LANMAN1.0 instead of LM1.2X002.
6655 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6656 * outbuf doesn't have to be set(only job id is used).
6658 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6659 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6660 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6661 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6663 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6664 DEBUG(2,("Transaction is %d\n",tran_call));
6666 END_PROFILE(SMBtrans2);
6667 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6671 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6674 if (state->total_data) {
6675 /* Can't use talloc here, the core routines do realloc on the
6676 * params and data. */
6677 state->data = (char *)SMB_MALLOC(state->total_data);
6678 if (state->data == NULL) {
6679 DEBUG(0,("reply_trans2: data malloc fail for %u "
6680 "bytes !\n", (unsigned int)state->total_data));
6682 END_PROFILE(SMBtrans2);
6683 return(ERROR_DOS(ERRDOS,ERRnomem));
6685 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6687 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6688 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6691 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6694 if (state->total_param) {
6695 /* Can't use talloc here, the core routines do realloc on the
6696 * params and data. */
6697 state->param = (char *)SMB_MALLOC(state->total_param);
6698 if (state->param == NULL) {
6699 DEBUG(0,("reply_trans: param malloc fail for %u "
6700 "bytes !\n", (unsigned int)state->total_param));
6701 SAFE_FREE(state->data);
6703 END_PROFILE(SMBtrans2);
6704 return(ERROR_DOS(ERRDOS,ERRnomem));
6706 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6708 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6709 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6712 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6715 state->received_data = dscnt;
6716 state->received_param = pscnt;
6718 if ((state->received_param == state->total_param) &&
6719 (state->received_data == state->total_data)) {
6721 outsize = handle_trans2(conn, state, inbuf, outbuf,
6723 SAFE_FREE(state->data);
6724 SAFE_FREE(state->param);
6726 END_PROFILE(SMBtrans2);
6730 DLIST_ADD(conn->pending_trans, state);
6732 /* We need to send an interim response then receive the rest
6733 of the parameter/data bytes */
6734 outsize = set_message(inbuf, outbuf,0,0,False);
6736 END_PROFILE(SMBtrans2);
6741 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6742 SAFE_FREE(state->data);
6743 SAFE_FREE(state->param);
6745 END_PROFILE(SMBtrans2);
6746 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6750 /****************************************************************************
6751 Reply to a SMBtranss2
6752 ****************************************************************************/
6754 int reply_transs2(connection_struct *conn,
6755 char *inbuf,char *outbuf,int size,int bufsize)
6758 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6759 struct trans_state *state;
6761 START_PROFILE(SMBtranss2);
6765 for (state = conn->pending_trans; state != NULL;
6766 state = state->next) {
6767 if (state->mid == SVAL(inbuf,smb_mid)) {
6772 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6773 END_PROFILE(SMBtranss2);
6774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6777 /* Revise state->total_param and state->total_data in case they have
6778 changed downwards */
6780 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6781 state->total_param = SVAL(inbuf, smb_tpscnt);
6782 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6783 state->total_data = SVAL(inbuf, smb_tdscnt);
6785 pcnt = SVAL(inbuf, smb_spscnt);
6786 poff = SVAL(inbuf, smb_spsoff);
6787 pdisp = SVAL(inbuf, smb_spsdisp);
6789 dcnt = SVAL(inbuf, smb_sdscnt);
6790 doff = SVAL(inbuf, smb_sdsoff);
6791 ddisp = SVAL(inbuf, smb_sdsdisp);
6793 state->received_param += pcnt;
6794 state->received_data += dcnt;
6796 if ((state->received_data > state->total_data) ||
6797 (state->received_param > state->total_param))
6801 if (pdisp+pcnt > state->total_param)
6803 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6805 if (pdisp > state->total_param)
6807 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6808 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6810 if (state->param + pdisp < state->param)
6813 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6818 if (ddisp+dcnt > state->total_data)
6820 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6822 if (ddisp > state->total_data)
6824 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6825 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6827 if (state->data + ddisp < state->data)
6830 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6834 if ((state->received_param < state->total_param) ||
6835 (state->received_data < state->total_data)) {
6836 END_PROFILE(SMBtranss2);
6840 /* construct_reply_common has done us the favor to pre-fill the
6841 * command field with SMBtranss2 which is wrong :-)
6843 SCVAL(outbuf,smb_com,SMBtrans2);
6845 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6847 DLIST_REMOVE(conn->pending_trans, state);
6848 SAFE_FREE(state->data);
6849 SAFE_FREE(state->param);
6853 END_PROFILE(SMBtranss2);
6854 return(ERROR_DOS(ERRSRV,ERRnosupport));
6857 END_PROFILE(SMBtranss2);
6862 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6863 DLIST_REMOVE(conn->pending_trans, state);
6864 SAFE_FREE(state->data);
6865 SAFE_FREE(state->param);
6867 END_PROFILE(SMBtranss2);
6868 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);