2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
9 Extensively modified by Andrew Tridgell, 1995
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 /********************************************************************
38 Roundup a value to the nearest allocation roundup size boundary.
39 Only do this for Windows clients.
40 ********************************************************************/
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
44 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
46 /* Only roundup for Windows clients. */
47 enum remote_arch_types ra_type = get_remote_arch();
48 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49 val = SMB_ROUNDUP(val,rval);
54 /********************************************************************
55 Given a stat buffer return the allocated size on disk, taking into
57 ********************************************************************/
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
63 if(S_ISDIR(sbuf->st_mode)) {
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
70 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
73 if (fsp && fsp->initial_allocation_size)
74 ret = MAX(ret,fsp->initial_allocation_size);
76 return smb_roundup(conn, ret);
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 static const char *prohibited_ea_names[] = {
84 SAMBA_POSIX_INHERITANCE_EA_NAME,
85 SAMBA_XATTR_DOS_ATTRIB,
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
123 if (fsp && fsp->fh->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
138 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139 dump_data(10, val, sizeret);
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
147 pea->value.data = (unsigned char *)val;
148 pea->value.length = (size_t)sizeret;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157 const char *fname, size_t *pea_total_len)
159 /* Get a list of all xattrs. Max namesize is 64k. */
160 size_t ea_namelist_size = 1024;
165 struct ea_list *ea_list_head = NULL;
169 if (!lp_ea_support(SNUM(conn))) {
173 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
174 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
180 if (fsp && fsp->fh->fd != -1) {
181 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
183 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
186 if (sizeret == -1 && errno == ERANGE) {
187 ea_namelist_size *= 2;
196 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
199 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
200 struct ea_list *listp, *tmp;
202 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
205 listp = TALLOC_P(mem_ctx, struct ea_list);
209 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
215 push_ascii_fstring(dos_ea_name, listp->ea.name);
216 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
217 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
218 (unsigned int)*pea_total_len, dos_ea_name,
219 (unsigned int)listp->ea.value.length ));
221 DLIST_ADD_END(ea_list_head, listp, tmp);
223 /* Add on 4 for total length. */
224 if (*pea_total_len) {
229 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
233 /****************************************************************************
234 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
236 ****************************************************************************/
238 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
239 connection_struct *conn, struct ea_list *ea_list)
241 unsigned int ret_data_size = 4;
244 SMB_ASSERT(total_data_size >= 4);
246 if (!lp_ea_support(SNUM(conn))) {
251 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
254 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
255 dos_namelen = strlen(dos_ea_name);
256 if (dos_namelen > 255 || dos_namelen == 0) {
259 if (ea_list->ea.value.length > 65535) {
262 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
266 /* We know we have room. */
267 SCVAL(p,0,ea_list->ea.flags);
268 SCVAL(p,1,dos_namelen);
269 SSVAL(p,2,ea_list->ea.value.length);
270 fstrcpy(p+4, dos_ea_name);
271 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
273 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
274 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
277 ret_data_size = PTR_DIFF(p, pdata);
278 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
279 SIVAL(pdata,0,ret_data_size);
280 return ret_data_size;
283 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
285 size_t total_ea_len = 0;
286 TALLOC_CTX *mem_ctx = NULL;
288 if (!lp_ea_support(SNUM(conn))) {
291 mem_ctx = talloc_init("estimate_ea_size");
292 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
293 talloc_destroy(mem_ctx);
297 /****************************************************************************
298 Ensure the EA name is case insensitive by matching any existing EA name.
299 ****************************************************************************/
301 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
304 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
305 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
307 for (; ea_list; ea_list = ea_list->next) {
308 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
309 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
310 &unix_ea_name[5], ea_list->ea.name));
311 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
315 talloc_destroy(mem_ctx);
318 /****************************************************************************
319 Set or delete an extended attribute.
320 ****************************************************************************/
322 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
324 if (!lp_ea_support(SNUM(conn))) {
325 return NT_STATUS_EAS_NOT_SUPPORTED;
328 for (;ea_list; ea_list = ea_list->next) {
330 fstring unix_ea_name;
332 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
333 fstrcat(unix_ea_name, ea_list->ea.name);
335 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
337 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
339 if (samba_private_attr_name(unix_ea_name)) {
340 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
341 return NT_STATUS_ACCESS_DENIED;
344 if (ea_list->ea.value.length == 0) {
345 /* Remove the attribute. */
346 if (fsp && (fsp->fh->fd != -1)) {
347 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
348 unix_ea_name, fsp->fsp_name));
349 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
351 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
352 unix_ea_name, fname));
353 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
356 /* Removing a non existent attribute always succeeds. */
357 if (ret == -1 && errno == ENOATTR) {
358 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
364 if (fsp && (fsp->fh->fd != -1)) {
365 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
366 unix_ea_name, fsp->fsp_name));
367 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
368 ea_list->ea.value.data, ea_list->ea.value.length, 0);
370 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
371 unix_ea_name, fname));
372 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
373 ea_list->ea.value.data, ea_list->ea.value.length, 0);
379 if (errno == ENOTSUP) {
380 return NT_STATUS_EAS_NOT_SUPPORTED;
383 return map_nt_error_from_unix(errno);
389 /****************************************************************************
390 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
391 ****************************************************************************/
393 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
395 struct ea_list *ea_list_head = NULL;
398 while (offset + 2 < data_size) {
400 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
401 unsigned int namelen = CVAL(pdata,offset);
403 offset++; /* Go past the namelen byte. */
405 /* integer wrap paranioa. */
406 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
407 (offset > data_size) || (namelen > data_size) ||
408 (offset + namelen >= data_size)) {
411 /* Ensure the name is null terminated. */
412 if (pdata[offset + namelen] != '\0') {
415 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
420 offset += (namelen + 1); /* Go past the name + terminating zero. */
421 DLIST_ADD_END(ea_list_head, eal, tmp);
422 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
428 /****************************************************************************
429 Read one EA list entry from the buffer.
430 ****************************************************************************/
432 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
434 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
436 unsigned int namelen;
446 eal->ea.flags = CVAL(pdata,0);
447 namelen = CVAL(pdata,1);
448 val_len = SVAL(pdata,2);
450 if (4 + namelen + 1 + val_len > data_size) {
454 /* Ensure the name is null terminated. */
455 if (pdata[namelen + 4] != '\0') {
458 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
463 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
464 if (!eal->ea.value.data) {
468 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
470 /* Ensure we're null terminated just in case we print the value. */
471 eal->ea.value.data[val_len] = '\0';
472 /* But don't count the null. */
473 eal->ea.value.length--;
476 *pbytes_used = 4 + namelen + 1 + val_len;
479 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
480 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
485 /****************************************************************************
486 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
487 ****************************************************************************/
489 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
491 struct ea_list *ea_list_head = NULL;
493 size_t bytes_used = 0;
495 while (offset < data_size) {
497 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
503 DLIST_ADD_END(ea_list_head, eal, tmp);
504 offset += bytes_used;
510 /****************************************************************************
511 Count the total EA size needed.
512 ****************************************************************************/
514 static size_t ea_list_size(struct ea_list *ealist)
517 struct ea_list *listp;
520 for (listp = ealist; listp; listp = listp->next) {
521 push_ascii_fstring(dos_ea_name, listp->ea.name);
522 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
524 /* Add on 4 for total length. */
532 /****************************************************************************
533 Return a union of EA's from a file list and a list of names.
534 The TALLOC context for the two lists *MUST* be identical as we steal
535 memory from one list to add to another. JRA.
536 ****************************************************************************/
538 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
540 struct ea_list *nlistp, *flistp;
542 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
543 for (flistp = file_list; flistp; flistp = flistp->next) {
544 if (strequal(nlistp->ea.name, flistp->ea.name)) {
550 /* Copy the data from this entry. */
551 nlistp->ea.flags = flistp->ea.flags;
552 nlistp->ea.value = flistp->ea.value;
555 nlistp->ea.flags = 0;
556 ZERO_STRUCT(nlistp->ea.value);
560 *total_ea_len = ea_list_size(name_list);
564 /****************************************************************************
565 Send the required number of replies back.
566 We assume all fields other than the data fields are
567 set correctly for the type of call.
568 HACK ! Always assumes smb_setup field is zero.
569 ****************************************************************************/
571 int send_trans2_replies(char *outbuf,
578 /* As we are using a protocol > LANMAN1 then the max_send
579 variable must have been set in the sessetupX call.
580 This takes precedence over the max_xmit field in the
581 global struct. These different max_xmit variables should
582 be merged as this is now too confusing */
584 int data_to_send = datasize;
585 int params_to_send = paramsize;
589 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
590 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
591 int data_alignment_offset = 0;
593 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
595 set_message(outbuf,10,0,True);
597 /* If there genuinely are no parameters or data to send just send the empty packet */
599 if(params_to_send == 0 && data_to_send == 0) {
601 if (!send_smb(smbd_server_fd(),outbuf))
602 exit_server("send_trans2_replies: send_smb failed.");
606 /* When sending params and data ensure that both are nicely aligned */
607 /* Only do this alignment when there is also data to send - else
608 can cause NT redirector problems. */
610 if (((params_to_send % 4) != 0) && (data_to_send != 0))
611 data_alignment_offset = 4 - (params_to_send % 4);
613 /* Space is bufsize minus Netbios over TCP header minus SMB header */
614 /* The alignment_offset is to align the param bytes on an even byte
615 boundary. NT 4.0 Beta needs this to work correctly. */
617 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
619 /* useable_space can never be more than max_send minus the alignment offset. */
621 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
623 while (params_to_send || data_to_send) {
624 /* Calculate whether we will totally or partially fill this packet */
626 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
628 /* We can never send more than useable_space */
630 * Note that 'useable_space' does not include the alignment offsets,
631 * but we must include the alignment offsets in the calculation of
632 * the length of the data we send over the wire, as the alignment offsets
633 * are sent here. Fix from Marc_Jacobsen@hp.com.
636 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
638 set_message(outbuf, 10, total_sent_thistime, True);
640 /* Set total params and data to be sent */
641 SSVAL(outbuf,smb_tprcnt,paramsize);
642 SSVAL(outbuf,smb_tdrcnt,datasize);
644 /* Calculate how many parameters and data we can fit into
645 * this packet. Parameters get precedence
648 params_sent_thistime = MIN(params_to_send,useable_space);
649 data_sent_thistime = useable_space - params_sent_thistime;
650 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
652 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
654 /* smb_proff is the offset from the start of the SMB header to the
655 parameter bytes, however the first 4 bytes of outbuf are
656 the Netbios over TCP header. Thus use smb_base() to subtract
657 them from the calculation */
659 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
661 if(params_sent_thistime == 0)
662 SSVAL(outbuf,smb_prdisp,0);
664 /* Absolute displacement of param bytes sent in this packet */
665 SSVAL(outbuf,smb_prdisp,pp - params);
667 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
668 if(data_sent_thistime == 0) {
669 SSVAL(outbuf,smb_droff,0);
670 SSVAL(outbuf,smb_drdisp, 0);
672 /* The offset of the data bytes is the offset of the
673 parameter bytes plus the number of parameters being sent this time */
674 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
675 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
676 SSVAL(outbuf,smb_drdisp, pd - pdata);
679 /* Copy the param bytes into the packet */
681 if(params_sent_thistime)
682 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
684 /* Copy in the data bytes */
685 if(data_sent_thistime)
686 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
687 data_alignment_offset,pd,data_sent_thistime);
689 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
690 params_sent_thistime, data_sent_thistime, useable_space));
691 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
692 params_to_send, data_to_send, paramsize, datasize));
694 /* Send the packet */
696 if (!send_smb(smbd_server_fd(),outbuf))
697 exit_server("send_trans2_replies: send_smb failed.");
699 pp += params_sent_thistime;
700 pd += data_sent_thistime;
702 params_to_send -= params_sent_thistime;
703 data_to_send -= data_sent_thistime;
706 if(params_to_send < 0 || data_to_send < 0) {
707 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
708 params_to_send, data_to_send));
716 /****************************************************************************
717 Reply to a TRANSACT2_OPEN.
718 ****************************************************************************/
720 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
721 char **pparams, int total_params, char **ppdata, int total_data,
722 unsigned int max_data_bytes)
724 char *params = *pparams;
725 char *pdata = *ppdata;
730 BOOL return_additional_info;
741 SMB_STRUCT_STAT sbuf;
743 BOOL bad_path = False;
745 TALLOC_CTX *ctx = NULL;
746 struct ea_list *ea_list = NULL;
751 uint32 create_disposition;
752 uint32 create_options = 0;
755 * Ensure we have enough parameters to perform the operation.
758 if (total_params < 29) {
759 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
762 flags = SVAL(params, 0);
763 deny_mode = SVAL(params, 2);
764 open_attr = SVAL(params,6);
765 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
766 if (oplock_request) {
767 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
771 return_additional_info = BITSETW(params,0);
772 open_sattr = SVAL(params, 4);
773 open_time = make_unix_date3(params+8);
775 open_ofun = SVAL(params,12);
776 open_size = IVAL(params,14);
780 return(ERROR_DOS(ERRSRV,ERRaccess));
783 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
784 if (!NT_STATUS_IS_OK(status)) {
785 return ERROR_NT(status);
788 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
789 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
790 (unsigned int)open_ofun, open_size));
792 /* XXXX we need to handle passed times, sattr and flags */
794 unix_convert(fname,conn,0,&bad_path,&sbuf);
796 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
799 if (!check_name(fname,conn)) {
800 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
803 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
808 return ERROR_DOS(ERRDOS, ERRbadaccess);
811 /* Any data in this call is an EA list. */
812 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
813 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
816 if (total_data != 4) {
817 if (total_data < 10) {
818 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
821 if (IVAL(pdata,0) > total_data) {
822 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
823 IVAL(pdata,0), (unsigned int)total_data));
824 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
827 ctx = talloc_init("TRANS2_OPEN_SET_EA");
829 return ERROR_NT(NT_STATUS_NO_MEMORY);
831 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
834 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
836 } else if (IVAL(pdata,0) != 4) {
837 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
840 status = open_file_ntcreate(conn,fname,&sbuf,
849 if (!NT_STATUS_IS_OK(status)) {
851 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
852 /* We have re-scheduled this call. */
855 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
858 size = get_file_size(sbuf);
859 fattr = dos_mode(conn,fname,&sbuf);
860 mtime = sbuf.st_mtime;
864 close_file(fsp,ERROR_CLOSE);
865 return(ERROR_DOS(ERRDOS,ERRnoaccess));
868 /* Save the requested allocation size. */
869 /* Allocate space for the file if a size hint is supplied */
870 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
871 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
872 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
873 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
874 if (fsp->is_directory) {
875 close_file(fsp,ERROR_CLOSE);
876 /* Can't set allocation size on a directory. */
877 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
879 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
880 close_file(fsp,ERROR_CLOSE);
881 return ERROR_NT(NT_STATUS_DISK_FULL);
884 /* Adjust size here to return the right size in the reply.
885 Windows does it this way. */
886 size = fsp->initial_allocation_size;
888 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
892 if (total_data && smb_action == FILE_WAS_CREATED) {
893 status = set_ea(conn, fsp, fname, ea_list);
895 if (!NT_STATUS_IS_OK(status)) {
896 close_file(fsp,ERROR_CLOSE);
897 return ERROR_NT(status);
901 /* Realloc the size of parameters and data we will return */
902 *pparams = SMB_REALLOC(*pparams, 30);
903 if(*pparams == NULL ) {
904 return ERROR_NT(NT_STATUS_NO_MEMORY);
908 SSVAL(params,0,fsp->fnum);
909 SSVAL(params,2,open_attr);
910 srv_put_dos_date2(params,4, mtime);
911 SIVAL(params,8, (uint32)size);
912 SSVAL(params,12,deny_mode);
913 SSVAL(params,14,0); /* open_type - file or directory. */
914 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
916 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
917 smb_action |= EXTENDED_OPLOCK_GRANTED;
920 SSVAL(params,18,smb_action);
923 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
925 SIVAL(params,20,inode);
926 SSVAL(params,24,0); /* Padding. */
928 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
929 SIVAL(params, 26, ea_size);
931 SIVAL(params, 26, 0);
934 /* Send the required number of replies */
935 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
940 /*********************************************************
941 Routine to check if a given string matches exactly.
942 as a special case a mask of "." does NOT match. That
943 is required for correct wildcard semantics
944 Case can be significant or not.
945 **********************************************************/
947 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
949 if (mask[0] == '.' && mask[1] == 0)
952 return strcmp(str,mask)==0;
953 if (StrCaseCmp(str,mask) != 0) {
956 if (ms_has_wild(str)) {
962 /****************************************************************************
963 Return the filetype for UNIX extensions.
964 ****************************************************************************/
966 static uint32 unix_filetype(mode_t mode)
969 return UNIX_TYPE_FILE;
970 else if(S_ISDIR(mode))
971 return UNIX_TYPE_DIR;
973 else if(S_ISLNK(mode))
974 return UNIX_TYPE_SYMLINK;
977 else if(S_ISCHR(mode))
978 return UNIX_TYPE_CHARDEV;
981 else if(S_ISBLK(mode))
982 return UNIX_TYPE_BLKDEV;
985 else if(S_ISFIFO(mode))
986 return UNIX_TYPE_FIFO;
989 else if(S_ISSOCK(mode))
990 return UNIX_TYPE_SOCKET;
993 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
994 return UNIX_TYPE_UNKNOWN;
997 /****************************************************************************
998 Map wire perms onto standard UNIX permissions. Obey share restrictions.
999 ****************************************************************************/
1001 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
1005 if (perms == SMB_MODE_NO_CHANGE)
1006 return pst->st_mode;
1008 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1009 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1010 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1011 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1012 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1013 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1014 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1015 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1016 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1018 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1021 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1024 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1027 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
1028 ret &= lp_dir_mask(SNUM(conn));
1029 /* Add in force bits */
1030 ret |= lp_force_dir_mode(SNUM(conn));
1032 /* Apply mode mask */
1033 ret &= lp_create_mask(SNUM(conn));
1034 /* Add in force bits */
1035 ret |= lp_force_create_mode(SNUM(conn));
1041 /****************************************************************************
1042 Get a level dependent lanman2 dir entry.
1043 ****************************************************************************/
1045 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1046 void *inbuf, void *outbuf,
1047 char *path_mask,uint32 dirtype,int info_level,
1048 int requires_resume_key,
1049 BOOL dont_descend,char **ppdata,
1050 char *base_data, int space_remaining,
1051 BOOL *out_of_space, BOOL *got_exact_match,
1052 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1056 SMB_STRUCT_STAT sbuf;
1060 char *p, *q, *pdata = *ppdata;
1064 SMB_OFF_T file_size = 0;
1065 SMB_BIG_UINT allocation_size = 0;
1067 time_t mdate=0, adate=0, cdate=0;
1069 char *last_entry_ptr;
1071 uint32 nt_extmode; /* Used for NT connections instead of mode */
1072 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1073 BOOL check_mangled_names = lp_manglednames(conn->params);
1076 *out_of_space = False;
1077 *got_exact_match = False;
1082 p = strrchr_m(path_mask,'/');
1085 pstrcpy(mask,"*.*");
1089 pstrcpy(mask, path_mask);
1094 BOOL ms_dfs_link = False;
1096 /* Needed if we run out of space */
1097 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1098 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1101 * Due to bugs in NT client redirectors we are not using
1102 * resume keys any more - set them to zero.
1103 * Check out the related comments in findfirst/findnext.
1109 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1110 (long)conn->dirptr,curr_dirpos));
1115 pstrcpy(fname,dname);
1117 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1118 got_match = mask_match(fname, mask, conn->case_sensitive);
1120 if(!got_match && check_mangled_names &&
1121 !mangle_is_8_3(fname, False, conn->params)) {
1124 * It turns out that NT matches wildcards against
1125 * both long *and* short names. This may explain some
1126 * of the wildcard wierdness from old DOS clients
1127 * that some people have been seeing.... JRA.
1131 pstrcpy( newname, fname);
1132 mangle_map( newname, True, False, conn->params);
1133 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1134 got_match = mask_match(newname, mask, conn->case_sensitive);
1138 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1139 if (dont_descend && !isdots)
1142 pstrcpy(pathreal,conn->dirpath);
1144 pstrcat(pathreal,"/");
1145 pstrcat(pathreal,dname);
1147 if (INFO_LEVEL_IS_UNIX(info_level)) {
1148 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1149 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1150 pathreal,strerror(errno)));
1153 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1155 /* Needed to show the msdfs symlinks as
1158 if(lp_host_msdfs() &&
1159 lp_msdfs_root(SNUM(conn)) &&
1160 ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1162 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1163 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1167 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1168 pathreal,strerror(errno)));
1174 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1176 mode = dos_mode(conn,pathreal,&sbuf);
1179 if (!dir_check_ftype(conn,mode,dirtype)) {
1180 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1185 file_size = get_file_size(sbuf);
1186 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1187 mdate = sbuf.st_mtime;
1188 adate = sbuf.st_atime;
1189 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1191 if (lp_dos_filetime_resolution(SNUM(conn))) {
1198 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1202 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1206 mangle_map(fname,False,True,conn->params);
1211 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1213 switch (info_level) {
1214 case SMB_FIND_INFO_STANDARD:
1215 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1216 if(requires_resume_key) {
1220 srv_put_dos_date2(p,0,cdate);
1221 srv_put_dos_date2(p,4,adate);
1222 srv_put_dos_date2(p,8,mdate);
1223 SIVAL(p,12,(uint32)file_size);
1224 SIVAL(p,16,(uint32)allocation_size);
1228 p += align_string(outbuf, p, 0);
1229 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1230 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1232 SCVAL(nameptr, -1, len - 2);
1234 SCVAL(nameptr, -1, 0);
1238 SCVAL(nameptr, -1, len - 1);
1240 SCVAL(nameptr, -1, 0);
1246 case SMB_FIND_EA_SIZE:
1247 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1248 if(requires_resume_key) {
1252 srv_put_dos_date2(p,0,cdate);
1253 srv_put_dos_date2(p,4,adate);
1254 srv_put_dos_date2(p,8,mdate);
1255 SIVAL(p,12,(uint32)file_size);
1256 SIVAL(p,16,(uint32)allocation_size);
1259 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1260 SIVAL(p,22,ea_size); /* Extended attributes */
1264 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1265 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1278 SCVAL(nameptr,0,len);
1280 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1283 case SMB_FIND_EA_LIST:
1285 struct ea_list *file_list = NULL;
1288 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1292 if(requires_resume_key) {
1296 srv_put_dos_date2(p,0,cdate);
1297 srv_put_dos_date2(p,4,adate);
1298 srv_put_dos_date2(p,8,mdate);
1299 SIVAL(p,12,(uint32)file_size);
1300 SIVAL(p,16,(uint32)allocation_size);
1302 p += 22; /* p now points to the EA area. */
1304 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1305 name_list = ea_list_union(name_list, file_list, &ea_len);
1307 /* We need to determine if this entry will fit in the space available. */
1308 /* Max string size is 255 bytes. */
1309 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1310 /* Move the dirptr back to prev_dirpos */
1311 dptr_SeekDir(conn->dirptr, prev_dirpos);
1312 *out_of_space = True;
1313 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1314 return False; /* Not finished - just out of space */
1317 /* Push the ea_data followed by the name. */
1318 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1320 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1321 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1334 SCVAL(nameptr,0,len);
1336 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1340 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1341 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1342 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1344 SIVAL(p,0,reskey); p += 4;
1345 put_long_date(p,cdate); p += 8;
1346 put_long_date(p,adate); p += 8;
1347 put_long_date(p,mdate); p += 8;
1348 put_long_date(p,mdate); p += 8;
1349 SOFF_T(p,0,file_size); p += 8;
1350 SOFF_T(p,0,allocation_size); p += 8;
1351 SIVAL(p,0,nt_extmode); p += 4;
1352 q = p; p += 4; /* q is placeholder for name length. */
1354 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1355 SIVAL(p,0,ea_size); /* Extended attributes */
1358 /* Clear the short name buffer. This is
1359 * IMPORTANT as not doing so will trigger
1360 * a Win2k client bug. JRA.
1362 if (!was_8_3 && check_mangled_names) {
1363 pstring mangled_name;
1364 pstrcpy(mangled_name, fname);
1365 mangle_map(mangled_name,True,True,
1367 mangled_name[12] = 0;
1368 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1370 memset(p + 2 + len,'\0',24 - len);
1377 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1380 SIVAL(p,0,0); /* Ensure any padding is null. */
1381 len = PTR_DIFF(p, pdata);
1382 len = (len + 3) & ~3;
1387 case SMB_FIND_FILE_DIRECTORY_INFO:
1388 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1390 SIVAL(p,0,reskey); p += 4;
1391 put_long_date(p,cdate); p += 8;
1392 put_long_date(p,adate); p += 8;
1393 put_long_date(p,mdate); p += 8;
1394 put_long_date(p,mdate); p += 8;
1395 SOFF_T(p,0,file_size); p += 8;
1396 SOFF_T(p,0,allocation_size); p += 8;
1397 SIVAL(p,0,nt_extmode); p += 4;
1398 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1401 SIVAL(p,0,0); /* Ensure any padding is null. */
1402 len = PTR_DIFF(p, pdata);
1403 len = (len + 3) & ~3;
1408 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1409 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1411 SIVAL(p,0,reskey); p += 4;
1412 put_long_date(p,cdate); p += 8;
1413 put_long_date(p,adate); p += 8;
1414 put_long_date(p,mdate); p += 8;
1415 put_long_date(p,mdate); p += 8;
1416 SOFF_T(p,0,file_size); p += 8;
1417 SOFF_T(p,0,allocation_size); p += 8;
1418 SIVAL(p,0,nt_extmode); p += 4;
1419 q = p; p += 4; /* q is placeholder for name length. */
1421 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1422 SIVAL(p,0,ea_size); /* Extended attributes */
1425 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1429 SIVAL(p,0,0); /* Ensure any padding is null. */
1430 len = PTR_DIFF(p, pdata);
1431 len = (len + 3) & ~3;
1436 case SMB_FIND_FILE_NAMES_INFO:
1437 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1439 SIVAL(p,0,reskey); p += 4;
1441 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1442 acl on a dir (tridge) */
1443 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1446 SIVAL(p,0,0); /* Ensure any padding is null. */
1447 len = PTR_DIFF(p, pdata);
1448 len = (len + 3) & ~3;
1453 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1454 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1456 SIVAL(p,0,reskey); p += 4;
1457 put_long_date(p,cdate); p += 8;
1458 put_long_date(p,adate); p += 8;
1459 put_long_date(p,mdate); p += 8;
1460 put_long_date(p,mdate); p += 8;
1461 SOFF_T(p,0,file_size); p += 8;
1462 SOFF_T(p,0,allocation_size); p += 8;
1463 SIVAL(p,0,nt_extmode); p += 4;
1464 q = p; p += 4; /* q is placeholder for name length. */
1466 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1467 SIVAL(p,0,ea_size); /* Extended attributes */
1470 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1471 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1472 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1473 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1476 SIVAL(p,0,0); /* Ensure any padding is null. */
1477 len = PTR_DIFF(p, pdata);
1478 len = (len + 3) & ~3;
1483 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1484 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1485 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1487 SIVAL(p,0,reskey); p += 4;
1488 put_long_date(p,cdate); p += 8;
1489 put_long_date(p,adate); p += 8;
1490 put_long_date(p,mdate); p += 8;
1491 put_long_date(p,mdate); p += 8;
1492 SOFF_T(p,0,file_size); p += 8;
1493 SOFF_T(p,0,allocation_size); p += 8;
1494 SIVAL(p,0,nt_extmode); p += 4;
1495 q = p; p += 4; /* q is placeholder for name length */
1497 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1498 SIVAL(p,0,ea_size); /* Extended attributes */
1501 /* Clear the short name buffer. This is
1502 * IMPORTANT as not doing so will trigger
1503 * a Win2k client bug. JRA.
1505 if (!was_8_3 && check_mangled_names) {
1506 pstring mangled_name;
1507 pstrcpy(mangled_name, fname);
1508 mangle_map(mangled_name,True,True,
1510 mangled_name[12] = 0;
1511 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1514 memset(p + 2 + len,'\0',24 - len);
1521 SSVAL(p,0,0); p += 2; /* Reserved ? */
1522 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1523 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1524 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1527 SIVAL(p,0,0); /* Ensure any padding is null. */
1528 len = PTR_DIFF(p, pdata);
1529 len = (len + 3) & ~3;
1534 /* CIFS UNIX Extension. */
1536 case SMB_FIND_FILE_UNIX:
1537 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1539 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1541 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1542 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1545 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1548 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1549 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1550 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1553 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1557 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1561 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1564 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1568 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1572 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1575 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1579 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1583 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1585 SIVAL(p,0,0); /* Ensure any padding is null. */
1587 len = PTR_DIFF(p, pdata);
1588 len = (len + 3) & ~3;
1589 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1591 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1600 if (PTR_DIFF(p,pdata) > space_remaining) {
1601 /* Move the dirptr back to prev_dirpos */
1602 dptr_SeekDir(conn->dirptr, prev_dirpos);
1603 *out_of_space = True;
1604 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1605 return False; /* Not finished - just out of space */
1608 /* Setup the last entry pointer, as an offset from base_data */
1609 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1610 /* Advance the data pointer to the next slot */
1616 /****************************************************************************
1617 Reply to a TRANS2_FINDFIRST.
1618 ****************************************************************************/
1620 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1621 char **pparams, int total_params, char **ppdata, int total_data,
1622 unsigned int max_data_bytes)
1624 /* We must be careful here that we don't return more than the
1625 allowed number of data bytes. If this means returning fewer than
1626 maxentries then so be it. We assume that the redirector has
1627 enough room for the fixed number of parameter bytes it has
1629 char *params = *pparams;
1630 char *pdata = *ppdata;
1631 uint32 dirtype = SVAL(params,0);
1632 int maxentries = SVAL(params,2);
1633 uint16 findfirst_flags = SVAL(params,4);
1634 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1635 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1636 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1637 int info_level = SVAL(params,6);
1641 int last_entry_off=0;
1645 BOOL finished = False;
1646 BOOL dont_descend = False;
1647 BOOL out_of_space = False;
1648 int space_remaining;
1649 BOOL bad_path = False;
1650 BOOL mask_contains_wcard = False;
1651 SMB_STRUCT_STAT sbuf;
1652 TALLOC_CTX *ea_ctx = NULL;
1653 struct ea_list *ea_list = NULL;
1654 NTSTATUS ntstatus = NT_STATUS_OK;
1656 if (total_params < 12) {
1657 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1660 *directory = *mask = 0;
1662 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1663 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1664 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1665 info_level, max_data_bytes));
1668 /* W2K3 seems to treat zero as 1. */
1672 switch (info_level) {
1673 case SMB_FIND_INFO_STANDARD:
1674 case SMB_FIND_EA_SIZE:
1675 case SMB_FIND_EA_LIST:
1676 case SMB_FIND_FILE_DIRECTORY_INFO:
1677 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1678 case SMB_FIND_FILE_NAMES_INFO:
1679 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1680 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1681 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1683 case SMB_FIND_FILE_UNIX:
1684 if (!lp_unix_extensions()) {
1685 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1689 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1692 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1693 if (!NT_STATUS_IS_OK(ntstatus)) {
1694 return ERROR_NT(ntstatus);
1697 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1699 unix_convert(directory,conn,0,&bad_path,&sbuf);
1701 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1703 if(!check_name(directory,conn)) {
1704 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1707 p = strrchr_m(directory,'/');
1709 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1710 if((directory[0] == '.') && (directory[1] == '\0')) {
1712 mask_contains_wcard = True;
1714 pstrcpy(mask,directory);
1716 pstrcpy(directory,"./");
1722 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1724 if (info_level == SMB_FIND_EA_LIST) {
1727 if (total_data < 4) {
1728 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1731 ea_size = IVAL(pdata,0);
1732 if (ea_size != total_data) {
1733 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1734 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1735 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1738 if (!lp_ea_support(SNUM(conn))) {
1739 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1742 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1743 return ERROR_NT(NT_STATUS_NO_MEMORY);
1746 /* Pull out the list of names. */
1747 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1749 talloc_destroy(ea_ctx);
1750 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1754 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1755 if(*ppdata == NULL ) {
1756 talloc_destroy(ea_ctx);
1757 return ERROR_NT(NT_STATUS_NO_MEMORY);
1761 /* Realloc the params space */
1762 *pparams = SMB_REALLOC(*pparams, 10);
1763 if (*pparams == NULL) {
1764 talloc_destroy(ea_ctx);
1765 return ERROR_NT(NT_STATUS_NO_MEMORY);
1769 /* Save the wildcard match and attribs we are using on this directory -
1770 needed as lanman2 assumes these are being saved between calls */
1772 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1774 talloc_destroy(ea_ctx);
1775 return(UNIXERROR(ERRDOS,ERRbadfile));
1778 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1780 /* We don't need to check for VOL here as this is returned by
1781 a different TRANS2 call. */
1783 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1784 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1785 dont_descend = True;
1788 space_remaining = max_data_bytes;
1789 out_of_space = False;
1791 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1792 BOOL got_exact_match = False;
1794 /* this is a heuristic to avoid seeking the dirptr except when
1795 absolutely necessary. It allows for a filename of about 40 chars */
1796 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1797 out_of_space = True;
1800 finished = !get_lanman2_dir_entry(conn,
1802 mask,dirtype,info_level,
1803 requires_resume_key,dont_descend,
1804 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1805 &last_entry_off, ea_list, ea_ctx);
1808 if (finished && out_of_space)
1811 if (!finished && !out_of_space)
1815 * As an optimisation if we know we aren't looking
1816 * for a wildcard name (ie. the name matches the wildcard exactly)
1817 * then we can finish on any (first) match.
1818 * This speeds up large directory searches. JRA.
1824 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1827 talloc_destroy(ea_ctx);
1829 /* Check if we can close the dirptr */
1830 if(close_after_first || (finished && close_if_end)) {
1831 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1832 dptr_close(&dptr_num);
1836 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1837 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1838 * the protocol level is less than NT1. Tested with smbclient. JRA.
1839 * This should fix the OS/2 client bug #2335.
1842 if(numentries == 0) {
1843 dptr_close(&dptr_num);
1844 if (Protocol < PROTOCOL_NT1) {
1845 return ERROR_DOS(ERRDOS,ERRnofiles);
1847 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1851 /* At this point pdata points to numentries directory entries. */
1853 /* Set up the return parameter block */
1854 SSVAL(params,0,dptr_num);
1855 SSVAL(params,2,numentries);
1856 SSVAL(params,4,finished);
1857 SSVAL(params,6,0); /* Never an EA error */
1858 SSVAL(params,8,last_entry_off);
1860 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1862 if ((! *directory) && dptr_path(dptr_num))
1863 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1865 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1866 smb_fn_name(CVAL(inbuf,smb_com)),
1867 mask, directory, dirtype, numentries ) );
1870 * Force a name mangle here to ensure that the
1871 * mask as an 8.3 name is top of the mangled cache.
1872 * The reasons for this are subtle. Don't remove
1873 * this code unless you know what you are doing
1874 * (see PR#13758). JRA.
1877 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1878 mangle_map(mask, True, True, conn->params);
1883 /****************************************************************************
1884 Reply to a TRANS2_FINDNEXT.
1885 ****************************************************************************/
1887 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1888 char **pparams, int total_params, char **ppdata, int total_data,
1889 unsigned int max_data_bytes)
1891 /* We must be careful here that we don't return more than the
1892 allowed number of data bytes. If this means returning fewer than
1893 maxentries then so be it. We assume that the redirector has
1894 enough room for the fixed number of parameter bytes it has
1896 char *params = *pparams;
1897 char *pdata = *ppdata;
1898 int dptr_num = SVAL(params,0);
1899 int maxentries = SVAL(params,2);
1900 uint16 info_level = SVAL(params,4);
1901 uint32 resume_key = IVAL(params,6);
1902 uint16 findnext_flags = SVAL(params,10);
1903 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1904 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1905 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1906 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1907 BOOL mask_contains_wcard = False;
1908 pstring resume_name;
1914 int i, last_entry_off=0;
1915 BOOL finished = False;
1916 BOOL dont_descend = False;
1917 BOOL out_of_space = False;
1918 int space_remaining;
1919 TALLOC_CTX *ea_ctx = NULL;
1920 struct ea_list *ea_list = NULL;
1921 NTSTATUS ntstatus = NT_STATUS_OK;
1923 if (total_params < 12) {
1924 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1927 *mask = *directory = *resume_name = 0;
1929 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1930 if (!NT_STATUS_IS_OK(ntstatus)) {
1931 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1932 complain (it thinks we're asking for the directory above the shared
1933 path or an invalid name). Catch this as the resume name is only compared, never used in
1934 a file access. JRA. */
1935 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1936 pstrcpy(resume_name, "..");
1937 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1938 pstrcpy(resume_name, ".");
1940 return ERROR_NT(ntstatus);
1944 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1945 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1946 resume_key = %d resume name = %s continue=%d level = %d\n",
1947 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1948 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1951 /* W2K3 seems to treat zero as 1. */
1955 switch (info_level) {
1956 case SMB_FIND_INFO_STANDARD:
1957 case SMB_FIND_EA_SIZE:
1958 case SMB_FIND_EA_LIST:
1959 case SMB_FIND_FILE_DIRECTORY_INFO:
1960 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1961 case SMB_FIND_FILE_NAMES_INFO:
1962 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1963 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1964 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1966 case SMB_FIND_FILE_UNIX:
1967 if (!lp_unix_extensions()) {
1968 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1972 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1975 if (info_level == SMB_FIND_EA_LIST) {
1978 if (total_data < 4) {
1979 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1982 ea_size = IVAL(pdata,0);
1983 if (ea_size != total_data) {
1984 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1985 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1986 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1989 if (!lp_ea_support(SNUM(conn))) {
1990 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1993 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1994 return ERROR_NT(NT_STATUS_NO_MEMORY);
1997 /* Pull out the list of names. */
1998 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2000 talloc_destroy(ea_ctx);
2001 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2005 *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2006 if(*ppdata == NULL) {
2007 talloc_destroy(ea_ctx);
2008 return ERROR_NT(NT_STATUS_NO_MEMORY);
2013 /* Realloc the params space */
2014 *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2015 if(*pparams == NULL ) {
2016 talloc_destroy(ea_ctx);
2017 return ERROR_NT(NT_STATUS_NO_MEMORY);
2022 /* Check that the dptr is valid */
2023 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2024 talloc_destroy(ea_ctx);
2025 return ERROR_DOS(ERRDOS,ERRnofiles);
2028 string_set(&conn->dirpath,dptr_path(dptr_num));
2030 /* Get the wildcard mask from the dptr */
2031 if((p = dptr_wcard(dptr_num))== NULL) {
2032 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2033 talloc_destroy(ea_ctx);
2034 return ERROR_DOS(ERRDOS,ERRnofiles);
2038 pstrcpy(directory,conn->dirpath);
2040 /* Get the attr mask from the dptr */
2041 dirtype = dptr_attr(dptr_num);
2043 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2044 dptr_num, mask, dirtype,
2046 dptr_TellDir(conn->dirptr)));
2048 /* We don't need to check for VOL here as this is returned by
2049 a different TRANS2 call. */
2051 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2052 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2053 dont_descend = True;
2056 space_remaining = max_data_bytes;
2057 out_of_space = False;
2060 * Seek to the correct position. We no longer use the resume key but
2061 * depend on the last file name instead.
2064 if(*resume_name && !continue_bit) {
2067 long current_pos = 0;
2069 * Remember, mangle_map is called by
2070 * get_lanman2_dir_entry(), so the resume name
2071 * could be mangled. Ensure we check the unmangled name.
2074 if (mangle_is_mangled(resume_name, conn->params)) {
2075 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2080 * Fix for NT redirector problem triggered by resume key indexes
2081 * changing between directory scans. We now return a resume key of 0
2082 * and instead look for the filename to continue from (also given
2083 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2084 * findfirst/findnext (as is usual) then the directory pointer
2085 * should already be at the correct place.
2088 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2089 } /* end if resume_name && !continue_bit */
2091 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2092 BOOL got_exact_match = False;
2094 /* this is a heuristic to avoid seeking the dirptr except when
2095 absolutely necessary. It allows for a filename of about 40 chars */
2096 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2097 out_of_space = True;
2100 finished = !get_lanman2_dir_entry(conn,
2102 mask,dirtype,info_level,
2103 requires_resume_key,dont_descend,
2104 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2105 &last_entry_off, ea_list, ea_ctx);
2108 if (finished && out_of_space)
2111 if (!finished && !out_of_space)
2115 * As an optimisation if we know we aren't looking
2116 * for a wildcard name (ie. the name matches the wildcard exactly)
2117 * then we can finish on any (first) match.
2118 * This speeds up large directory searches. JRA.
2124 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2127 talloc_destroy(ea_ctx);
2129 /* Check if we can close the dirptr */
2130 if(close_after_request || (finished && close_if_end)) {
2131 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2132 dptr_close(&dptr_num); /* This frees up the saved mask */
2135 /* Set up the return parameter block */
2136 SSVAL(params,0,numentries);
2137 SSVAL(params,2,finished);
2138 SSVAL(params,4,0); /* Never an EA error */
2139 SSVAL(params,6,last_entry_off);
2141 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2143 if ((! *directory) && dptr_path(dptr_num))
2144 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2146 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2147 smb_fn_name(CVAL(inbuf,smb_com)),
2148 mask, directory, dirtype, numentries ) );
2153 /****************************************************************************
2154 Reply to a TRANS2_QFSINFO (query filesystem info).
2155 ****************************************************************************/
2157 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2158 char **pparams, int total_params, char **ppdata, int total_data,
2159 unsigned int max_data_bytes)
2161 char *pdata = *ppdata;
2162 char *params = *pparams;
2163 uint16 info_level = SVAL(params,0);
2166 char *vname = volume_label(SNUM(conn));
2167 int snum = SNUM(conn);
2168 char *fstype = lp_fstype(SNUM(conn));
2171 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2173 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2174 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2175 return ERROR_DOS(ERRSRV,ERRinvdevice);
2178 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2179 if (*ppdata == NULL ) {
2180 return ERROR_NT(NT_STATUS_NO_MEMORY);
2184 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2186 switch (info_level) {
2187 case SMB_INFO_ALLOCATION:
2189 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2191 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2192 return(UNIXERROR(ERRHRD,ERRgeneral));
2195 block_size = lp_block_size(snum);
2196 if (bsize < block_size) {
2197 SMB_BIG_UINT factor = block_size/bsize;
2202 if (bsize > block_size) {
2203 SMB_BIG_UINT factor = bsize/block_size;
2208 bytes_per_sector = 512;
2209 sectors_per_unit = bsize/bytes_per_sector;
2211 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2212 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2213 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2215 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2216 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2217 SIVAL(pdata,l1_cUnit,dsize);
2218 SIVAL(pdata,l1_cUnitAvail,dfree);
2219 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2223 case SMB_INFO_VOLUME:
2224 /* Return volume name */
2226 * Add volume serial number - hash of a combination of
2227 * the called hostname and the service name.
2229 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2231 * Win2k3 and previous mess this up by sending a name length
2232 * one byte short. I believe only older clients (OS/2 Win9x) use
2233 * this call so try fixing this by adding a terminating null to
2234 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2236 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2237 SCVAL(pdata,l2_vol_cch,len);
2238 data_len = l2_vol_szVolLabel + len;
2239 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2240 (unsigned)st.st_ctime, len, vname));
2243 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2244 case SMB_FS_ATTRIBUTE_INFORMATION:
2247 #if defined(HAVE_SYS_QUOTAS)
2248 quota_flag = FILE_VOLUME_QUOTAS;
2251 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2252 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2253 quota_flag); /* FS ATTRIBUTES */
2255 SIVAL(pdata,4,255); /* Max filename component length */
2256 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2257 and will think we can't do long filenames */
2258 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2260 data_len = 12 + len;
2263 case SMB_QUERY_FS_LABEL_INFO:
2264 case SMB_FS_LABEL_INFORMATION:
2265 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2270 case SMB_QUERY_FS_VOLUME_INFO:
2271 case SMB_FS_VOLUME_INFORMATION:
2274 * Add volume serial number - hash of a combination of
2275 * the called hostname and the service name.
2277 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2278 (str_checksum(get_local_machine_name())<<16));
2280 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2281 SIVAL(pdata,12,len);
2283 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2284 (int)strlen(vname),vname, lp_servicename(snum)));
2287 case SMB_QUERY_FS_SIZE_INFO:
2288 case SMB_FS_SIZE_INFORMATION:
2290 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2292 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2293 return(UNIXERROR(ERRHRD,ERRgeneral));
2295 block_size = lp_block_size(snum);
2296 if (bsize < block_size) {
2297 SMB_BIG_UINT factor = block_size/bsize;
2302 if (bsize > block_size) {
2303 SMB_BIG_UINT factor = bsize/block_size;
2308 bytes_per_sector = 512;
2309 sectors_per_unit = bsize/bytes_per_sector;
2310 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2311 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2312 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2313 SBIG_UINT(pdata,0,dsize);
2314 SBIG_UINT(pdata,8,dfree);
2315 SIVAL(pdata,16,sectors_per_unit);
2316 SIVAL(pdata,20,bytes_per_sector);
2320 case SMB_FS_FULL_SIZE_INFORMATION:
2322 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2324 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2325 return(UNIXERROR(ERRHRD,ERRgeneral));
2327 block_size = lp_block_size(snum);
2328 if (bsize < block_size) {
2329 SMB_BIG_UINT factor = block_size/bsize;
2334 if (bsize > block_size) {
2335 SMB_BIG_UINT factor = bsize/block_size;
2340 bytes_per_sector = 512;
2341 sectors_per_unit = bsize/bytes_per_sector;
2342 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2343 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2344 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2345 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2346 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2347 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2348 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2349 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2353 case SMB_QUERY_FS_DEVICE_INFO:
2354 case SMB_FS_DEVICE_INFORMATION:
2356 SIVAL(pdata,0,0); /* dev type */
2357 SIVAL(pdata,4,0); /* characteristics */
2360 #ifdef HAVE_SYS_QUOTAS
2361 case SMB_FS_QUOTA_INFORMATION:
2363 * what we have to send --metze:
2365 * Unknown1: 24 NULL bytes
2366 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2367 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2368 * Quota Flags: 2 byte :
2369 * Unknown3: 6 NULL bytes
2373 * details for Quota Flags:
2375 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2376 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2377 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2378 * 0x0001 Enable Quotas: enable quota for this fs
2382 /* we need to fake up a fsp here,
2383 * because its not send in this call
2386 SMB_NTQUOTA_STRUCT quotas;
2389 ZERO_STRUCT(quotas);
2395 if (current_user.ut.uid != 0) {
2396 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2397 lp_servicename(SNUM(conn)),conn->user));
2398 return ERROR_DOS(ERRDOS,ERRnoaccess);
2401 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2402 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2403 return ERROR_DOS(ERRSRV,ERRerror);
2408 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2410 /* Unknown1 24 NULL bytes*/
2411 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2412 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2413 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2415 /* Default Soft Quota 8 bytes */
2416 SBIG_UINT(pdata,24,quotas.softlim);
2418 /* Default Hard Quota 8 bytes */
2419 SBIG_UINT(pdata,32,quotas.hardlim);
2421 /* Quota flag 2 bytes */
2422 SSVAL(pdata,40,quotas.qflags);
2424 /* Unknown3 6 NULL bytes */
2430 #endif /* HAVE_SYS_QUOTAS */
2431 case SMB_FS_OBJECTID_INFORMATION:
2436 * Query the version and capabilities of the CIFS UNIX extensions
2440 case SMB_QUERY_CIFS_UNIX_INFO:
2441 if (!lp_unix_extensions()) {
2442 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2445 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2446 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2447 /* We have POSIX ACLs, pathname and locking capability. */
2448 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2449 CIFS_UNIX_POSIX_ACLS_CAP|
2450 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2451 CIFS_UNIX_FCNTL_LOCKS_CAP)));
2454 case SMB_QUERY_POSIX_FS_INFO:
2457 vfs_statvfs_struct svfs;
2459 if (!lp_unix_extensions()) {
2460 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2463 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2467 SIVAL(pdata,0,svfs.OptimalTransferSize);
2468 SIVAL(pdata,4,svfs.BlockSize);
2469 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2470 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2471 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2472 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2473 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2474 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2475 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2477 } else if (rc == EOPNOTSUPP) {
2478 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2479 #endif /* EOPNOTSUPP */
2481 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2482 return ERROR_DOS(ERRSRV,ERRerror);
2487 case SMB_MAC_QUERY_FS_INFO:
2489 * Thursby MAC extension... ONLY on NTFS filesystems
2490 * once we do streams then we don't need this
2492 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2494 SIVAL(pdata,84,0x100); /* Don't support mac... */
2499 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2503 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2505 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2510 /****************************************************************************
2511 Reply to a TRANS2_SETFSINFO (set filesystem info).
2512 ****************************************************************************/
2514 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2515 char **pparams, int total_params, char **ppdata, int total_data,
2516 unsigned int max_data_bytes)
2518 char *pdata = *ppdata;
2519 char *params = *pparams;
2523 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2526 if (total_params < 4) {
2527 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2529 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2532 info_level = SVAL(params,2);
2534 switch(info_level) {
2535 case SMB_SET_CIFS_UNIX_INFO:
2537 uint16 client_unix_major;
2538 uint16 client_unix_minor;
2539 uint32 client_unix_cap_low;
2540 uint32 client_unix_cap_high;
2542 if (!lp_unix_extensions()) {
2543 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2546 /* There should be 12 bytes of capabilities set. */
2547 if (total_data < 8) {
2548 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2550 client_unix_major = SVAL(pdata,0);
2551 client_unix_minor = SVAL(pdata,2);
2552 client_unix_cap_low = IVAL(pdata,4);
2553 client_unix_cap_high = IVAL(pdata,8);
2554 /* Just print these values for now. */
2555 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2556 cap_low = 0x%x, cap_high = 0x%x\n",
2557 (unsigned int)client_unix_major,
2558 (unsigned int)client_unix_minor,
2559 (unsigned int)client_unix_cap_low,
2560 (unsigned int)client_unix_cap_high ));
2562 /* Here is where we must switch to posix pathname processing... */
2563 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2564 lp_set_posix_pathnames();
2565 mangle_change_to_posix();
2568 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2569 lp_set_posix_cifsx_locktype(POSIX_LOCK);
2573 case SMB_FS_QUOTA_INFORMATION:
2575 files_struct *fsp = NULL;
2576 SMB_NTQUOTA_STRUCT quotas;
2578 ZERO_STRUCT(quotas);
2581 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2582 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2583 lp_servicename(SNUM(conn)),conn->user));
2584 return ERROR_DOS(ERRSRV,ERRaccess);
2587 /* note: normaly there're 48 bytes,
2588 * but we didn't use the last 6 bytes for now
2591 fsp = file_fsp(params,0);
2592 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2593 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2594 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2597 if (total_data < 42) {
2598 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2600 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2603 /* unknown_1 24 NULL bytes in pdata*/
2605 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2606 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2607 #ifdef LARGE_SMB_OFF_T
2608 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2609 #else /* LARGE_SMB_OFF_T */
2610 if ((IVAL(pdata,28) != 0)&&
2611 ((quotas.softlim != 0xFFFFFFFF)||
2612 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2613 /* more than 32 bits? */
2614 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2616 #endif /* LARGE_SMB_OFF_T */
2618 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2619 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2620 #ifdef LARGE_SMB_OFF_T
2621 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2622 #else /* LARGE_SMB_OFF_T */
2623 if ((IVAL(pdata,36) != 0)&&
2624 ((quotas.hardlim != 0xFFFFFFFF)||
2625 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2626 /* more than 32 bits? */
2627 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2629 #endif /* LARGE_SMB_OFF_T */
2631 /* quota_flags 2 bytes **/
2632 quotas.qflags = SVAL(pdata,40);
2634 /* unknown_2 6 NULL bytes follow*/
2636 /* now set the quotas */
2637 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2638 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2639 return ERROR_DOS(ERRSRV,ERRerror);
2645 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2647 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2652 * sending this reply works fine,
2653 * but I'm not sure it's the same
2654 * like windows do...
2657 outsize = set_message(outbuf,10,0,True);
2662 /****************************************************************************
2663 Utility function to set bad path error.
2664 ****************************************************************************/
2666 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2668 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2669 err, (int)bad_path ));
2673 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2675 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2678 return UNIXERROR(def_class,def_code);
2681 #if defined(HAVE_POSIX_ACLS)
2682 /****************************************************************************
2683 Utility function to count the number of entries in a POSIX acl.
2684 ****************************************************************************/
2686 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2688 unsigned int ace_count = 0;
2689 int entry_id = SMB_ACL_FIRST_ENTRY;
2690 SMB_ACL_ENTRY_T entry;
2692 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2694 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2695 entry_id = SMB_ACL_NEXT_ENTRY;
2702 /****************************************************************************
2703 Utility function to marshall a POSIX acl into wire format.
2704 ****************************************************************************/
2706 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2708 int entry_id = SMB_ACL_FIRST_ENTRY;
2709 SMB_ACL_ENTRY_T entry;
2711 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2712 SMB_ACL_TAG_T tagtype;
2713 SMB_ACL_PERMSET_T permset;
2714 unsigned char perms = 0;
2715 unsigned int own_grp;
2718 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2719 entry_id = SMB_ACL_NEXT_ENTRY;
2722 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2723 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2727 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2728 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2732 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2733 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2734 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2736 SCVAL(pdata,1,perms);
2739 case SMB_ACL_USER_OBJ:
2740 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2741 own_grp = (unsigned int)pst->st_uid;
2742 SIVAL(pdata,2,own_grp);
2747 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2749 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2751 own_grp = (unsigned int)*puid;
2752 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2753 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2754 SIVAL(pdata,2,own_grp);
2758 case SMB_ACL_GROUP_OBJ:
2759 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2760 own_grp = (unsigned int)pst->st_gid;
2761 SIVAL(pdata,2,own_grp);
2766 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2768 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2770 own_grp = (unsigned int)*pgid;
2771 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2772 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2773 SIVAL(pdata,2,own_grp);
2778 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2779 SIVAL(pdata,2,0xFFFFFFFF);
2780 SIVAL(pdata,6,0xFFFFFFFF);
2783 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2784 SIVAL(pdata,2,0xFFFFFFFF);
2785 SIVAL(pdata,6,0xFFFFFFFF);
2788 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2791 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2798 /****************************************************************************
2799 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2800 file name or file id).
2801 ****************************************************************************/
2803 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2804 unsigned int tran_call,
2805 char **pparams, int total_params, char **ppdata, int total_data,
2806 unsigned int max_data_bytes)
2808 char *params = *pparams;
2809 char *pdata = *ppdata;
2813 SMB_OFF_T file_size=0;
2814 SMB_BIG_UINT allocation_size=0;
2815 unsigned int data_size = 0;
2816 unsigned int param_size = 2;
2817 SMB_STRUCT_STAT sbuf;
2818 pstring fname, dos_fname;
2823 BOOL bad_path = False;
2824 BOOL delete_pending = False;
2827 files_struct *fsp = NULL;
2828 TALLOC_CTX *data_ctx = NULL;
2829 struct ea_list *ea_list = NULL;
2830 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2831 char *lock_data = NULL;
2834 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2838 if (tran_call == TRANSACT2_QFILEINFO) {
2839 if (total_params < 4) {
2840 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2843 fsp = file_fsp(params,0);
2844 info_level = SVAL(params,2);
2846 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2848 if(fsp && (fsp->fake_file_handle)) {
2850 * This is actually for the QUOTA_FAKE_FILE --metze
2853 pstrcpy(fname, fsp->fsp_name);
2854 /* We know this name is ok, it's already passed the checks. */
2856 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2858 * This is actually a QFILEINFO on a directory
2859 * handle (returned from an NT SMB). NT5.0 seems
2860 * to do this call. JRA.
2862 /* We know this name is ok, it's already passed the checks. */
2863 pstrcpy(fname, fsp->fsp_name);
2865 if (INFO_LEVEL_IS_UNIX(info_level)) {
2866 /* Always do lstat for UNIX calls. */
2867 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2868 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2869 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2871 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2872 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2873 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2876 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2879 * Original code - this is an open file.
2881 CHECK_FSP(fsp,conn);
2883 pstrcpy(fname, fsp->fsp_name);
2884 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2885 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2886 return(UNIXERROR(ERRDOS,ERRbadfid));
2888 pos = fsp->fh->position_information;
2889 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2890 access_mask = fsp->access_mask;
2893 NTSTATUS status = NT_STATUS_OK;
2896 if (total_params < 6) {
2897 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2900 info_level = SVAL(params,0);
2902 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2904 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2905 if (!NT_STATUS_IS_OK(status)) {
2906 return ERROR_NT(status);
2909 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2911 unix_convert(fname,conn,0,&bad_path,&sbuf);
2913 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2915 if (!check_name(fname,conn)) {
2916 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2917 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2920 if (INFO_LEVEL_IS_UNIX(info_level)) {
2921 /* Always do lstat for UNIX calls. */
2922 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2923 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2924 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2926 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2927 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2928 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2931 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2932 if (delete_pending) {
2933 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2937 nlink = sbuf.st_nlink;
2939 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2940 /* NTFS does not seem to count ".." */
2944 if ((nlink > 0) && delete_pending) {
2948 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2949 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2952 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2953 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2955 p = strrchr_m(fname,'/');
2961 mode = dos_mode(conn,fname,&sbuf);
2963 mode = FILE_ATTRIBUTE_NORMAL;
2965 fullpathname = fname;
2967 file_size = get_file_size(sbuf);
2969 /* Pull out any data sent here before we realloc. */
2970 switch (info_level) {
2971 case SMB_INFO_QUERY_EAS_FROM_LIST:
2973 /* Pull any EA list from the data portion. */
2976 if (total_data < 4) {
2977 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2979 ea_size = IVAL(pdata,0);
2981 if (total_data > 0 && ea_size != total_data) {
2982 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2983 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2984 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2987 if (!lp_ea_support(SNUM(conn))) {
2988 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2991 if ((data_ctx = talloc_init("ea_list")) == NULL) {
2992 return ERROR_NT(NT_STATUS_NO_MEMORY);
2995 /* Pull out the list of names. */
2996 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
2998 talloc_destroy(data_ctx);
2999 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3004 case SMB_QUERY_POSIX_LOCK:
3006 if (fsp == NULL || fsp->fh->fd == -1) {
3007 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3010 if (total_data != POSIX_LOCK_DATA_SIZE) {
3011 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3014 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3015 return ERROR_NT(NT_STATUS_NO_MEMORY);
3018 /* Copy the lock range data. */
3019 lock_data = talloc_memdup(data_ctx, pdata, total_data);
3021 talloc_destroy(data_ctx);
3022 return ERROR_NT(NT_STATUS_NO_MEMORY);
3029 *pparams = SMB_REALLOC(*pparams,2);
3030 if (*pparams == NULL) {
3031 talloc_destroy(data_ctx);
3032 return ERROR_NT(NT_STATUS_NO_MEMORY);
3036 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3037 *ppdata = SMB_REALLOC(*ppdata, data_size);
3038 if (*ppdata == NULL ) {
3039 talloc_destroy(data_ctx);
3040 return ERROR_NT(NT_STATUS_NO_MEMORY);
3044 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3046 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3049 if (fsp->pending_modtime) {
3050 /* the pending modtime overrides the current modtime */
3051 sbuf.st_mtime = fsp->pending_modtime;
3054 /* Do we have this path open ? */
3055 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3056 if (fsp1 && fsp1->pending_modtime) {
3057 /* the pending modtime overrides the current modtime */
3058 sbuf.st_mtime = fsp1->pending_modtime;
3060 if (fsp1 && fsp1->initial_allocation_size) {
3061 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3065 if (lp_dos_filetime_resolution(SNUM(conn))) {
3067 sbuf.st_atime &= ~1;
3068 sbuf.st_ctime &= ~1;
3069 sbuf.st_mtime &= ~1;
3072 /* NT expects the name to be in an exact form of the *full*
3073 filename. See the trans2 torture test */
3074 if (strequal(base_name,".")) {
3075 pstrcpy(dos_fname, "\\");
3077 pstr_sprintf(dos_fname, "\\%s", fname);
3078 string_replace(dos_fname, '/', '\\');
3081 switch (info_level) {
3082 case SMB_INFO_STANDARD:
3083 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3085 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3086 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3087 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3088 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3089 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3090 SSVAL(pdata,l1_attrFile,mode);
3093 case SMB_INFO_QUERY_EA_SIZE:
3095 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3096 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3098 srv_put_dos_date2(pdata,0,c_time);
3099 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3100 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3101 SIVAL(pdata,12,(uint32)file_size);
3102 SIVAL(pdata,16,(uint32)allocation_size);
3103 SSVAL(pdata,20,mode);
3104 SIVAL(pdata,22,ea_size);
3108 case SMB_INFO_IS_NAME_VALID:
3109 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3110 if (tran_call == TRANSACT2_QFILEINFO) {
3111 /* os/2 needs this ? really ?*/
3112 return ERROR_DOS(ERRDOS,ERRbadfunc);
3118 case SMB_INFO_QUERY_EAS_FROM_LIST:
3120 size_t total_ea_len = 0;
3121 struct ea_list *ea_file_list = NULL;
3123 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3125 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3126 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3128 if (!ea_list || (total_ea_len > data_size)) {
3129 talloc_destroy(data_ctx);
3131 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3135 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3136 talloc_destroy(data_ctx);
3140 case SMB_INFO_QUERY_ALL_EAS:
3142 /* We have data_size bytes to put EA's into. */
3143 size_t total_ea_len = 0;
3145 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3147 data_ctx = talloc_init("ea_ctx");
3149 return ERROR_NT(NT_STATUS_NO_MEMORY);
3152 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3153 if (!ea_list || (total_ea_len > data_size)) {
3154 talloc_destroy(data_ctx);
3156 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3160 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3161 talloc_destroy(data_ctx);
3165 case SMB_FILE_BASIC_INFORMATION:
3166 case SMB_QUERY_FILE_BASIC_INFO:
3168 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3169 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3170 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3172 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3176 put_long_date(pdata,c_time);
3177 put_long_date(pdata+8,sbuf.st_atime);
3178 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3179 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3180 SIVAL(pdata,32,mode);
3182 DEBUG(5,("SMB_QFBI - "));
3184 time_t create_time = c_time;
3185 DEBUG(5,("create: %s ", ctime(&create_time)));
3187 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3188 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3189 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3190 DEBUG(5,("mode: %x\n", mode));
3193 case SMB_FILE_STANDARD_INFORMATION:
3194 case SMB_QUERY_FILE_STANDARD_INFO:
3196 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3198 SOFF_T(pdata,0,allocation_size);
3199 SOFF_T(pdata,8,file_size);
3200 SIVAL(pdata,16,nlink);
3201 SCVAL(pdata,20,delete_pending?1:0);
3202 SCVAL(pdata,21,(mode&aDIR)?1:0);
3203 SSVAL(pdata,22,0); /* Padding. */
3206 case SMB_FILE_EA_INFORMATION:
3207 case SMB_QUERY_FILE_EA_INFO:
3209 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3210 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3212 SIVAL(pdata,0,ea_size);
3216 /* Get the 8.3 name - used if NT SMB was negotiated. */
3217 case SMB_QUERY_FILE_ALT_NAME_INFO:
3218 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3222 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3223 pstrcpy(short_name,base_name);
3224 /* Mangle if not already 8.3 */
3225 if(!mangle_is_8_3(short_name, True, conn->params)) {
3226 mangle_map(short_name,True,True,conn->params);
3228 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3229 data_size = 4 + len;
3234 case SMB_QUERY_FILE_NAME_INFO:
3236 this must be *exactly* right for ACLs on mapped drives to work
3238 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3239 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3240 data_size = 4 + len;
3244 case SMB_FILE_ALLOCATION_INFORMATION:
3245 case SMB_QUERY_FILE_ALLOCATION_INFO:
3246 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3248 SOFF_T(pdata,0,allocation_size);
3251 case SMB_FILE_END_OF_FILE_INFORMATION:
3252 case SMB_QUERY_FILE_END_OF_FILEINFO:
3253 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3255 SOFF_T(pdata,0,file_size);
3258 case SMB_QUERY_FILE_ALL_INFO:
3259 case SMB_FILE_ALL_INFORMATION:
3261 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3262 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3263 put_long_date(pdata,c_time);
3264 put_long_date(pdata+8,sbuf.st_atime);
3265 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3266 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3267 SIVAL(pdata,32,mode);
3268 SIVAL(pdata,36,0); /* padding. */
3270 SOFF_T(pdata,0,allocation_size);
3271 SOFF_T(pdata,8,file_size);
3272 SIVAL(pdata,16,nlink);
3273 SCVAL(pdata,20,delete_pending);
3274 SCVAL(pdata,21,(mode&aDIR)?1:0);
3277 SIVAL(pdata,0,ea_size);
3278 pdata += 4; /* EA info */
3279 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3282 data_size = PTR_DIFF(pdata,(*ppdata));
3285 case SMB_FILE_INTERNAL_INFORMATION:
3286 /* This should be an index number - looks like
3289 I think this causes us to fail the IFSKIT
3290 BasicFileInformationTest. -tpot */
3292 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3293 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3294 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3298 case SMB_FILE_ACCESS_INFORMATION:
3299 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3300 SIVAL(pdata,0,access_mask);
3304 case SMB_FILE_NAME_INFORMATION:
3305 /* Pathname with leading '\'. */
3308 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3309 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3310 SIVAL(pdata,0,byte_len);
3311 data_size = 4 + byte_len;
3315 case SMB_FILE_DISPOSITION_INFORMATION:
3316 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3318 SCVAL(pdata,0,delete_pending);
3321 case SMB_FILE_POSITION_INFORMATION:
3322 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3324 SOFF_T(pdata,0,pos);
3327 case SMB_FILE_MODE_INFORMATION:
3328 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3329 SIVAL(pdata,0,mode);
3333 case SMB_FILE_ALIGNMENT_INFORMATION:
3334 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3335 SIVAL(pdata,0,0); /* No alignment needed. */
3341 * NT4 server just returns "invalid query" to this - if we try to answer
3342 * it then NTws gets a BSOD! (tridge).
3343 * W2K seems to want this. JRA.
3345 case SMB_QUERY_FILE_STREAM_INFO:
3347 case SMB_FILE_STREAM_INFORMATION:
3348 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3352 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3353 SIVAL(pdata,0,0); /* ??? */
3354 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3355 SOFF_T(pdata,8,file_size);
3356 SIVAL(pdata,16,allocation_size);
3357 SIVAL(pdata,20,0); /* ??? */
3358 data_size = 24 + byte_len;
3362 case SMB_QUERY_COMPRESSION_INFO:
3363 case SMB_FILE_COMPRESSION_INFORMATION:
3364 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3365 SOFF_T(pdata,0,file_size);
3366 SIVAL(pdata,8,0); /* ??? */
3367 SIVAL(pdata,12,0); /* ??? */
3371 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3372 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3373 put_long_date(pdata,c_time);
3374 put_long_date(pdata+8,sbuf.st_atime);
3375 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3376 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3377 SIVAL(pdata,32,allocation_size);
3378 SOFF_T(pdata,40,file_size);
3379 SIVAL(pdata,48,mode);
3380 SIVAL(pdata,52,0); /* ??? */
3384 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3385 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3386 SIVAL(pdata,0,mode);
3392 * CIFS UNIX Extensions.
3395 case SMB_QUERY_FILE_UNIX_BASIC:
3397 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3398 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3400 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3403 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3406 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3407 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3408 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3411 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3415 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3419 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3422 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3426 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3430 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3433 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3437 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3440 data_size = PTR_DIFF(pdata,(*ppdata));
3444 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3446 for (i=0; i<100; i++)
3447 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3453 case SMB_QUERY_FILE_UNIX_LINK:
3457 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3459 if(!S_ISLNK(sbuf.st_mode))
3460 return(UNIXERROR(ERRSRV,ERRbadlink));
3462 return(UNIXERROR(ERRDOS,ERRbadlink));
3464 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3466 return(UNIXERROR(ERRDOS,ERRnoaccess));
3468 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3470 data_size = PTR_DIFF(pdata,(*ppdata));
3475 #if defined(HAVE_POSIX_ACLS)
3476 case SMB_QUERY_POSIX_ACL:
3478 SMB_ACL_T file_acl = NULL;
3479 SMB_ACL_T def_acl = NULL;
3480 uint16 num_file_acls = 0;
3481 uint16 num_def_acls = 0;
3483 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3484 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3486 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3489 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3490 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3492 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3495 if (S_ISDIR(sbuf.st_mode)) {
3496 if (fsp && fsp->is_directory) {
3497 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3499 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3501 def_acl = free_empty_sys_acl(conn, def_acl);
3504 num_file_acls = count_acl_entries(conn, file_acl);
3505 num_def_acls = count_acl_entries(conn, def_acl);
3507 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3508 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3510 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3511 SMB_POSIX_ACL_HEADER_SIZE) ));
3513 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3516 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3518 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3521 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3522 SSVAL(pdata,2,num_file_acls);
3523 SSVAL(pdata,4,num_def_acls);
3524 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3526 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3529 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3531 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3533 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3535 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3538 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3540 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3544 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3547 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3549 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3555 case SMB_QUERY_POSIX_LOCK:
3557 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3559 SMB_BIG_UINT offset;
3561 enum brl_type lock_type;
3563 if (total_data != POSIX_LOCK_DATA_SIZE) {
3564 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3567 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3568 case POSIX_LOCK_TYPE_READ:
3569 lock_type = READ_LOCK;
3571 case POSIX_LOCK_TYPE_WRITE:
3572 lock_type = WRITE_LOCK;
3574 case POSIX_LOCK_TYPE_UNLOCK:
3576 /* There's no point in asking for an unlock... */
3577 talloc_destroy(data_ctx);
3578 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3581 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3582 #if defined(HAVE_LONGLONG)
3583 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3584 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3585 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3586 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3587 #else /* HAVE_LONGLONG */
3588 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3589 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3590 #endif /* HAVE_LONGLONG */
3592 status = query_lock(fsp,
3599 if (ERROR_WAS_LOCK_DENIED(status)) {
3600 /* Here we need to report who has it locked... */
3601 data_size = POSIX_LOCK_DATA_SIZE;
3603 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3604 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3605 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3606 #if defined(HAVE_LONGLONG)
3607 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3608 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3609 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3610 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3611 #else /* HAVE_LONGLONG */
3612 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3613 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3614 #endif /* HAVE_LONGLONG */
3616 } else if (NT_STATUS_IS_OK(status)) {
3617 /* For success we just return a copy of what we sent
3618 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3619 data_size = POSIX_LOCK_DATA_SIZE;
3620 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3621 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3623 return ERROR_NT(status);
3629 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3632 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3637 /****************************************************************************
3638 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3640 ****************************************************************************/
3642 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3644 BOOL bad_path_oldname = False;
3645 BOOL bad_path_newname = False;
3646 SMB_STRUCT_STAT sbuf1, sbuf2;
3647 pstring last_component_oldname;
3648 pstring last_component_newname;
3649 NTSTATUS status = NT_STATUS_OK;
3655 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3656 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3659 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3660 if (bad_path_oldname) {
3661 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3664 /* Quick check for "." and ".." */
3665 if (last_component_oldname[0] == '.') {
3666 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3667 return NT_STATUS_OBJECT_NAME_INVALID;
3671 /* source must already exist. */
3672 if (!VALID_STAT(sbuf1)) {
3673 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3676 if (!check_name(oldname,conn)) {
3677 return NT_STATUS_ACCESS_DENIED;
3680 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3681 if (bad_path_newname) {
3682 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3685 /* Quick check for "." and ".." */
3686 if (last_component_newname[0] == '.') {
3687 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3688 return NT_STATUS_OBJECT_NAME_INVALID;
3692 /* Disallow if newname already exists. */
3693 if (VALID_STAT(sbuf2)) {
3694 return NT_STATUS_OBJECT_NAME_COLLISION;
3697 if (!check_name(newname,conn)) {
3698 return NT_STATUS_ACCESS_DENIED;
3701 /* No links from a directory. */
3702 if (S_ISDIR(sbuf1.st_mode)) {
3703 return NT_STATUS_FILE_IS_A_DIRECTORY;
3706 /* Ensure this is within the share. */
3707 if (!reduce_name(conn, oldname) != 0)
3708 return NT_STATUS_ACCESS_DENIED;
3710 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3712 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3713 status = map_nt_error_from_unix(errno);
3714 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3715 nt_errstr(status), newname, oldname));
3721 /****************************************************************************
3722 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3723 ****************************************************************************/
3725 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3726 unsigned int tran_call,
3727 char **pparams, int total_params, char **ppdata, int total_data,
3728 unsigned int max_data_bytes)
3730 char *params = *pparams;
3731 char *pdata = *ppdata;
3736 SMB_STRUCT_STAT sbuf;
3739 BOOL bad_path = False;
3740 files_struct *fsp = NULL;
3741 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3742 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3743 mode_t unixmode = 0;
3744 NTSTATUS status = NT_STATUS_OK;
3747 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3752 if (tran_call == TRANSACT2_SETFILEINFO) {
3753 if (total_params < 4) {
3754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3757 fsp = file_fsp(params,0);
3758 info_level = SVAL(params,2);
3760 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3762 * This is actually a SETFILEINFO on a directory
3763 * handle (returned from an NT SMB). NT5.0 seems
3764 * to do this call. JRA.
3766 pstrcpy(fname, fsp->fsp_name);
3767 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3768 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3769 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3771 } else if (fsp && fsp->print_file) {
3773 * Doing a DELETE_ON_CLOSE should cancel a print job.
3775 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3776 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3778 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3781 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3784 return (UNIXERROR(ERRDOS,ERRbadpath));
3787 * Original code - this is an open file.
3789 CHECK_FSP(fsp,conn);
3791 pstrcpy(fname, fsp->fsp_name);
3794 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3795 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3796 return(UNIXERROR(ERRDOS,ERRbadfid));
3801 if (total_params < 6) {
3802 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3805 info_level = SVAL(params,0);
3806 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3807 if (!NT_STATUS_IS_OK(status)) {
3808 return ERROR_NT(status);
3810 unix_convert(fname,conn,0,&bad_path,&sbuf);
3812 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3816 * For CIFS UNIX extensions the target name may not exist.
3819 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3820 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3821 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3824 if(!check_name(fname, conn)) {
3825 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3830 if (!CAN_WRITE(conn))
3831 return ERROR_DOS(ERRSRV,ERRaccess);
3833 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3834 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3837 if (VALID_STAT(sbuf))
3838 unixmode = sbuf.st_mode;
3840 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3841 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3843 /* Realloc the parameter size */
3844 *pparams = SMB_REALLOC(*pparams,2);
3845 if (*pparams == NULL) {
3846 return ERROR_NT(NT_STATUS_NO_MEMORY);
3852 if (fsp && fsp->pending_modtime) {
3853 /* the pending modtime overrides the current modtime */
3854 sbuf.st_mtime = fsp->pending_modtime;
3857 size = get_file_size(sbuf);
3858 tvs.modtime = sbuf.st_mtime;
3859 tvs.actime = sbuf.st_atime;
3860 dosmode = dos_mode(conn,fname,&sbuf);
3861 unixmode = sbuf.st_mode;
3863 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3864 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3866 switch (info_level) {
3867 case SMB_INFO_STANDARD:
3869 if (total_data < 12) {
3870 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3874 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3876 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3880 case SMB_INFO_SET_EA:
3882 struct ea_list *ea_list = NULL;
3883 TALLOC_CTX *ctx = NULL;
3885 if (total_data < 10) {
3887 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3888 length. They seem to have no effect. Bug #3212. JRA */
3890 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3891 /* We're done. We only get EA info in this call. */
3893 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3897 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3900 if (IVAL(pdata,0) > total_data) {
3901 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3902 IVAL(pdata,0), (unsigned int)total_data));
3903 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3906 ctx = talloc_init("SMB_INFO_SET_EA");
3908 return ERROR_NT(NT_STATUS_NO_MEMORY);
3910 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3912 talloc_destroy(ctx);
3913 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3915 status = set_ea(conn, fsp, fname, ea_list);
3916 talloc_destroy(ctx);
3918 if (!NT_STATUS_IS_OK(status)) {
3919 return ERROR_NT(status);
3922 /* We're done. We only get EA info in this call. */
3924 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3929 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3930 /* XXXX um, i don't think this is right.
3931 it's also not in the cifs6.txt spec.
3933 case SMB_INFO_QUERY_EAS_FROM_LIST:
3934 if (total_data < 28)
3935 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3937 tvs.actime = make_unix_date2(pdata+8);
3938 tvs.modtime = make_unix_date2(pdata+12);
3939 size = IVAL(pdata,16);
3940 dosmode = IVAL(pdata,24);
3943 /* XXXX nor this. not in cifs6.txt, either. */
3944 case SMB_INFO_QUERY_ALL_EAS:
3945 if (total_data < 28)
3946 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3948 tvs.actime = make_unix_date2(pdata+8);
3949 tvs.modtime = make_unix_date2(pdata+12);
3950 size = IVAL(pdata,16);
3951 dosmode = IVAL(pdata,24);
3955 case SMB_SET_FILE_BASIC_INFO:
3956 case SMB_FILE_BASIC_INFORMATION:
3958 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3960 time_t changed_time;
3962 if (total_data < 36) {
3963 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3966 /* Ignore create time at offset pdata. */
3969 tvs.actime = interpret_long_date(pdata+8);
3971 write_time = interpret_long_date(pdata+16);
3972 changed_time = interpret_long_date(pdata+24);
3974 tvs.modtime = MIN(write_time, changed_time);
3976 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3977 tvs.modtime = write_time;
3979 /* Prefer a defined time to an undefined one. */
3980 if (null_mtime(tvs.modtime)) {
3981 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3985 dosmode = IVAL(pdata,32);
3989 case SMB_FILE_ALLOCATION_INFORMATION:
3990 case SMB_SET_FILE_ALLOCATION_INFO:
3993 SMB_BIG_UINT allocation_size;
3995 if (total_data < 8) {
3996 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3999 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4000 #ifdef LARGE_SMB_OFF_T
4001 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4002 #else /* LARGE_SMB_OFF_T */
4003 if (IVAL(pdata,4) != 0) {
4004 /* more than 32 bits? */
4005 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4007 #endif /* LARGE_SMB_OFF_T */
4008 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4009 fname, (double)allocation_size ));
4011 if (allocation_size) {
4012 allocation_size = smb_roundup(conn, allocation_size);
4015 if(allocation_size != get_file_size(sbuf)) {
4016 SMB_STRUCT_STAT new_sbuf;
4018 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4019 fname, (double)allocation_size ));
4022 files_struct *new_fsp = NULL;
4024 status = open_file_ntcreate(conn, fname, &sbuf,
4026 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4029 FILE_ATTRIBUTE_NORMAL,
4030 FORCE_OPLOCK_BREAK_TO_NONE,
4033 if (!NT_STATUS_IS_OK(status)) {
4034 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4035 /* We have re-scheduled this call. */
4038 return(UNIXERROR(ERRDOS,ERRnoaccess));
4040 ret = vfs_allocate_file_space(new_fsp, allocation_size);
4041 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4042 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4043 new_fsp->fnum, strerror(errno)));
4046 close_file(new_fsp,NORMAL_CLOSE);
4048 ret = vfs_allocate_file_space(fsp, allocation_size);
4049 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4050 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4051 fsp->fnum, strerror(errno)));
4056 return ERROR_NT(NT_STATUS_DISK_FULL);
4058 /* Allocate can truncate size... */
4059 size = get_file_size(new_sbuf);
4065 case SMB_FILE_END_OF_FILE_INFORMATION:
4066 case SMB_SET_FILE_END_OF_FILE_INFO:
4068 if (total_data < 8) {
4069 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4072 size = IVAL(pdata,0);
4073 #ifdef LARGE_SMB_OFF_T
4074 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4075 #else /* LARGE_SMB_OFF_T */
4076 if (IVAL(pdata,4) != 0) {
4077 /* more than 32 bits? */
4078 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4080 #endif /* LARGE_SMB_OFF_T */
4081 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4085 case SMB_FILE_DISPOSITION_INFORMATION:
4086 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4088 BOOL delete_on_close;
4090 if (total_data < 1) {
4091 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4094 delete_on_close = (CVAL(pdata,0) ? True : False);
4096 /* Just ignore this set on a path. */
4097 if (tran_call != TRANSACT2_SETFILEINFO)
4101 return(UNIXERROR(ERRDOS,ERRbadfid));
4103 status = can_set_delete_on_close(fsp, delete_on_close,
4106 if (!NT_STATUS_IS_OK(status)) {
4107 return ERROR_NT(status);
4110 /* The set is across all open files on this dev/inode pair. */
4111 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4112 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4116 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4120 case SMB_FILE_POSITION_INFORMATION:
4122 SMB_BIG_UINT position_information;
4124 if (total_data < 8) {
4125 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4128 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4129 #ifdef LARGE_SMB_OFF_T
4130 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4131 #else /* LARGE_SMB_OFF_T */
4132 if (IVAL(pdata,4) != 0) {
4133 /* more than 32 bits? */
4134 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4136 #endif /* LARGE_SMB_OFF_T */
4137 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4138 fname, (double)position_information ));
4140 fsp->fh->position_information = position_information;
4143 /* We're done. We only get position info in this call. */
4145 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4149 /* From tridge Samba4 :
4150 * MODE_INFORMATION in setfileinfo (I have no
4151 * idea what "mode information" on a file is - it takes a value of 0,
4152 * 2, 4 or 6. What could it be?).
4155 case SMB_FILE_MODE_INFORMATION:
4159 if (total_data < 4) {
4160 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4162 mode = IVAL(pdata,0);
4163 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4164 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4167 /* We're done. We only get mode info in this call. */
4169 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4174 * CIFS UNIX extensions.
4177 case SMB_SET_FILE_UNIX_BASIC:
4179 uint32 raw_unixmode;
4181 if (total_data < 100) {
4182 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4185 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4186 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4187 size=IVAL(pdata,0); /* first 8 Bytes are size */
4188 #ifdef LARGE_SMB_OFF_T
4189 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4190 #else /* LARGE_SMB_OFF_T */
4191 if (IVAL(pdata,4) != 0) {
4192 /* more than 32 bits? */
4193 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4195 #endif /* LARGE_SMB_OFF_T */
4197 pdata+=24; /* ctime & st_blocks are not changed */
4198 tvs.actime = interpret_long_date(pdata); /* access_time */
4199 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4201 set_owner = (uid_t)IVAL(pdata,0);
4203 set_grp = (gid_t)IVAL(pdata,0);
4205 raw_unixmode = IVAL(pdata,28);
4206 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4207 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4209 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4210 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4211 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4213 if (!VALID_STAT(sbuf)) {
4216 * The only valid use of this is to create character and block
4217 * devices, and named pipes. This is deprecated (IMHO) and
4218 * a new info level should be used for mknod. JRA.
4221 uint32 file_type = IVAL(pdata,0);
4222 #if defined(HAVE_MAKEDEV)
4223 uint32 dev_major = IVAL(pdata,4);
4224 uint32 dev_minor = IVAL(pdata,12);
4227 uid_t myuid = geteuid();
4228 gid_t mygid = getegid();
4229 SMB_DEV_T dev = (SMB_DEV_T)0;
4231 if (tran_call == TRANSACT2_SETFILEINFO)
4232 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4234 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4235 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4238 #if defined(HAVE_MAKEDEV)
4239 dev = makedev(dev_major, dev_minor);
4242 /* We can only create as the owner/group we are. */
4244 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4245 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4246 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4247 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4249 switch (file_type) {
4250 #if defined(S_IFIFO)
4251 case UNIX_TYPE_FIFO:
4252 unixmode |= S_IFIFO;
4255 #if defined(S_IFSOCK)
4256 case UNIX_TYPE_SOCKET:
4257 unixmode |= S_IFSOCK;
4260 #if defined(S_IFCHR)
4261 case UNIX_TYPE_CHARDEV:
4262 unixmode |= S_IFCHR;
4265 #if defined(S_IFBLK)
4266 case UNIX_TYPE_BLKDEV:
4267 unixmode |= S_IFBLK;
4271 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4274 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4275 0%o for file %s\n", (double)dev, unixmode, fname ));
4277 /* Ok - do the mknod. */
4278 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4279 return(UNIXERROR(ERRDOS,ERRnoaccess));
4281 inherit_access_acl(conn, fname, unixmode);
4284 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4289 * Deal with the UNIX specific mode set.
4292 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4293 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4294 (unsigned int)unixmode, fname ));
4295 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4296 return(UNIXERROR(ERRDOS,ERRnoaccess));
4300 * Deal with the UNIX specific uid set.
4303 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4304 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4305 (unsigned int)set_owner, fname ));
4306 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4307 return(UNIXERROR(ERRDOS,ERRnoaccess));
4311 * Deal with the UNIX specific gid set.
4314 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4315 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4316 (unsigned int)set_owner, fname ));
4317 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4318 return(UNIXERROR(ERRDOS,ERRnoaccess));
4323 case SMB_SET_FILE_UNIX_LINK:
4325 pstring link_target;
4326 char *newname = fname;
4328 /* Set a symbolic link. */
4329 /* Don't allow this if follow links is false. */
4331 if (!lp_symlinks(SNUM(conn)))
4332 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4334 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4336 /* !widelinks forces the target path to be within the share. */
4337 /* This means we can interpret the target as a pathname. */
4338 if (!lp_widelinks(SNUM(conn))) {
4340 char *last_dirp = NULL;
4342 unix_format(link_target);
4343 if (*link_target == '/') {
4344 /* No absolute paths allowed. */
4345 return(UNIXERROR(ERRDOS,ERRnoaccess));
4347 pstrcpy(rel_name, newname);
4348 last_dirp = strrchr_m(rel_name, '/');
4350 last_dirp[1] = '\0';
4352 pstrcpy(rel_name, "./");
4354 pstrcat(rel_name, link_target);
4356 if (!check_name(rel_name, conn)) {
4357 return(UNIXERROR(ERRDOS,ERRnoaccess));
4361 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4362 fname, link_target ));
4364 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4365 return(UNIXERROR(ERRDOS,ERRnoaccess));
4367 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4371 case SMB_SET_FILE_UNIX_HLINK:
4374 char *newname = fname;
4376 /* Set a hard link. */
4377 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4378 if (!NT_STATUS_IS_OK(status)) {
4379 return ERROR_NT(status);
4382 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4385 status = hardlink_internals(conn, oldname, newname);
4386 if (!NT_STATUS_IS_OK(status)) {
4387 return ERROR_NT(status);
4391 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4395 case SMB_FILE_RENAME_INFORMATION:
4398 /* uint32 root_fid; */ /* Not used */
4404 if (total_data < 12) {
4405 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4408 overwrite = (CVAL(pdata,0) ? True : False);
4409 /* root_fid = IVAL(pdata,4); */
4410 len = IVAL(pdata,8);
4411 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4412 if (!NT_STATUS_IS_OK(status)) {
4413 return ERROR_NT(status);
4416 /* Check the new name has no '/' characters. */
4417 if (strchr_m(newname, '/'))
4418 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4420 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4422 /* Create the base directory. */
4423 pstrcpy(base_name, fname);
4424 p = strrchr_m(base_name, '/');
4427 /* Append the new name. */
4428 pstrcat(base_name, "/");
4429 pstrcat(base_name, newname);
4432 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4433 fsp->fnum, fsp->fsp_name, base_name ));
4434 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4436 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4438 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4440 if (!NT_STATUS_IS_OK(status)) {
4441 return ERROR_NT(status);
4443 process_pending_change_notify_queue((time_t)0);
4445 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4449 #if defined(HAVE_POSIX_ACLS)
4450 case SMB_SET_POSIX_ACL:
4452 uint16 posix_acl_version;
4453 uint16 num_file_acls;
4454 uint16 num_def_acls;
4455 BOOL valid_file_acls = True;
4456 BOOL valid_def_acls = True;
4458 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4459 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4461 posix_acl_version = SVAL(pdata,0);
4462 num_file_acls = SVAL(pdata,2);
4463 num_def_acls = SVAL(pdata,4);
4465 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4466 valid_file_acls = False;
4470 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4471 valid_def_acls = False;
4475 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4476 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4479 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4480 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4481 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4484 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4485 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4486 return(UNIXERROR(ERRDOS,ERRnoaccess));
4489 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4490 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4491 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4492 return(UNIXERROR(ERRDOS,ERRnoaccess));
4496 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4501 case SMB_SET_POSIX_LOCK:
4504 SMB_BIG_UINT offset;
4507 enum brl_type lock_type;
4510 if (fsp == NULL || fsp->fh->fd == -1) {
4511 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4514 if (total_data != POSIX_LOCK_DATA_SIZE) {
4515 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4518 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4519 case POSIX_LOCK_TYPE_READ:
4520 lock_type = READ_LOCK;
4522 case POSIX_LOCK_TYPE_WRITE:
4523 /* Return the right POSIX-mappable error code for files opened read-only. */
4524 if (!fsp->can_write) {
4525 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4527 lock_type = WRITE_LOCK;
4529 case POSIX_LOCK_TYPE_UNLOCK:
4530 lock_type = UNLOCK_LOCK;
4533 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4536 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4537 lock_blocking = False;
4538 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4539 lock_blocking = True;
4541 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4544 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4545 #if defined(HAVE_LONGLONG)
4546 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4547 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4548 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4549 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4550 #else /* HAVE_LONGLONG */
4551 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4552 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4553 #endif /* HAVE_LONGLONG */
4555 if (lock_type == UNLOCK_LOCK) {
4556 status = do_unlock(fsp,
4562 status = do_lock(fsp,
4570 if (lock_blocking && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4572 * A blocking lock was requested. Package up
4573 * this smb into a queued request and push it
4574 * onto the blocking lock queue.
4576 if(push_blocking_lock_request(inbuf, length,
4578 -1, /* infinite timeout. */
4590 if (!NT_STATUS_IS_OK(status)) {
4591 return ERROR_NT(status);
4595 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4600 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4603 /* get some defaults (no modifications) if any info is zero or -1. */
4604 if (null_mtime(tvs.actime)) {
4605 tvs.actime = sbuf.st_atime;
4608 if (null_mtime(tvs.modtime)) {
4609 tvs.modtime = sbuf.st_mtime;
4612 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4613 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4614 DEBUG(6,("size: %.0f ", (double)size));
4617 if (S_ISDIR(sbuf.st_mode))
4623 DEBUG(6,("dosmode: %x\n" , dosmode));
4625 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4626 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4627 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4628 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4631 * Only do this test if we are not explicitly
4632 * changing the size of a file.
4635 size = get_file_size(sbuf);
4639 * Try and set the times, size and mode of this file -
4640 * if they are different from the current values
4643 /* check the mode isn't different, before changing it */
4644 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4646 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4648 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4649 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4650 return(UNIXERROR(ERRDOS,ERRnoaccess));
4655 if (size != get_file_size(sbuf)) {
4659 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4660 fname, (double)size ));
4663 files_struct *new_fsp = NULL;
4665 status = open_file_ntcreate(conn, fname, &sbuf,
4667 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4670 FILE_ATTRIBUTE_NORMAL,
4671 FORCE_OPLOCK_BREAK_TO_NONE,
4674 if (!NT_STATUS_IS_OK(status)) {
4675 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4676 /* We have re-scheduled this call. */
4679 return(UNIXERROR(ERRDOS,ERRnoaccess));
4681 ret = vfs_set_filelen(new_fsp, size);
4682 close_file(new_fsp,NORMAL_CLOSE);
4684 ret = vfs_set_filelen(fsp, size);
4688 return (UNIXERROR(ERRHRD,ERRdiskfull));
4693 * Finally the times.
4695 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4698 * This was a setfileinfo on an open file.
4699 * NT does this a lot. We also need to
4700 * set the time here, as it can be read by
4701 * FindFirst/FindNext and with the patch for bug #2045
4702 * in smbd/fileio.c it ensures that this timestamp is
4703 * kept sticky even after a write. We save the request
4704 * away and will set it on file close and after a write. JRA.
4707 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4708 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4709 fsp_set_pending_modtime(fsp, tvs.modtime);
4713 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4715 if(file_utime(conn, fname, &tvs)!=0) {
4716 return(UNIXERROR(ERRDOS,ERRnoaccess));
4721 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4726 /****************************************************************************
4727 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4728 ****************************************************************************/
4730 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4731 char **pparams, int total_params, char **ppdata, int total_data,
4732 unsigned int max_data_bytes)
4734 char *params = *pparams;
4735 char *pdata = *ppdata;
4738 SMB_STRUCT_STAT sbuf;
4739 BOOL bad_path = False;
4740 NTSTATUS status = NT_STATUS_OK;
4741 TALLOC_CTX *ctx = NULL;
4742 struct ea_list *ea_list = NULL;
4744 if (!CAN_WRITE(conn))
4745 return ERROR_DOS(ERRSRV,ERRaccess);
4747 if (total_params < 4) {
4748 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4751 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
4752 if (!NT_STATUS_IS_OK(status)) {
4753 return ERROR_NT(status);
4756 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4758 unix_convert(directory,conn,0,&bad_path,&sbuf);
4760 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4763 /* Any data in this call is an EA list. */
4764 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4765 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4769 * OS/2 workplace shell seems to send SET_EA requests of "null"
4770 * length (4 bytes containing IVAL 4).
4771 * They seem to have no effect. Bug #3212. JRA.
4774 if (total_data != 4) {
4775 if (total_data < 10) {
4776 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4779 if (IVAL(pdata,0) > total_data) {
4780 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4781 IVAL(pdata,0), (unsigned int)total_data));
4782 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4785 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4787 return ERROR_NT(NT_STATUS_NO_MEMORY);
4789 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4791 talloc_destroy(ctx);
4792 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4794 } else if (IVAL(pdata,0) != 4) {
4795 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4798 if (check_name(directory,conn)) {
4799 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4803 talloc_destroy(ctx);
4804 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4805 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4808 /* Try and set any given EA. */
4810 status = set_ea(conn, NULL, directory, ea_list);
4811 talloc_destroy(ctx);
4812 if (!NT_STATUS_IS_OK(status)) {
4813 return ERROR_NT(status);
4817 /* Realloc the parameter and data sizes */
4818 *pparams = SMB_REALLOC(*pparams,2);
4819 if(*pparams == NULL) {
4820 return ERROR_NT(NT_STATUS_NO_MEMORY);
4826 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4831 /****************************************************************************
4832 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4833 We don't actually do this - we just send a null response.
4834 ****************************************************************************/
4836 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4837 char **pparams, int total_params, char **ppdata, int total_data,
4838 unsigned int max_data_bytes)
4840 static uint16 fnf_handle = 257;
4841 char *params = *pparams;
4844 if (total_params < 6) {
4845 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4848 info_level = SVAL(params,4);
4849 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4851 switch (info_level) {
4856 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4859 /* Realloc the parameter and data sizes */
4860 *pparams = SMB_REALLOC(*pparams,6);
4861 if (*pparams == NULL) {
4862 return ERROR_NT(NT_STATUS_NO_MEMORY);
4866 SSVAL(params,0,fnf_handle);
4867 SSVAL(params,2,0); /* No changes */
4868 SSVAL(params,4,0); /* No EA errors */
4875 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4880 /****************************************************************************
4881 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4882 changes). Currently this does nothing.
4883 ****************************************************************************/
4885 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4886 char **pparams, int total_params, char **ppdata, int total_data,
4887 unsigned int max_data_bytes)
4889 char *params = *pparams;
4891 DEBUG(3,("call_trans2findnotifynext\n"));
4893 /* Realloc the parameter and data sizes */
4894 *pparams = SMB_REALLOC(*pparams,4);
4895 if (*pparams == NULL) {
4896 return ERROR_NT(NT_STATUS_NO_MEMORY);
4900 SSVAL(params,0,0); /* No changes */
4901 SSVAL(params,2,0); /* No EA errors */
4903 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4908 /****************************************************************************
4909 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4910 ****************************************************************************/
4912 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4913 char **pparams, int total_params, char **ppdata, int total_data,
4914 unsigned int max_data_bytes)
4916 char *params = *pparams;
4919 int max_referral_level;
4921 DEBUG(10,("call_trans2getdfsreferral\n"));
4923 if (total_params < 2) {
4924 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4927 max_referral_level = SVAL(params,0);
4929 if(!lp_host_msdfs())
4930 return ERROR_DOS(ERRDOS,ERRbadfunc);
4932 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4933 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4934 return UNIXERROR(ERRDOS,ERRbadfile);
4936 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4937 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4942 #define LMCAT_SPL 0x53
4943 #define LMFUNC_GETJOBID 0x60
4945 /****************************************************************************
4946 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4947 ****************************************************************************/
4949 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4950 char **pparams, int total_params, char **ppdata, int total_data,
4951 unsigned int max_data_bytes)
4953 char *pdata = *ppdata;
4954 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4956 /* check for an invalid fid before proceeding */
4959 return(ERROR_DOS(ERRDOS,ERRbadfid));
4961 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4962 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4963 *ppdata = SMB_REALLOC(*ppdata, 32);
4964 if (*ppdata == NULL) {
4965 return ERROR_NT(NT_STATUS_NO_MEMORY);
4969 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4970 CAN ACCEPT THIS IN UNICODE. JRA. */
4972 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4973 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4974 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4975 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4978 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4979 return ERROR_DOS(ERRSRV,ERRerror);
4983 /****************************************************************************
4984 Reply to a SMBfindclose (stop trans2 directory search).
4985 ****************************************************************************/
4987 int reply_findclose(connection_struct *conn,
4988 char *inbuf,char *outbuf,int length,int bufsize)
4991 int dptr_num=SVALS(inbuf,smb_vwv0);
4992 START_PROFILE(SMBfindclose);
4994 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4996 dptr_close(&dptr_num);
4998 outsize = set_message(outbuf,0,0,False);
5000 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5002 END_PROFILE(SMBfindclose);
5006 /****************************************************************************
5007 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5008 ****************************************************************************/
5010 int reply_findnclose(connection_struct *conn,
5011 char *inbuf,char *outbuf,int length,int bufsize)
5015 START_PROFILE(SMBfindnclose);
5017 dptr_num = SVAL(inbuf,smb_vwv0);
5019 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5021 /* We never give out valid handles for a
5022 findnotifyfirst - so any dptr_num is ok here.
5025 outsize = set_message(outbuf,0,0,False);
5027 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5029 END_PROFILE(SMBfindnclose);
5033 int handle_trans2(connection_struct *conn,
5034 struct trans_state *state,
5035 char *inbuf, char *outbuf, int size, int bufsize)
5039 if (Protocol >= PROTOCOL_NT1) {
5040 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5043 /* Now we must call the relevant TRANS2 function */
5044 switch(state->call) {
5045 case TRANSACT2_OPEN:
5047 START_PROFILE_NESTED(Trans2_open);
5048 outsize = call_trans2open(
5049 conn, inbuf, outbuf, bufsize,
5050 &state->param, state->total_param,
5051 &state->data, state->total_data,
5052 state->max_data_return);
5053 END_PROFILE_NESTED(Trans2_open);
5057 case TRANSACT2_FINDFIRST:
5059 START_PROFILE_NESTED(Trans2_findfirst);
5060 outsize = call_trans2findfirst(
5061 conn, inbuf, outbuf, bufsize,
5062 &state->param, state->total_param,
5063 &state->data, state->total_data,
5064 state->max_data_return);
5065 END_PROFILE_NESTED(Trans2_findfirst);
5069 case TRANSACT2_FINDNEXT:
5071 START_PROFILE_NESTED(Trans2_findnext);
5072 outsize = call_trans2findnext(
5073 conn, inbuf, outbuf, size, bufsize,
5074 &state->param, state->total_param,
5075 &state->data, state->total_data,
5076 state->max_data_return);
5077 END_PROFILE_NESTED(Trans2_findnext);
5081 case TRANSACT2_QFSINFO:
5083 START_PROFILE_NESTED(Trans2_qfsinfo);
5084 outsize = call_trans2qfsinfo(
5085 conn, inbuf, outbuf, size, bufsize,
5086 &state->param, state->total_param,
5087 &state->data, state->total_data,
5088 state->max_data_return);
5089 END_PROFILE_NESTED(Trans2_qfsinfo);
5093 case TRANSACT2_SETFSINFO:
5095 START_PROFILE_NESTED(Trans2_setfsinfo);
5096 outsize = call_trans2setfsinfo(
5097 conn, inbuf, outbuf, size, bufsize,
5098 &state->param, state->total_param,
5099 &state->data, state->total_data,
5100 state->max_data_return);
5101 END_PROFILE_NESTED(Trans2_setfsinfo);
5105 case TRANSACT2_QPATHINFO:
5106 case TRANSACT2_QFILEINFO:
5108 START_PROFILE_NESTED(Trans2_qpathinfo);
5109 outsize = call_trans2qfilepathinfo(
5110 conn, inbuf, outbuf, size, bufsize, state->call,
5111 &state->param, state->total_param,
5112 &state->data, state->total_data,
5113 state->max_data_return);
5114 END_PROFILE_NESTED(Trans2_qpathinfo);
5118 case TRANSACT2_SETPATHINFO:
5119 case TRANSACT2_SETFILEINFO:
5121 START_PROFILE_NESTED(Trans2_setpathinfo);
5122 outsize = call_trans2setfilepathinfo(
5123 conn, inbuf, outbuf, size, bufsize, state->call,
5124 &state->param, state->total_param,
5125 &state->data, state->total_data,
5126 state->max_data_return);
5127 END_PROFILE_NESTED(Trans2_setpathinfo);
5131 case TRANSACT2_FINDNOTIFYFIRST:
5133 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5134 outsize = call_trans2findnotifyfirst(
5135 conn, inbuf, outbuf, size, bufsize,
5136 &state->param, state->total_param,
5137 &state->data, state->total_data,
5138 state->max_data_return);
5139 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5143 case TRANSACT2_FINDNOTIFYNEXT:
5145 START_PROFILE_NESTED(Trans2_findnotifynext);
5146 outsize = call_trans2findnotifynext(
5147 conn, inbuf, outbuf, size, bufsize,
5148 &state->param, state->total_param,
5149 &state->data, state->total_data,
5150 state->max_data_return);
5151 END_PROFILE_NESTED(Trans2_findnotifynext);
5155 case TRANSACT2_MKDIR:
5157 START_PROFILE_NESTED(Trans2_mkdir);
5158 outsize = call_trans2mkdir(
5159 conn, inbuf, outbuf, size, bufsize,
5160 &state->param, state->total_param,
5161 &state->data, state->total_data,
5162 state->max_data_return);
5163 END_PROFILE_NESTED(Trans2_mkdir);
5167 case TRANSACT2_GET_DFS_REFERRAL:
5169 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5170 outsize = call_trans2getdfsreferral(
5171 conn, inbuf, outbuf, size, bufsize,
5172 &state->param, state->total_param,
5173 &state->data, state->total_data,
5174 state->max_data_return);
5175 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5179 case TRANSACT2_IOCTL:
5181 START_PROFILE_NESTED(Trans2_ioctl);
5182 outsize = call_trans2ioctl(
5183 conn, inbuf, outbuf, size, bufsize,
5184 &state->param, state->total_param,
5185 &state->data, state->total_data,
5186 state->max_data_return);
5187 END_PROFILE_NESTED(Trans2_ioctl);
5192 /* Error in request */
5193 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5194 outsize = ERROR_DOS(ERRSRV,ERRerror);
5200 /****************************************************************************
5201 Reply to a SMBtrans2.
5202 ****************************************************************************/
5204 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5205 int size, int bufsize)
5208 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5209 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5210 unsigned int psoff = SVAL(inbuf, smb_psoff);
5211 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5212 unsigned int tran_call = SVAL(inbuf, smb_setup0);
5213 struct trans_state *state;
5216 START_PROFILE(SMBtrans2);
5218 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5219 if (!NT_STATUS_IS_OK(result)) {
5220 DEBUG(2, ("Got invalid trans2 request: %s\n",
5221 nt_errstr(result)));
5222 END_PROFILE(SMBtrans2);
5223 return ERROR_NT(result);
5226 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5227 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5228 END_PROFILE(SMBtrans2);
5229 return ERROR_DOS(ERRSRV,ERRaccess);
5232 if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
5233 DEBUG(0, ("talloc failed\n"));
5234 END_PROFILE(SMBtrans2);
5235 return ERROR_NT(NT_STATUS_NO_MEMORY);
5238 state->cmd = SMBtrans2;
5240 state->mid = SVAL(inbuf, smb_mid);
5241 state->vuid = SVAL(inbuf, smb_uid);
5242 state->setup_count = SVAL(inbuf, smb_suwcnt);
5243 state->total_param = SVAL(inbuf, smb_tpscnt);
5244 state->param = NULL;
5245 state->total_data = SVAL(inbuf, smb_tdscnt);
5247 state->max_param_return = SVAL(inbuf, smb_mprcnt);
5248 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
5249 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5250 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5251 state->one_way = BITSETW(inbuf+smb_vwv5,1);
5253 state->call = tran_call;
5255 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5256 is so as a sanity check */
5257 if (state->setup_count != 1) {
5259 * Need to have rc=0 for ioctl to get job id for OS/2.
5260 * Network printing will fail if function is not successful.
5261 * Similar function in reply.c will be used if protocol
5262 * is LANMAN1.0 instead of LM1.2X002.
5263 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5264 * outbuf doesn't have to be set(only job id is used).
5266 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5267 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5268 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5269 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5271 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5272 DEBUG(2,("Transaction is %d\n",tran_call));
5274 END_PROFILE(SMBtrans2);
5275 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5279 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5282 if (state->total_data) {
5283 /* Can't use talloc here, the core routines do realloc on the
5284 * params and data. */
5285 state->data = SMB_MALLOC(state->total_data);
5286 if (state->data == NULL) {
5287 DEBUG(0,("reply_trans2: data malloc fail for %u "
5288 "bytes !\n", (unsigned int)state->total_data));
5290 END_PROFILE(SMBtrans2);
5291 return(ERROR_DOS(ERRDOS,ERRnomem));
5293 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5295 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5296 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5299 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5302 if (state->total_param) {
5303 /* Can't use talloc here, the core routines do realloc on the
5304 * params and data. */
5305 state->param = SMB_MALLOC(state->total_param);
5306 if (state->param == NULL) {
5307 DEBUG(0,("reply_trans: param malloc fail for %u "
5308 "bytes !\n", (unsigned int)state->total_param));
5309 SAFE_FREE(state->data);
5311 END_PROFILE(SMBtrans2);
5312 return(ERROR_DOS(ERRDOS,ERRnomem));
5314 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5316 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5317 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5320 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5323 state->received_data = dscnt;
5324 state->received_param = pscnt;
5326 if ((state->received_param == state->total_param) &&
5327 (state->received_data == state->total_data)) {
5329 outsize = handle_trans2(conn, state, inbuf, outbuf,
5331 SAFE_FREE(state->data);
5332 SAFE_FREE(state->param);
5334 END_PROFILE(SMBtrans2);
5338 DLIST_ADD(conn->pending_trans, state);
5340 /* We need to send an interim response then receive the rest
5341 of the parameter/data bytes */
5342 outsize = set_message(outbuf,0,0,False);
5344 END_PROFILE(SMBtrans2);
5349 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5350 SAFE_FREE(state->data);
5351 SAFE_FREE(state->param);
5353 END_PROFILE(SMBtrans2);
5354 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5358 /****************************************************************************
5359 Reply to a SMBtranss2
5360 ****************************************************************************/
5362 int reply_transs2(connection_struct *conn,
5363 char *inbuf,char *outbuf,int size,int bufsize)
5366 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5367 struct trans_state *state;
5369 START_PROFILE(SMBtranss2);
5373 for (state = conn->pending_trans; state != NULL;
5374 state = state->next) {
5375 if (state->mid == SVAL(inbuf,smb_mid)) {
5380 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5381 END_PROFILE(SMBtranss2);
5382 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5385 /* Revise state->total_param and state->total_data in case they have
5386 changed downwards */
5388 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5389 state->total_param = SVAL(inbuf, smb_tpscnt);
5390 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5391 state->total_data = SVAL(inbuf, smb_tdscnt);
5393 pcnt = SVAL(inbuf, smb_spscnt);
5394 poff = SVAL(inbuf, smb_spsoff);
5395 pdisp = SVAL(inbuf, smb_spsdisp);
5397 dcnt = SVAL(inbuf, smb_sdscnt);
5398 doff = SVAL(inbuf, smb_sdsoff);
5399 ddisp = SVAL(inbuf, smb_sdsdisp);
5401 state->received_param += pcnt;
5402 state->received_data += dcnt;
5404 if ((state->received_data > state->total_data) ||
5405 (state->received_param > state->total_param))
5409 if (pdisp+pcnt > state->total_param)
5411 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5413 if (pdisp > state->total_param)
5415 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5416 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5418 if (state->param + pdisp < state->param)
5421 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5426 if (ddisp+dcnt > state->total_data)
5428 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5430 if (ddisp > state->total_data)
5432 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5433 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5435 if (state->data + ddisp < state->data)
5438 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5442 if ((state->received_param < state->total_param) ||
5443 (state->received_data < state->total_data)) {
5444 END_PROFILE(SMBtranss2);
5448 /* construct_reply_common has done us the favor to pre-fill the
5449 * command field with SMBtranss2 which is wrong :-)
5451 SCVAL(outbuf,smb_com,SMBtrans2);
5453 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5455 DLIST_REMOVE(conn->pending_trans, state);
5456 SAFE_FREE(state->data);
5457 SAFE_FREE(state->param);
5461 END_PROFILE(SMBtranss2);
5462 return(ERROR_DOS(ERRSRV,ERRnosupport));
5465 END_PROFILE(SMBtranss2);
5470 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5471 DLIST_REMOVE(conn->pending_trans, state);
5472 SAFE_FREE(state->data);
5473 SAFE_FREE(state->param);
5475 END_PROFILE(SMBtranss2);
5476 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);