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_ARRAY(mem_ctx, char, 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 = (char *)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, char *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 = (char *)SMB_REALLOC(
1755 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1756 if(*ppdata == NULL ) {
1757 talloc_destroy(ea_ctx);
1758 return ERROR_NT(NT_STATUS_NO_MEMORY);
1762 /* Realloc the params space */
1763 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1764 if (*pparams == NULL) {
1765 talloc_destroy(ea_ctx);
1766 return ERROR_NT(NT_STATUS_NO_MEMORY);
1770 /* Save the wildcard match and attribs we are using on this directory -
1771 needed as lanman2 assumes these are being saved between calls */
1773 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1775 talloc_destroy(ea_ctx);
1776 return(UNIXERROR(ERRDOS,ERRbadfile));
1779 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1781 /* We don't need to check for VOL here as this is returned by
1782 a different TRANS2 call. */
1784 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1785 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1786 dont_descend = True;
1789 space_remaining = max_data_bytes;
1790 out_of_space = False;
1792 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1793 BOOL got_exact_match = False;
1795 /* this is a heuristic to avoid seeking the dirptr except when
1796 absolutely necessary. It allows for a filename of about 40 chars */
1797 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1798 out_of_space = True;
1801 finished = !get_lanman2_dir_entry(conn,
1803 mask,dirtype,info_level,
1804 requires_resume_key,dont_descend,
1805 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1806 &last_entry_off, ea_list, ea_ctx);
1809 if (finished && out_of_space)
1812 if (!finished && !out_of_space)
1816 * As an optimisation if we know we aren't looking
1817 * for a wildcard name (ie. the name matches the wildcard exactly)
1818 * then we can finish on any (first) match.
1819 * This speeds up large directory searches. JRA.
1825 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1828 talloc_destroy(ea_ctx);
1830 /* Check if we can close the dirptr */
1831 if(close_after_first || (finished && close_if_end)) {
1832 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1833 dptr_close(&dptr_num);
1837 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1838 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1839 * the protocol level is less than NT1. Tested with smbclient. JRA.
1840 * This should fix the OS/2 client bug #2335.
1843 if(numentries == 0) {
1844 dptr_close(&dptr_num);
1845 if (Protocol < PROTOCOL_NT1) {
1846 return ERROR_DOS(ERRDOS,ERRnofiles);
1848 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1852 /* At this point pdata points to numentries directory entries. */
1854 /* Set up the return parameter block */
1855 SSVAL(params,0,dptr_num);
1856 SSVAL(params,2,numentries);
1857 SSVAL(params,4,finished);
1858 SSVAL(params,6,0); /* Never an EA error */
1859 SSVAL(params,8,last_entry_off);
1861 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1863 if ((! *directory) && dptr_path(dptr_num))
1864 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1866 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1867 smb_fn_name(CVAL(inbuf,smb_com)),
1868 mask, directory, dirtype, numentries ) );
1871 * Force a name mangle here to ensure that the
1872 * mask as an 8.3 name is top of the mangled cache.
1873 * The reasons for this are subtle. Don't remove
1874 * this code unless you know what you are doing
1875 * (see PR#13758). JRA.
1878 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1879 mangle_map(mask, True, True, conn->params);
1884 /****************************************************************************
1885 Reply to a TRANS2_FINDNEXT.
1886 ****************************************************************************/
1888 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1889 char **pparams, int total_params, char **ppdata, int total_data,
1890 unsigned int max_data_bytes)
1892 /* We must be careful here that we don't return more than the
1893 allowed number of data bytes. If this means returning fewer than
1894 maxentries then so be it. We assume that the redirector has
1895 enough room for the fixed number of parameter bytes it has
1897 char *params = *pparams;
1898 char *pdata = *ppdata;
1899 int dptr_num = SVAL(params,0);
1900 int maxentries = SVAL(params,2);
1901 uint16 info_level = SVAL(params,4);
1902 uint32 resume_key = IVAL(params,6);
1903 uint16 findnext_flags = SVAL(params,10);
1904 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1905 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1906 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1907 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1908 BOOL mask_contains_wcard = False;
1909 pstring resume_name;
1915 int i, last_entry_off=0;
1916 BOOL finished = False;
1917 BOOL dont_descend = False;
1918 BOOL out_of_space = False;
1919 int space_remaining;
1920 TALLOC_CTX *ea_ctx = NULL;
1921 struct ea_list *ea_list = NULL;
1922 NTSTATUS ntstatus = NT_STATUS_OK;
1924 if (total_params < 12) {
1925 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1928 *mask = *directory = *resume_name = 0;
1930 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1931 if (!NT_STATUS_IS_OK(ntstatus)) {
1932 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1933 complain (it thinks we're asking for the directory above the shared
1934 path or an invalid name). Catch this as the resume name is only compared, never used in
1935 a file access. JRA. */
1936 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1937 pstrcpy(resume_name, "..");
1938 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1939 pstrcpy(resume_name, ".");
1941 return ERROR_NT(ntstatus);
1945 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1946 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1947 resume_key = %d resume name = %s continue=%d level = %d\n",
1948 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1949 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1952 /* W2K3 seems to treat zero as 1. */
1956 switch (info_level) {
1957 case SMB_FIND_INFO_STANDARD:
1958 case SMB_FIND_EA_SIZE:
1959 case SMB_FIND_EA_LIST:
1960 case SMB_FIND_FILE_DIRECTORY_INFO:
1961 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1962 case SMB_FIND_FILE_NAMES_INFO:
1963 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1964 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1965 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1967 case SMB_FIND_FILE_UNIX:
1968 if (!lp_unix_extensions()) {
1969 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1973 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1976 if (info_level == SMB_FIND_EA_LIST) {
1979 if (total_data < 4) {
1980 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1983 ea_size = IVAL(pdata,0);
1984 if (ea_size != total_data) {
1985 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1986 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1987 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1990 if (!lp_ea_support(SNUM(conn))) {
1991 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1994 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1995 return ERROR_NT(NT_STATUS_NO_MEMORY);
1998 /* Pull out the list of names. */
1999 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2001 talloc_destroy(ea_ctx);
2002 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2006 *ppdata = (char *)SMB_REALLOC(
2007 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2008 if(*ppdata == NULL) {
2009 talloc_destroy(ea_ctx);
2010 return ERROR_NT(NT_STATUS_NO_MEMORY);
2015 /* Realloc the params space */
2016 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2017 if(*pparams == NULL ) {
2018 talloc_destroy(ea_ctx);
2019 return ERROR_NT(NT_STATUS_NO_MEMORY);
2024 /* Check that the dptr is valid */
2025 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2026 talloc_destroy(ea_ctx);
2027 return ERROR_DOS(ERRDOS,ERRnofiles);
2030 string_set(&conn->dirpath,dptr_path(dptr_num));
2032 /* Get the wildcard mask from the dptr */
2033 if((p = dptr_wcard(dptr_num))== NULL) {
2034 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2035 talloc_destroy(ea_ctx);
2036 return ERROR_DOS(ERRDOS,ERRnofiles);
2040 pstrcpy(directory,conn->dirpath);
2042 /* Get the attr mask from the dptr */
2043 dirtype = dptr_attr(dptr_num);
2045 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2046 dptr_num, mask, dirtype,
2048 dptr_TellDir(conn->dirptr)));
2050 /* We don't need to check for VOL here as this is returned by
2051 a different TRANS2 call. */
2053 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2054 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2055 dont_descend = True;
2058 space_remaining = max_data_bytes;
2059 out_of_space = False;
2062 * Seek to the correct position. We no longer use the resume key but
2063 * depend on the last file name instead.
2066 if(*resume_name && !continue_bit) {
2069 long current_pos = 0;
2071 * Remember, mangle_map is called by
2072 * get_lanman2_dir_entry(), so the resume name
2073 * could be mangled. Ensure we check the unmangled name.
2076 if (mangle_is_mangled(resume_name, conn->params)) {
2077 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2082 * Fix for NT redirector problem triggered by resume key indexes
2083 * changing between directory scans. We now return a resume key of 0
2084 * and instead look for the filename to continue from (also given
2085 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2086 * findfirst/findnext (as is usual) then the directory pointer
2087 * should already be at the correct place.
2090 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2091 } /* end if resume_name && !continue_bit */
2093 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2094 BOOL got_exact_match = False;
2096 /* this is a heuristic to avoid seeking the dirptr except when
2097 absolutely necessary. It allows for a filename of about 40 chars */
2098 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2099 out_of_space = True;
2102 finished = !get_lanman2_dir_entry(conn,
2104 mask,dirtype,info_level,
2105 requires_resume_key,dont_descend,
2106 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2107 &last_entry_off, ea_list, ea_ctx);
2110 if (finished && out_of_space)
2113 if (!finished && !out_of_space)
2117 * As an optimisation if we know we aren't looking
2118 * for a wildcard name (ie. the name matches the wildcard exactly)
2119 * then we can finish on any (first) match.
2120 * This speeds up large directory searches. JRA.
2126 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2129 talloc_destroy(ea_ctx);
2131 /* Check if we can close the dirptr */
2132 if(close_after_request || (finished && close_if_end)) {
2133 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2134 dptr_close(&dptr_num); /* This frees up the saved mask */
2137 /* Set up the return parameter block */
2138 SSVAL(params,0,numentries);
2139 SSVAL(params,2,finished);
2140 SSVAL(params,4,0); /* Never an EA error */
2141 SSVAL(params,6,last_entry_off);
2143 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2145 if ((! *directory) && dptr_path(dptr_num))
2146 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2148 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2149 smb_fn_name(CVAL(inbuf,smb_com)),
2150 mask, directory, dirtype, numentries ) );
2155 /****************************************************************************
2156 Reply to a TRANS2_QFSINFO (query filesystem info).
2157 ****************************************************************************/
2159 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2160 char **pparams, int total_params, char **ppdata, int total_data,
2161 unsigned int max_data_bytes)
2163 char *pdata = *ppdata;
2164 char *params = *pparams;
2165 uint16 info_level = SVAL(params,0);
2168 char *vname = volume_label(SNUM(conn));
2169 int snum = SNUM(conn);
2170 char *fstype = lp_fstype(SNUM(conn));
2173 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2175 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2176 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2177 return ERROR_DOS(ERRSRV,ERRinvdevice);
2180 *ppdata = (char *)SMB_REALLOC(
2181 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2182 if (*ppdata == NULL ) {
2183 return ERROR_NT(NT_STATUS_NO_MEMORY);
2187 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2189 switch (info_level) {
2190 case SMB_INFO_ALLOCATION:
2192 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2194 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2195 return(UNIXERROR(ERRHRD,ERRgeneral));
2198 block_size = lp_block_size(snum);
2199 if (bsize < block_size) {
2200 SMB_BIG_UINT factor = block_size/bsize;
2205 if (bsize > block_size) {
2206 SMB_BIG_UINT factor = bsize/block_size;
2211 bytes_per_sector = 512;
2212 sectors_per_unit = bsize/bytes_per_sector;
2214 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2215 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2216 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2218 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2219 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2220 SIVAL(pdata,l1_cUnit,dsize);
2221 SIVAL(pdata,l1_cUnitAvail,dfree);
2222 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2226 case SMB_INFO_VOLUME:
2227 /* Return volume name */
2229 * Add volume serial number - hash of a combination of
2230 * the called hostname and the service name.
2232 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2234 * Win2k3 and previous mess this up by sending a name length
2235 * one byte short. I believe only older clients (OS/2 Win9x) use
2236 * this call so try fixing this by adding a terminating null to
2237 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2239 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2240 SCVAL(pdata,l2_vol_cch,len);
2241 data_len = l2_vol_szVolLabel + len;
2242 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2243 (unsigned)st.st_ctime, len, vname));
2246 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2247 case SMB_FS_ATTRIBUTE_INFORMATION:
2250 #if defined(HAVE_SYS_QUOTAS)
2251 quota_flag = FILE_VOLUME_QUOTAS;
2254 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2255 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2256 quota_flag); /* FS ATTRIBUTES */
2258 SIVAL(pdata,4,255); /* Max filename component length */
2259 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2260 and will think we can't do long filenames */
2261 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2263 data_len = 12 + len;
2266 case SMB_QUERY_FS_LABEL_INFO:
2267 case SMB_FS_LABEL_INFORMATION:
2268 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2273 case SMB_QUERY_FS_VOLUME_INFO:
2274 case SMB_FS_VOLUME_INFORMATION:
2277 * Add volume serial number - hash of a combination of
2278 * the called hostname and the service name.
2280 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2281 (str_checksum(get_local_machine_name())<<16));
2283 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2284 SIVAL(pdata,12,len);
2286 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2287 (int)strlen(vname),vname, lp_servicename(snum)));
2290 case SMB_QUERY_FS_SIZE_INFO:
2291 case SMB_FS_SIZE_INFORMATION:
2293 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2295 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2296 return(UNIXERROR(ERRHRD,ERRgeneral));
2298 block_size = lp_block_size(snum);
2299 if (bsize < block_size) {
2300 SMB_BIG_UINT factor = block_size/bsize;
2305 if (bsize > block_size) {
2306 SMB_BIG_UINT factor = bsize/block_size;
2311 bytes_per_sector = 512;
2312 sectors_per_unit = bsize/bytes_per_sector;
2313 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2314 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2315 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2316 SBIG_UINT(pdata,0,dsize);
2317 SBIG_UINT(pdata,8,dfree);
2318 SIVAL(pdata,16,sectors_per_unit);
2319 SIVAL(pdata,20,bytes_per_sector);
2323 case SMB_FS_FULL_SIZE_INFORMATION:
2325 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2327 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2328 return(UNIXERROR(ERRHRD,ERRgeneral));
2330 block_size = lp_block_size(snum);
2331 if (bsize < block_size) {
2332 SMB_BIG_UINT factor = block_size/bsize;
2337 if (bsize > block_size) {
2338 SMB_BIG_UINT factor = bsize/block_size;
2343 bytes_per_sector = 512;
2344 sectors_per_unit = bsize/bytes_per_sector;
2345 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2346 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2347 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2348 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2349 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2350 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2351 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2352 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2356 case SMB_QUERY_FS_DEVICE_INFO:
2357 case SMB_FS_DEVICE_INFORMATION:
2359 SIVAL(pdata,0,0); /* dev type */
2360 SIVAL(pdata,4,0); /* characteristics */
2363 #ifdef HAVE_SYS_QUOTAS
2364 case SMB_FS_QUOTA_INFORMATION:
2366 * what we have to send --metze:
2368 * Unknown1: 24 NULL bytes
2369 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2370 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2371 * Quota Flags: 2 byte :
2372 * Unknown3: 6 NULL bytes
2376 * details for Quota Flags:
2378 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2379 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2380 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2381 * 0x0001 Enable Quotas: enable quota for this fs
2385 /* we need to fake up a fsp here,
2386 * because its not send in this call
2389 SMB_NTQUOTA_STRUCT quotas;
2392 ZERO_STRUCT(quotas);
2398 if (current_user.ut.uid != 0) {
2399 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2400 lp_servicename(SNUM(conn)),conn->user));
2401 return ERROR_DOS(ERRDOS,ERRnoaccess);
2404 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2405 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2406 return ERROR_DOS(ERRSRV,ERRerror);
2411 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2413 /* Unknown1 24 NULL bytes*/
2414 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2415 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2416 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2418 /* Default Soft Quota 8 bytes */
2419 SBIG_UINT(pdata,24,quotas.softlim);
2421 /* Default Hard Quota 8 bytes */
2422 SBIG_UINT(pdata,32,quotas.hardlim);
2424 /* Quota flag 2 bytes */
2425 SSVAL(pdata,40,quotas.qflags);
2427 /* Unknown3 6 NULL bytes */
2433 #endif /* HAVE_SYS_QUOTAS */
2434 case SMB_FS_OBJECTID_INFORMATION:
2439 * Query the version and capabilities of the CIFS UNIX extensions
2443 case SMB_QUERY_CIFS_UNIX_INFO:
2444 if (!lp_unix_extensions()) {
2445 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2448 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2449 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2450 /* We have POSIX ACLs, pathname and locking capability. */
2451 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2452 CIFS_UNIX_POSIX_ACLS_CAP|
2453 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2454 CIFS_UNIX_FCNTL_LOCKS_CAP)));
2457 case SMB_QUERY_POSIX_FS_INFO:
2460 vfs_statvfs_struct svfs;
2462 if (!lp_unix_extensions()) {
2463 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2466 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2470 SIVAL(pdata,0,svfs.OptimalTransferSize);
2471 SIVAL(pdata,4,svfs.BlockSize);
2472 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2473 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2474 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2475 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2476 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2477 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2478 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2480 } else if (rc == EOPNOTSUPP) {
2481 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2482 #endif /* EOPNOTSUPP */
2484 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2485 return ERROR_DOS(ERRSRV,ERRerror);
2490 case SMB_MAC_QUERY_FS_INFO:
2492 * Thursby MAC extension... ONLY on NTFS filesystems
2493 * once we do streams then we don't need this
2495 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2497 SIVAL(pdata,84,0x100); /* Don't support mac... */
2502 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2506 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2508 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2513 /****************************************************************************
2514 Reply to a TRANS2_SETFSINFO (set filesystem info).
2515 ****************************************************************************/
2517 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2518 char **pparams, int total_params, char **ppdata, int total_data,
2519 unsigned int max_data_bytes)
2521 char *pdata = *ppdata;
2522 char *params = *pparams;
2526 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2529 if (total_params < 4) {
2530 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2532 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2535 info_level = SVAL(params,2);
2537 switch(info_level) {
2538 case SMB_SET_CIFS_UNIX_INFO:
2540 uint16 client_unix_major;
2541 uint16 client_unix_minor;
2542 uint32 client_unix_cap_low;
2543 uint32 client_unix_cap_high;
2545 if (!lp_unix_extensions()) {
2546 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2549 /* There should be 12 bytes of capabilities set. */
2550 if (total_data < 8) {
2551 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2553 client_unix_major = SVAL(pdata,0);
2554 client_unix_minor = SVAL(pdata,2);
2555 client_unix_cap_low = IVAL(pdata,4);
2556 client_unix_cap_high = IVAL(pdata,8);
2557 /* Just print these values for now. */
2558 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2559 cap_low = 0x%x, cap_high = 0x%x\n",
2560 (unsigned int)client_unix_major,
2561 (unsigned int)client_unix_minor,
2562 (unsigned int)client_unix_cap_low,
2563 (unsigned int)client_unix_cap_high ));
2565 /* Here is where we must switch to posix pathname processing... */
2566 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2567 lp_set_posix_pathnames();
2568 mangle_change_to_posix();
2571 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2572 lp_set_posix_cifsx_locktype(POSIX_LOCK);
2576 case SMB_FS_QUOTA_INFORMATION:
2578 files_struct *fsp = NULL;
2579 SMB_NTQUOTA_STRUCT quotas;
2581 ZERO_STRUCT(quotas);
2584 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2585 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2586 lp_servicename(SNUM(conn)),conn->user));
2587 return ERROR_DOS(ERRSRV,ERRaccess);
2590 /* note: normaly there're 48 bytes,
2591 * but we didn't use the last 6 bytes for now
2594 fsp = file_fsp(params,0);
2595 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2596 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2597 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2600 if (total_data < 42) {
2601 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2603 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2606 /* unknown_1 24 NULL bytes in pdata*/
2608 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2609 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2610 #ifdef LARGE_SMB_OFF_T
2611 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2612 #else /* LARGE_SMB_OFF_T */
2613 if ((IVAL(pdata,28) != 0)&&
2614 ((quotas.softlim != 0xFFFFFFFF)||
2615 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2616 /* more than 32 bits? */
2617 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2619 #endif /* LARGE_SMB_OFF_T */
2621 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2622 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2623 #ifdef LARGE_SMB_OFF_T
2624 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2625 #else /* LARGE_SMB_OFF_T */
2626 if ((IVAL(pdata,36) != 0)&&
2627 ((quotas.hardlim != 0xFFFFFFFF)||
2628 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2629 /* more than 32 bits? */
2630 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2632 #endif /* LARGE_SMB_OFF_T */
2634 /* quota_flags 2 bytes **/
2635 quotas.qflags = SVAL(pdata,40);
2637 /* unknown_2 6 NULL bytes follow*/
2639 /* now set the quotas */
2640 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2641 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2642 return ERROR_DOS(ERRSRV,ERRerror);
2648 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2650 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2655 * sending this reply works fine,
2656 * but I'm not sure it's the same
2657 * like windows do...
2660 outsize = set_message(outbuf,10,0,True);
2665 /****************************************************************************
2666 Utility function to set bad path error.
2667 ****************************************************************************/
2669 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2671 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2672 err, (int)bad_path ));
2676 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2678 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2681 return UNIXERROR(def_class,def_code);
2684 #if defined(HAVE_POSIX_ACLS)
2685 /****************************************************************************
2686 Utility function to count the number of entries in a POSIX acl.
2687 ****************************************************************************/
2689 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2691 unsigned int ace_count = 0;
2692 int entry_id = SMB_ACL_FIRST_ENTRY;
2693 SMB_ACL_ENTRY_T entry;
2695 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2697 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2698 entry_id = SMB_ACL_NEXT_ENTRY;
2705 /****************************************************************************
2706 Utility function to marshall a POSIX acl into wire format.
2707 ****************************************************************************/
2709 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2711 int entry_id = SMB_ACL_FIRST_ENTRY;
2712 SMB_ACL_ENTRY_T entry;
2714 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2715 SMB_ACL_TAG_T tagtype;
2716 SMB_ACL_PERMSET_T permset;
2717 unsigned char perms = 0;
2718 unsigned int own_grp;
2721 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2722 entry_id = SMB_ACL_NEXT_ENTRY;
2725 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2726 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2730 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2731 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2735 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2736 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2737 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2739 SCVAL(pdata,1,perms);
2742 case SMB_ACL_USER_OBJ:
2743 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2744 own_grp = (unsigned int)pst->st_uid;
2745 SIVAL(pdata,2,own_grp);
2750 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2752 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2754 own_grp = (unsigned int)*puid;
2755 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2756 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2757 SIVAL(pdata,2,own_grp);
2761 case SMB_ACL_GROUP_OBJ:
2762 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2763 own_grp = (unsigned int)pst->st_gid;
2764 SIVAL(pdata,2,own_grp);
2769 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2771 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2773 own_grp = (unsigned int)*pgid;
2774 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2775 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2776 SIVAL(pdata,2,own_grp);
2781 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2782 SIVAL(pdata,2,0xFFFFFFFF);
2783 SIVAL(pdata,6,0xFFFFFFFF);
2786 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2787 SIVAL(pdata,2,0xFFFFFFFF);
2788 SIVAL(pdata,6,0xFFFFFFFF);
2791 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2794 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2801 /****************************************************************************
2802 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2803 file name or file id).
2804 ****************************************************************************/
2806 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2807 unsigned int tran_call,
2808 char **pparams, int total_params, char **ppdata, int total_data,
2809 unsigned int max_data_bytes)
2811 char *params = *pparams;
2812 char *pdata = *ppdata;
2816 SMB_OFF_T file_size=0;
2817 SMB_BIG_UINT allocation_size=0;
2818 unsigned int data_size = 0;
2819 unsigned int param_size = 2;
2820 SMB_STRUCT_STAT sbuf;
2821 pstring fname, dos_fname;
2826 BOOL bad_path = False;
2827 BOOL delete_pending = False;
2830 files_struct *fsp = NULL;
2831 TALLOC_CTX *data_ctx = NULL;
2832 struct ea_list *ea_list = NULL;
2833 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2834 char *lock_data = NULL;
2837 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2841 if (tran_call == TRANSACT2_QFILEINFO) {
2842 if (total_params < 4) {
2843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2846 fsp = file_fsp(params,0);
2847 info_level = SVAL(params,2);
2849 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2851 if(fsp && (fsp->fake_file_handle)) {
2853 * This is actually for the QUOTA_FAKE_FILE --metze
2856 pstrcpy(fname, fsp->fsp_name);
2857 /* We know this name is ok, it's already passed the checks. */
2859 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2861 * This is actually a QFILEINFO on a directory
2862 * handle (returned from an NT SMB). NT5.0 seems
2863 * to do this call. JRA.
2865 /* We know this name is ok, it's already passed the checks. */
2866 pstrcpy(fname, fsp->fsp_name);
2868 if (INFO_LEVEL_IS_UNIX(info_level)) {
2869 /* Always do lstat for UNIX calls. */
2870 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2871 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2872 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2874 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2875 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2876 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2879 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2882 * Original code - this is an open file.
2884 CHECK_FSP(fsp,conn);
2886 pstrcpy(fname, fsp->fsp_name);
2887 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2888 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2889 return(UNIXERROR(ERRDOS,ERRbadfid));
2891 pos = fsp->fh->position_information;
2892 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2893 access_mask = fsp->access_mask;
2896 NTSTATUS status = NT_STATUS_OK;
2899 if (total_params < 6) {
2900 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2903 info_level = SVAL(params,0);
2905 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2907 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2908 if (!NT_STATUS_IS_OK(status)) {
2909 return ERROR_NT(status);
2912 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2914 unix_convert(fname,conn,0,&bad_path,&sbuf);
2916 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2918 if (!check_name(fname,conn)) {
2919 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2920 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2923 if (INFO_LEVEL_IS_UNIX(info_level)) {
2924 /* Always do lstat for UNIX calls. */
2925 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2926 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2927 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2929 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2930 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2931 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2934 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2935 if (delete_pending) {
2936 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2940 nlink = sbuf.st_nlink;
2942 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2943 /* NTFS does not seem to count ".." */
2947 if ((nlink > 0) && delete_pending) {
2951 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2952 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2955 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2956 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2958 p = strrchr_m(fname,'/');
2964 mode = dos_mode(conn,fname,&sbuf);
2966 mode = FILE_ATTRIBUTE_NORMAL;
2968 fullpathname = fname;
2970 file_size = get_file_size(sbuf);
2972 /* Pull out any data sent here before we realloc. */
2973 switch (info_level) {
2974 case SMB_INFO_QUERY_EAS_FROM_LIST:
2976 /* Pull any EA list from the data portion. */
2979 if (total_data < 4) {
2980 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2982 ea_size = IVAL(pdata,0);
2984 if (total_data > 0 && ea_size != total_data) {
2985 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2986 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2987 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2990 if (!lp_ea_support(SNUM(conn))) {
2991 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2994 if ((data_ctx = talloc_init("ea_list")) == NULL) {
2995 return ERROR_NT(NT_STATUS_NO_MEMORY);
2998 /* Pull out the list of names. */
2999 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3001 talloc_destroy(data_ctx);
3002 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3007 case SMB_QUERY_POSIX_LOCK:
3009 if (fsp == NULL || fsp->fh->fd == -1) {
3010 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3013 if (total_data != POSIX_LOCK_DATA_SIZE) {
3014 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3017 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3018 return ERROR_NT(NT_STATUS_NO_MEMORY);
3021 /* Copy the lock range data. */
3022 lock_data = (char *)talloc_memdup(
3023 data_ctx, pdata, total_data);
3025 talloc_destroy(data_ctx);
3026 return ERROR_NT(NT_STATUS_NO_MEMORY);
3033 *pparams = (char *)SMB_REALLOC(*pparams,2);
3034 if (*pparams == NULL) {
3035 talloc_destroy(data_ctx);
3036 return ERROR_NT(NT_STATUS_NO_MEMORY);
3040 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3041 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3042 if (*ppdata == NULL ) {
3043 talloc_destroy(data_ctx);
3044 return ERROR_NT(NT_STATUS_NO_MEMORY);
3048 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3050 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3053 if (fsp->pending_modtime) {
3054 /* the pending modtime overrides the current modtime */
3055 sbuf.st_mtime = fsp->pending_modtime;
3058 /* Do we have this path open ? */
3059 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3060 if (fsp1 && fsp1->pending_modtime) {
3061 /* the pending modtime overrides the current modtime */
3062 sbuf.st_mtime = fsp1->pending_modtime;
3064 if (fsp1 && fsp1->initial_allocation_size) {
3065 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3069 if (lp_dos_filetime_resolution(SNUM(conn))) {
3071 sbuf.st_atime &= ~1;
3072 sbuf.st_ctime &= ~1;
3073 sbuf.st_mtime &= ~1;
3076 /* NT expects the name to be in an exact form of the *full*
3077 filename. See the trans2 torture test */
3078 if (strequal(base_name,".")) {
3079 pstrcpy(dos_fname, "\\");
3081 pstr_sprintf(dos_fname, "\\%s", fname);
3082 string_replace(dos_fname, '/', '\\');
3085 switch (info_level) {
3086 case SMB_INFO_STANDARD:
3087 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3089 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3090 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3091 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3092 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3093 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3094 SSVAL(pdata,l1_attrFile,mode);
3097 case SMB_INFO_QUERY_EA_SIZE:
3099 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3100 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3102 srv_put_dos_date2(pdata,0,c_time);
3103 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3104 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3105 SIVAL(pdata,12,(uint32)file_size);
3106 SIVAL(pdata,16,(uint32)allocation_size);
3107 SSVAL(pdata,20,mode);
3108 SIVAL(pdata,22,ea_size);
3112 case SMB_INFO_IS_NAME_VALID:
3113 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3114 if (tran_call == TRANSACT2_QFILEINFO) {
3115 /* os/2 needs this ? really ?*/
3116 return ERROR_DOS(ERRDOS,ERRbadfunc);
3122 case SMB_INFO_QUERY_EAS_FROM_LIST:
3124 size_t total_ea_len = 0;
3125 struct ea_list *ea_file_list = NULL;
3127 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3129 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3130 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3132 if (!ea_list || (total_ea_len > data_size)) {
3133 talloc_destroy(data_ctx);
3135 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3139 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3140 talloc_destroy(data_ctx);
3144 case SMB_INFO_QUERY_ALL_EAS:
3146 /* We have data_size bytes to put EA's into. */
3147 size_t total_ea_len = 0;
3149 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3151 data_ctx = talloc_init("ea_ctx");
3153 return ERROR_NT(NT_STATUS_NO_MEMORY);
3156 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3157 if (!ea_list || (total_ea_len > data_size)) {
3158 talloc_destroy(data_ctx);
3160 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3164 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3165 talloc_destroy(data_ctx);
3169 case SMB_FILE_BASIC_INFORMATION:
3170 case SMB_QUERY_FILE_BASIC_INFO:
3172 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3173 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3174 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3176 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3180 put_long_date(pdata,c_time);
3181 put_long_date(pdata+8,sbuf.st_atime);
3182 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3183 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3184 SIVAL(pdata,32,mode);
3186 DEBUG(5,("SMB_QFBI - "));
3188 time_t create_time = c_time;
3189 DEBUG(5,("create: %s ", ctime(&create_time)));
3191 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3192 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3193 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3194 DEBUG(5,("mode: %x\n", mode));
3197 case SMB_FILE_STANDARD_INFORMATION:
3198 case SMB_QUERY_FILE_STANDARD_INFO:
3200 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3202 SOFF_T(pdata,0,allocation_size);
3203 SOFF_T(pdata,8,file_size);
3204 SIVAL(pdata,16,nlink);
3205 SCVAL(pdata,20,delete_pending?1:0);
3206 SCVAL(pdata,21,(mode&aDIR)?1:0);
3207 SSVAL(pdata,22,0); /* Padding. */
3210 case SMB_FILE_EA_INFORMATION:
3211 case SMB_QUERY_FILE_EA_INFO:
3213 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3214 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3216 SIVAL(pdata,0,ea_size);
3220 /* Get the 8.3 name - used if NT SMB was negotiated. */
3221 case SMB_QUERY_FILE_ALT_NAME_INFO:
3222 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3226 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3227 pstrcpy(short_name,base_name);
3228 /* Mangle if not already 8.3 */
3229 if(!mangle_is_8_3(short_name, True, conn->params)) {
3230 mangle_map(short_name,True,True,conn->params);
3232 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3233 data_size = 4 + len;
3238 case SMB_QUERY_FILE_NAME_INFO:
3240 this must be *exactly* right for ACLs on mapped drives to work
3242 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3243 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3244 data_size = 4 + len;
3248 case SMB_FILE_ALLOCATION_INFORMATION:
3249 case SMB_QUERY_FILE_ALLOCATION_INFO:
3250 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3252 SOFF_T(pdata,0,allocation_size);
3255 case SMB_FILE_END_OF_FILE_INFORMATION:
3256 case SMB_QUERY_FILE_END_OF_FILEINFO:
3257 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3259 SOFF_T(pdata,0,file_size);
3262 case SMB_QUERY_FILE_ALL_INFO:
3263 case SMB_FILE_ALL_INFORMATION:
3265 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3266 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3267 put_long_date(pdata,c_time);
3268 put_long_date(pdata+8,sbuf.st_atime);
3269 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3270 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3271 SIVAL(pdata,32,mode);
3272 SIVAL(pdata,36,0); /* padding. */
3274 SOFF_T(pdata,0,allocation_size);
3275 SOFF_T(pdata,8,file_size);
3276 SIVAL(pdata,16,nlink);
3277 SCVAL(pdata,20,delete_pending);
3278 SCVAL(pdata,21,(mode&aDIR)?1:0);
3281 SIVAL(pdata,0,ea_size);
3282 pdata += 4; /* EA info */
3283 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3286 data_size = PTR_DIFF(pdata,(*ppdata));
3289 case SMB_FILE_INTERNAL_INFORMATION:
3290 /* This should be an index number - looks like
3293 I think this causes us to fail the IFSKIT
3294 BasicFileInformationTest. -tpot */
3296 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3297 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3298 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3302 case SMB_FILE_ACCESS_INFORMATION:
3303 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3304 SIVAL(pdata,0,access_mask);
3308 case SMB_FILE_NAME_INFORMATION:
3309 /* Pathname with leading '\'. */
3312 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3313 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3314 SIVAL(pdata,0,byte_len);
3315 data_size = 4 + byte_len;
3319 case SMB_FILE_DISPOSITION_INFORMATION:
3320 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3322 SCVAL(pdata,0,delete_pending);
3325 case SMB_FILE_POSITION_INFORMATION:
3326 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3328 SOFF_T(pdata,0,pos);
3331 case SMB_FILE_MODE_INFORMATION:
3332 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3333 SIVAL(pdata,0,mode);
3337 case SMB_FILE_ALIGNMENT_INFORMATION:
3338 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3339 SIVAL(pdata,0,0); /* No alignment needed. */
3345 * NT4 server just returns "invalid query" to this - if we try to answer
3346 * it then NTws gets a BSOD! (tridge).
3347 * W2K seems to want this. JRA.
3349 case SMB_QUERY_FILE_STREAM_INFO:
3351 case SMB_FILE_STREAM_INFORMATION:
3352 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3356 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3357 SIVAL(pdata,0,0); /* ??? */
3358 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3359 SOFF_T(pdata,8,file_size);
3360 SIVAL(pdata,16,allocation_size);
3361 SIVAL(pdata,20,0); /* ??? */
3362 data_size = 24 + byte_len;
3366 case SMB_QUERY_COMPRESSION_INFO:
3367 case SMB_FILE_COMPRESSION_INFORMATION:
3368 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3369 SOFF_T(pdata,0,file_size);
3370 SIVAL(pdata,8,0); /* ??? */
3371 SIVAL(pdata,12,0); /* ??? */
3375 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3377 put_long_date(pdata,c_time);
3378 put_long_date(pdata+8,sbuf.st_atime);
3379 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3380 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3381 SIVAL(pdata,32,allocation_size);
3382 SOFF_T(pdata,40,file_size);
3383 SIVAL(pdata,48,mode);
3384 SIVAL(pdata,52,0); /* ??? */
3388 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3389 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3390 SIVAL(pdata,0,mode);
3396 * CIFS UNIX Extensions.
3399 case SMB_QUERY_FILE_UNIX_BASIC:
3401 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3402 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3404 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3407 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3410 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3411 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3412 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3415 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3419 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3423 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3426 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3430 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3434 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3437 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3441 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3444 data_size = PTR_DIFF(pdata,(*ppdata));
3448 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3450 for (i=0; i<100; i++)
3451 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3457 case SMB_QUERY_FILE_UNIX_LINK:
3461 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3463 if(!S_ISLNK(sbuf.st_mode))
3464 return(UNIXERROR(ERRSRV,ERRbadlink));
3466 return(UNIXERROR(ERRDOS,ERRbadlink));
3468 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3470 return(UNIXERROR(ERRDOS,ERRnoaccess));
3472 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3474 data_size = PTR_DIFF(pdata,(*ppdata));
3479 #if defined(HAVE_POSIX_ACLS)
3480 case SMB_QUERY_POSIX_ACL:
3482 SMB_ACL_T file_acl = NULL;
3483 SMB_ACL_T def_acl = NULL;
3484 uint16 num_file_acls = 0;
3485 uint16 num_def_acls = 0;
3487 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3488 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3490 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3493 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3494 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3496 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3499 if (S_ISDIR(sbuf.st_mode)) {
3500 if (fsp && fsp->is_directory) {
3501 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3503 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3505 def_acl = free_empty_sys_acl(conn, def_acl);
3508 num_file_acls = count_acl_entries(conn, file_acl);
3509 num_def_acls = count_acl_entries(conn, def_acl);
3511 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3512 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3514 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3515 SMB_POSIX_ACL_HEADER_SIZE) ));
3517 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3520 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3522 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3525 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3526 SSVAL(pdata,2,num_file_acls);
3527 SSVAL(pdata,4,num_def_acls);
3528 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3530 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3533 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3535 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3537 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3539 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3542 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3544 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3548 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3551 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3553 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3559 case SMB_QUERY_POSIX_LOCK:
3561 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3563 SMB_BIG_UINT offset;
3565 enum brl_type lock_type;
3567 if (total_data != POSIX_LOCK_DATA_SIZE) {
3568 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3571 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3572 case POSIX_LOCK_TYPE_READ:
3573 lock_type = READ_LOCK;
3575 case POSIX_LOCK_TYPE_WRITE:
3576 lock_type = WRITE_LOCK;
3578 case POSIX_LOCK_TYPE_UNLOCK:
3580 /* There's no point in asking for an unlock... */
3581 talloc_destroy(data_ctx);
3582 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3585 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3586 #if defined(HAVE_LONGLONG)
3587 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3588 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3589 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3590 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3591 #else /* HAVE_LONGLONG */
3592 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3593 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3594 #endif /* HAVE_LONGLONG */
3596 status = query_lock(fsp,
3603 if (ERROR_WAS_LOCK_DENIED(status)) {
3604 /* Here we need to report who has it locked... */
3605 data_size = POSIX_LOCK_DATA_SIZE;
3607 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3608 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3609 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3610 #if defined(HAVE_LONGLONG)
3611 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3612 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3613 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3614 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3615 #else /* HAVE_LONGLONG */
3616 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3617 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3618 #endif /* HAVE_LONGLONG */
3620 } else if (NT_STATUS_IS_OK(status)) {
3621 /* For success we just return a copy of what we sent
3622 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3623 data_size = POSIX_LOCK_DATA_SIZE;
3624 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3625 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3627 return ERROR_NT(status);
3633 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3636 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3641 /****************************************************************************
3642 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3644 ****************************************************************************/
3646 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3648 BOOL bad_path_oldname = False;
3649 BOOL bad_path_newname = False;
3650 SMB_STRUCT_STAT sbuf1, sbuf2;
3651 pstring last_component_oldname;
3652 pstring last_component_newname;
3653 NTSTATUS status = NT_STATUS_OK;
3659 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3660 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3663 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3664 if (bad_path_oldname) {
3665 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3668 /* Quick check for "." and ".." */
3669 if (last_component_oldname[0] == '.') {
3670 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3671 return NT_STATUS_OBJECT_NAME_INVALID;
3675 /* source must already exist. */
3676 if (!VALID_STAT(sbuf1)) {
3677 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3680 if (!check_name(oldname,conn)) {
3681 return NT_STATUS_ACCESS_DENIED;
3684 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3685 if (bad_path_newname) {
3686 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3689 /* Quick check for "." and ".." */
3690 if (last_component_newname[0] == '.') {
3691 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3692 return NT_STATUS_OBJECT_NAME_INVALID;
3696 /* Disallow if newname already exists. */
3697 if (VALID_STAT(sbuf2)) {
3698 return NT_STATUS_OBJECT_NAME_COLLISION;
3701 if (!check_name(newname,conn)) {
3702 return NT_STATUS_ACCESS_DENIED;
3705 /* No links from a directory. */
3706 if (S_ISDIR(sbuf1.st_mode)) {
3707 return NT_STATUS_FILE_IS_A_DIRECTORY;
3710 /* Ensure this is within the share. */
3711 if (!reduce_name(conn, oldname) != 0)
3712 return NT_STATUS_ACCESS_DENIED;
3714 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3716 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3717 status = map_nt_error_from_unix(errno);
3718 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3719 nt_errstr(status), newname, oldname));
3725 /****************************************************************************
3726 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3727 ****************************************************************************/
3729 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3730 unsigned int tran_call,
3731 char **pparams, int total_params, char **ppdata, int total_data,
3732 unsigned int max_data_bytes)
3734 char *params = *pparams;
3735 char *pdata = *ppdata;
3740 SMB_STRUCT_STAT sbuf;
3743 BOOL bad_path = False;
3744 files_struct *fsp = NULL;
3745 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3746 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3747 mode_t unixmode = 0;
3748 NTSTATUS status = NT_STATUS_OK;
3751 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3756 if (tran_call == TRANSACT2_SETFILEINFO) {
3757 if (total_params < 4) {
3758 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3761 fsp = file_fsp(params,0);
3762 info_level = SVAL(params,2);
3764 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3766 * This is actually a SETFILEINFO on a directory
3767 * handle (returned from an NT SMB). NT5.0 seems
3768 * to do this call. JRA.
3770 pstrcpy(fname, fsp->fsp_name);
3771 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3772 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3773 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3775 } else if (fsp && fsp->print_file) {
3777 * Doing a DELETE_ON_CLOSE should cancel a print job.
3779 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3780 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3782 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3785 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3788 return (UNIXERROR(ERRDOS,ERRbadpath));
3791 * Original code - this is an open file.
3793 CHECK_FSP(fsp,conn);
3795 pstrcpy(fname, fsp->fsp_name);
3798 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3799 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3800 return(UNIXERROR(ERRDOS,ERRbadfid));
3805 if (total_params < 6) {
3806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3809 info_level = SVAL(params,0);
3810 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3811 if (!NT_STATUS_IS_OK(status)) {
3812 return ERROR_NT(status);
3814 unix_convert(fname,conn,0,&bad_path,&sbuf);
3816 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3820 * For CIFS UNIX extensions the target name may not exist.
3823 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3824 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3825 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3828 if(!check_name(fname, conn)) {
3829 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3834 if (!CAN_WRITE(conn))
3835 return ERROR_DOS(ERRSRV,ERRaccess);
3837 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3838 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3841 if (VALID_STAT(sbuf))
3842 unixmode = sbuf.st_mode;
3844 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3845 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3847 /* Realloc the parameter size */
3848 *pparams = (char *)SMB_REALLOC(*pparams,2);
3849 if (*pparams == NULL) {
3850 return ERROR_NT(NT_STATUS_NO_MEMORY);
3856 if (fsp && fsp->pending_modtime) {
3857 /* the pending modtime overrides the current modtime */
3858 sbuf.st_mtime = fsp->pending_modtime;
3861 size = get_file_size(sbuf);
3862 tvs.modtime = sbuf.st_mtime;
3863 tvs.actime = sbuf.st_atime;
3864 dosmode = dos_mode(conn,fname,&sbuf);
3865 unixmode = sbuf.st_mode;
3867 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3868 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3870 switch (info_level) {
3871 case SMB_INFO_STANDARD:
3873 if (total_data < 12) {
3874 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3878 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3880 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3884 case SMB_INFO_SET_EA:
3886 struct ea_list *ea_list = NULL;
3887 TALLOC_CTX *ctx = NULL;
3889 if (total_data < 10) {
3891 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3892 length. They seem to have no effect. Bug #3212. JRA */
3894 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3895 /* We're done. We only get EA info in this call. */
3897 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3901 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3904 if (IVAL(pdata,0) > total_data) {
3905 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3906 IVAL(pdata,0), (unsigned int)total_data));
3907 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3910 ctx = talloc_init("SMB_INFO_SET_EA");
3912 return ERROR_NT(NT_STATUS_NO_MEMORY);
3914 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3916 talloc_destroy(ctx);
3917 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3919 status = set_ea(conn, fsp, fname, ea_list);
3920 talloc_destroy(ctx);
3922 if (!NT_STATUS_IS_OK(status)) {
3923 return ERROR_NT(status);
3926 /* We're done. We only get EA info in this call. */
3928 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3933 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3934 /* XXXX um, i don't think this is right.
3935 it's also not in the cifs6.txt spec.
3937 case SMB_INFO_QUERY_EAS_FROM_LIST:
3938 if (total_data < 28)
3939 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3941 tvs.actime = make_unix_date2(pdata+8);
3942 tvs.modtime = make_unix_date2(pdata+12);
3943 size = IVAL(pdata,16);
3944 dosmode = IVAL(pdata,24);
3947 /* XXXX nor this. not in cifs6.txt, either. */
3948 case SMB_INFO_QUERY_ALL_EAS:
3949 if (total_data < 28)
3950 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3952 tvs.actime = make_unix_date2(pdata+8);
3953 tvs.modtime = make_unix_date2(pdata+12);
3954 size = IVAL(pdata,16);
3955 dosmode = IVAL(pdata,24);
3959 case SMB_SET_FILE_BASIC_INFO:
3960 case SMB_FILE_BASIC_INFORMATION:
3962 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3964 time_t changed_time;
3966 if (total_data < 36) {
3967 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3970 /* Ignore create time at offset pdata. */
3973 tvs.actime = interpret_long_date(pdata+8);
3975 write_time = interpret_long_date(pdata+16);
3976 changed_time = interpret_long_date(pdata+24);
3978 tvs.modtime = MIN(write_time, changed_time);
3980 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3981 tvs.modtime = write_time;
3983 /* Prefer a defined time to an undefined one. */
3984 if (null_mtime(tvs.modtime)) {
3985 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3989 dosmode = IVAL(pdata,32);
3993 case SMB_FILE_ALLOCATION_INFORMATION:
3994 case SMB_SET_FILE_ALLOCATION_INFO:
3997 SMB_BIG_UINT allocation_size;
3999 if (total_data < 8) {
4000 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4003 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4004 #ifdef LARGE_SMB_OFF_T
4005 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4006 #else /* LARGE_SMB_OFF_T */
4007 if (IVAL(pdata,4) != 0) {
4008 /* more than 32 bits? */
4009 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4011 #endif /* LARGE_SMB_OFF_T */
4012 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4013 fname, (double)allocation_size ));
4015 if (allocation_size) {
4016 allocation_size = smb_roundup(conn, allocation_size);
4019 if(allocation_size != get_file_size(sbuf)) {
4020 SMB_STRUCT_STAT new_sbuf;
4022 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4023 fname, (double)allocation_size ));
4026 files_struct *new_fsp = NULL;
4028 status = open_file_ntcreate(conn, fname, &sbuf,
4030 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4033 FILE_ATTRIBUTE_NORMAL,
4034 FORCE_OPLOCK_BREAK_TO_NONE,
4037 if (!NT_STATUS_IS_OK(status)) {
4038 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4039 /* We have re-scheduled this call. */
4042 return(UNIXERROR(ERRDOS,ERRnoaccess));
4044 ret = vfs_allocate_file_space(new_fsp, allocation_size);
4045 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4046 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4047 new_fsp->fnum, strerror(errno)));
4050 close_file(new_fsp,NORMAL_CLOSE);
4052 ret = vfs_allocate_file_space(fsp, allocation_size);
4053 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4054 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4055 fsp->fnum, strerror(errno)));
4060 return ERROR_NT(NT_STATUS_DISK_FULL);
4062 /* Allocate can truncate size... */
4063 size = get_file_size(new_sbuf);
4069 case SMB_FILE_END_OF_FILE_INFORMATION:
4070 case SMB_SET_FILE_END_OF_FILE_INFO:
4072 if (total_data < 8) {
4073 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4076 size = IVAL(pdata,0);
4077 #ifdef LARGE_SMB_OFF_T
4078 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4079 #else /* LARGE_SMB_OFF_T */
4080 if (IVAL(pdata,4) != 0) {
4081 /* more than 32 bits? */
4082 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4084 #endif /* LARGE_SMB_OFF_T */
4085 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4089 case SMB_FILE_DISPOSITION_INFORMATION:
4090 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4092 BOOL delete_on_close;
4094 if (total_data < 1) {
4095 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4098 delete_on_close = (CVAL(pdata,0) ? True : False);
4100 /* Just ignore this set on a path. */
4101 if (tran_call != TRANSACT2_SETFILEINFO)
4105 return(UNIXERROR(ERRDOS,ERRbadfid));
4107 status = can_set_delete_on_close(fsp, delete_on_close,
4110 if (!NT_STATUS_IS_OK(status)) {
4111 return ERROR_NT(status);
4114 /* The set is across all open files on this dev/inode pair. */
4115 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4116 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4120 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4124 case SMB_FILE_POSITION_INFORMATION:
4126 SMB_BIG_UINT position_information;
4128 if (total_data < 8) {
4129 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4132 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4133 #ifdef LARGE_SMB_OFF_T
4134 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4135 #else /* LARGE_SMB_OFF_T */
4136 if (IVAL(pdata,4) != 0) {
4137 /* more than 32 bits? */
4138 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4140 #endif /* LARGE_SMB_OFF_T */
4141 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4142 fname, (double)position_information ));
4144 fsp->fh->position_information = position_information;
4147 /* We're done. We only get position info in this call. */
4149 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4153 /* From tridge Samba4 :
4154 * MODE_INFORMATION in setfileinfo (I have no
4155 * idea what "mode information" on a file is - it takes a value of 0,
4156 * 2, 4 or 6. What could it be?).
4159 case SMB_FILE_MODE_INFORMATION:
4163 if (total_data < 4) {
4164 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4166 mode = IVAL(pdata,0);
4167 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4168 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4171 /* We're done. We only get mode info in this call. */
4173 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4178 * CIFS UNIX extensions.
4181 case SMB_SET_FILE_UNIX_BASIC:
4183 uint32 raw_unixmode;
4185 if (total_data < 100) {
4186 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4189 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4190 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4191 size=IVAL(pdata,0); /* first 8 Bytes are size */
4192 #ifdef LARGE_SMB_OFF_T
4193 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4194 #else /* LARGE_SMB_OFF_T */
4195 if (IVAL(pdata,4) != 0) {
4196 /* more than 32 bits? */
4197 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4199 #endif /* LARGE_SMB_OFF_T */
4201 pdata+=24; /* ctime & st_blocks are not changed */
4202 tvs.actime = interpret_long_date(pdata); /* access_time */
4203 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4205 set_owner = (uid_t)IVAL(pdata,0);
4207 set_grp = (gid_t)IVAL(pdata,0);
4209 raw_unixmode = IVAL(pdata,28);
4210 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4211 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4213 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4214 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4215 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4217 if (!VALID_STAT(sbuf)) {
4220 * The only valid use of this is to create character and block
4221 * devices, and named pipes. This is deprecated (IMHO) and
4222 * a new info level should be used for mknod. JRA.
4225 uint32 file_type = IVAL(pdata,0);
4226 #if defined(HAVE_MAKEDEV)
4227 uint32 dev_major = IVAL(pdata,4);
4228 uint32 dev_minor = IVAL(pdata,12);
4231 uid_t myuid = geteuid();
4232 gid_t mygid = getegid();
4233 SMB_DEV_T dev = (SMB_DEV_T)0;
4235 if (tran_call == TRANSACT2_SETFILEINFO)
4236 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4238 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4239 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4242 #if defined(HAVE_MAKEDEV)
4243 dev = makedev(dev_major, dev_minor);
4246 /* We can only create as the owner/group we are. */
4248 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4249 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4250 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4251 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4253 switch (file_type) {
4254 #if defined(S_IFIFO)
4255 case UNIX_TYPE_FIFO:
4256 unixmode |= S_IFIFO;
4259 #if defined(S_IFSOCK)
4260 case UNIX_TYPE_SOCKET:
4261 unixmode |= S_IFSOCK;
4264 #if defined(S_IFCHR)
4265 case UNIX_TYPE_CHARDEV:
4266 unixmode |= S_IFCHR;
4269 #if defined(S_IFBLK)
4270 case UNIX_TYPE_BLKDEV:
4271 unixmode |= S_IFBLK;
4275 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4278 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4279 0%o for file %s\n", (double)dev, unixmode, fname ));
4281 /* Ok - do the mknod. */
4282 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4283 return(UNIXERROR(ERRDOS,ERRnoaccess));
4285 inherit_access_acl(conn, fname, unixmode);
4288 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4293 * Deal with the UNIX specific mode set.
4296 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4297 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4298 (unsigned int)unixmode, fname ));
4299 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4300 return(UNIXERROR(ERRDOS,ERRnoaccess));
4304 * Deal with the UNIX specific uid set.
4307 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4308 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4309 (unsigned int)set_owner, fname ));
4310 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4311 return(UNIXERROR(ERRDOS,ERRnoaccess));
4315 * Deal with the UNIX specific gid set.
4318 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4319 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4320 (unsigned int)set_owner, fname ));
4321 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4322 return(UNIXERROR(ERRDOS,ERRnoaccess));
4327 case SMB_SET_FILE_UNIX_LINK:
4329 pstring link_target;
4330 char *newname = fname;
4332 /* Set a symbolic link. */
4333 /* Don't allow this if follow links is false. */
4335 if (!lp_symlinks(SNUM(conn)))
4336 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4338 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4340 /* !widelinks forces the target path to be within the share. */
4341 /* This means we can interpret the target as a pathname. */
4342 if (!lp_widelinks(SNUM(conn))) {
4344 char *last_dirp = NULL;
4346 unix_format(link_target);
4347 if (*link_target == '/') {
4348 /* No absolute paths allowed. */
4349 return(UNIXERROR(ERRDOS,ERRnoaccess));
4351 pstrcpy(rel_name, newname);
4352 last_dirp = strrchr_m(rel_name, '/');
4354 last_dirp[1] = '\0';
4356 pstrcpy(rel_name, "./");
4358 pstrcat(rel_name, link_target);
4360 if (!check_name(rel_name, conn)) {
4361 return(UNIXERROR(ERRDOS,ERRnoaccess));
4365 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4366 fname, link_target ));
4368 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4369 return(UNIXERROR(ERRDOS,ERRnoaccess));
4371 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4375 case SMB_SET_FILE_UNIX_HLINK:
4378 char *newname = fname;
4380 /* Set a hard link. */
4381 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4382 if (!NT_STATUS_IS_OK(status)) {
4383 return ERROR_NT(status);
4386 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4389 status = hardlink_internals(conn, oldname, newname);
4390 if (!NT_STATUS_IS_OK(status)) {
4391 return ERROR_NT(status);
4395 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4399 case SMB_FILE_RENAME_INFORMATION:
4402 /* uint32 root_fid; */ /* Not used */
4408 if (total_data < 12) {
4409 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4412 overwrite = (CVAL(pdata,0) ? True : False);
4413 /* root_fid = IVAL(pdata,4); */
4414 len = IVAL(pdata,8);
4415 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4416 if (!NT_STATUS_IS_OK(status)) {
4417 return ERROR_NT(status);
4420 /* Check the new name has no '/' characters. */
4421 if (strchr_m(newname, '/'))
4422 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4424 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4426 /* Create the base directory. */
4427 pstrcpy(base_name, fname);
4428 p = strrchr_m(base_name, '/');
4431 /* Append the new name. */
4432 pstrcat(base_name, "/");
4433 pstrcat(base_name, newname);
4436 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4437 fsp->fnum, fsp->fsp_name, base_name ));
4438 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4440 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4442 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4444 if (!NT_STATUS_IS_OK(status)) {
4445 return ERROR_NT(status);
4447 process_pending_change_notify_queue((time_t)0);
4449 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4453 #if defined(HAVE_POSIX_ACLS)
4454 case SMB_SET_POSIX_ACL:
4456 uint16 posix_acl_version;
4457 uint16 num_file_acls;
4458 uint16 num_def_acls;
4459 BOOL valid_file_acls = True;
4460 BOOL valid_def_acls = True;
4462 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4463 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4465 posix_acl_version = SVAL(pdata,0);
4466 num_file_acls = SVAL(pdata,2);
4467 num_def_acls = SVAL(pdata,4);
4469 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4470 valid_file_acls = False;
4474 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4475 valid_def_acls = False;
4479 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4480 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4483 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4484 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4485 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4488 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4489 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4490 return(UNIXERROR(ERRDOS,ERRnoaccess));
4493 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4494 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4495 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4496 return(UNIXERROR(ERRDOS,ERRnoaccess));
4500 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4505 case SMB_SET_POSIX_LOCK:
4508 SMB_BIG_UINT offset;
4510 BOOL blocking_lock = False;
4511 enum brl_type lock_type;
4513 if (fsp == NULL || fsp->fh->fd == -1) {
4514 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4517 if (total_data != POSIX_LOCK_DATA_SIZE) {
4518 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4521 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4522 case POSIX_LOCK_TYPE_READ:
4523 lock_type = READ_LOCK;
4525 case POSIX_LOCK_TYPE_WRITE:
4526 /* Return the right POSIX-mappable error code for files opened read-only. */
4527 if (!fsp->can_write) {
4528 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4530 lock_type = WRITE_LOCK;
4532 case POSIX_LOCK_TYPE_UNLOCK:
4533 lock_type = UNLOCK_LOCK;
4536 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4539 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4540 blocking_lock = False;
4541 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4542 blocking_lock = True;
4544 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4547 if (!lp_blocking_locks(SNUM(conn))) {
4548 blocking_lock = False;
4551 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4552 #if defined(HAVE_LONGLONG)
4553 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4554 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4555 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4556 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4557 #else /* HAVE_LONGLONG */
4558 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4559 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4560 #endif /* HAVE_LONGLONG */
4562 if (lock_type == UNLOCK_LOCK) {
4563 status = do_unlock(fsp,
4569 struct byte_range_lock *br_lck = do_lock(fsp,
4578 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4580 * A blocking lock was requested. Package up
4581 * this smb into a queued request and push it
4582 * onto the blocking lock queue.
4584 if(push_blocking_lock_request(br_lck,
4587 -1, /* infinite timeout. */
4594 TALLOC_FREE(br_lck);
4598 TALLOC_FREE(br_lck);
4601 if (!NT_STATUS_IS_OK(status)) {
4602 return ERROR_NT(status);
4606 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4611 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4614 /* get some defaults (no modifications) if any info is zero or -1. */
4615 if (null_mtime(tvs.actime)) {
4616 tvs.actime = sbuf.st_atime;
4619 if (null_mtime(tvs.modtime)) {
4620 tvs.modtime = sbuf.st_mtime;
4623 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4624 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4625 DEBUG(6,("size: %.0f ", (double)size));
4628 if (S_ISDIR(sbuf.st_mode))
4634 DEBUG(6,("dosmode: %x\n" , dosmode));
4636 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4637 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4638 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4639 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4642 * Only do this test if we are not explicitly
4643 * changing the size of a file.
4646 size = get_file_size(sbuf);
4650 * Try and set the times, size and mode of this file -
4651 * if they are different from the current values
4654 /* check the mode isn't different, before changing it */
4655 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4657 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4659 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4660 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4661 return(UNIXERROR(ERRDOS,ERRnoaccess));
4666 if (size != get_file_size(sbuf)) {
4670 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4671 fname, (double)size ));
4674 files_struct *new_fsp = NULL;
4676 status = open_file_ntcreate(conn, fname, &sbuf,
4678 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4681 FILE_ATTRIBUTE_NORMAL,
4682 FORCE_OPLOCK_BREAK_TO_NONE,
4685 if (!NT_STATUS_IS_OK(status)) {
4686 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4687 /* We have re-scheduled this call. */
4690 return(UNIXERROR(ERRDOS,ERRnoaccess));
4692 ret = vfs_set_filelen(new_fsp, size);
4693 close_file(new_fsp,NORMAL_CLOSE);
4695 ret = vfs_set_filelen(fsp, size);
4699 return (UNIXERROR(ERRHRD,ERRdiskfull));
4704 * Finally the times.
4706 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4709 * This was a setfileinfo on an open file.
4710 * NT does this a lot. We also need to
4711 * set the time here, as it can be read by
4712 * FindFirst/FindNext and with the patch for bug #2045
4713 * in smbd/fileio.c it ensures that this timestamp is
4714 * kept sticky even after a write. We save the request
4715 * away and will set it on file close and after a write. JRA.
4718 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4719 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4720 fsp_set_pending_modtime(fsp, tvs.modtime);
4724 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4726 if(file_utime(conn, fname, &tvs)!=0) {
4727 return(UNIXERROR(ERRDOS,ERRnoaccess));
4732 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4737 /****************************************************************************
4738 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4739 ****************************************************************************/
4741 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4742 char **pparams, int total_params, char **ppdata, int total_data,
4743 unsigned int max_data_bytes)
4745 char *params = *pparams;
4746 char *pdata = *ppdata;
4749 SMB_STRUCT_STAT sbuf;
4750 BOOL bad_path = False;
4751 NTSTATUS status = NT_STATUS_OK;
4752 TALLOC_CTX *ctx = NULL;
4753 struct ea_list *ea_list = NULL;
4755 if (!CAN_WRITE(conn))
4756 return ERROR_DOS(ERRSRV,ERRaccess);
4758 if (total_params < 4) {
4759 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4762 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
4763 if (!NT_STATUS_IS_OK(status)) {
4764 return ERROR_NT(status);
4767 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4769 unix_convert(directory,conn,0,&bad_path,&sbuf);
4771 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4774 /* Any data in this call is an EA list. */
4775 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4776 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4780 * OS/2 workplace shell seems to send SET_EA requests of "null"
4781 * length (4 bytes containing IVAL 4).
4782 * They seem to have no effect. Bug #3212. JRA.
4785 if (total_data != 4) {
4786 if (total_data < 10) {
4787 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4790 if (IVAL(pdata,0) > total_data) {
4791 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4792 IVAL(pdata,0), (unsigned int)total_data));
4793 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4796 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4798 return ERROR_NT(NT_STATUS_NO_MEMORY);
4800 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4802 talloc_destroy(ctx);
4803 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4805 } else if (IVAL(pdata,0) != 4) {
4806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4809 if (check_name(directory,conn)) {
4810 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4814 talloc_destroy(ctx);
4815 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4816 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4819 /* Try and set any given EA. */
4821 status = set_ea(conn, NULL, directory, ea_list);
4822 talloc_destroy(ctx);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 return ERROR_NT(status);
4828 /* Realloc the parameter and data sizes */
4829 *pparams = (char *)SMB_REALLOC(*pparams,2);
4830 if(*pparams == NULL) {
4831 return ERROR_NT(NT_STATUS_NO_MEMORY);
4837 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4842 /****************************************************************************
4843 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4844 We don't actually do this - we just send a null response.
4845 ****************************************************************************/
4847 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4848 char **pparams, int total_params, char **ppdata, int total_data,
4849 unsigned int max_data_bytes)
4851 static uint16 fnf_handle = 257;
4852 char *params = *pparams;
4855 if (total_params < 6) {
4856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4859 info_level = SVAL(params,4);
4860 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4862 switch (info_level) {
4867 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4870 /* Realloc the parameter and data sizes */
4871 *pparams = (char *)SMB_REALLOC(*pparams,6);
4872 if (*pparams == NULL) {
4873 return ERROR_NT(NT_STATUS_NO_MEMORY);
4877 SSVAL(params,0,fnf_handle);
4878 SSVAL(params,2,0); /* No changes */
4879 SSVAL(params,4,0); /* No EA errors */
4886 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4891 /****************************************************************************
4892 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4893 changes). Currently this does nothing.
4894 ****************************************************************************/
4896 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4897 char **pparams, int total_params, char **ppdata, int total_data,
4898 unsigned int max_data_bytes)
4900 char *params = *pparams;
4902 DEBUG(3,("call_trans2findnotifynext\n"));
4904 /* Realloc the parameter and data sizes */
4905 *pparams = (char *)SMB_REALLOC(*pparams,4);
4906 if (*pparams == NULL) {
4907 return ERROR_NT(NT_STATUS_NO_MEMORY);
4911 SSVAL(params,0,0); /* No changes */
4912 SSVAL(params,2,0); /* No EA errors */
4914 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4919 /****************************************************************************
4920 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4921 ****************************************************************************/
4923 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4924 char **pparams, int total_params, char **ppdata, int total_data,
4925 unsigned int max_data_bytes)
4927 char *params = *pparams;
4930 int max_referral_level;
4932 DEBUG(10,("call_trans2getdfsreferral\n"));
4934 if (total_params < 2) {
4935 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4938 max_referral_level = SVAL(params,0);
4940 if(!lp_host_msdfs())
4941 return ERROR_DOS(ERRDOS,ERRbadfunc);
4943 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4944 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4945 return UNIXERROR(ERRDOS,ERRbadfile);
4947 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4948 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4953 #define LMCAT_SPL 0x53
4954 #define LMFUNC_GETJOBID 0x60
4956 /****************************************************************************
4957 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4958 ****************************************************************************/
4960 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4961 char **pparams, int total_params, char **ppdata, int total_data,
4962 unsigned int max_data_bytes)
4964 char *pdata = *ppdata;
4965 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4967 /* check for an invalid fid before proceeding */
4970 return(ERROR_DOS(ERRDOS,ERRbadfid));
4972 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4973 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4974 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
4975 if (*ppdata == NULL) {
4976 return ERROR_NT(NT_STATUS_NO_MEMORY);
4980 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4981 CAN ACCEPT THIS IN UNICODE. JRA. */
4983 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4984 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4985 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4986 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4989 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4990 return ERROR_DOS(ERRSRV,ERRerror);
4994 /****************************************************************************
4995 Reply to a SMBfindclose (stop trans2 directory search).
4996 ****************************************************************************/
4998 int reply_findclose(connection_struct *conn,
4999 char *inbuf,char *outbuf,int length,int bufsize)
5002 int dptr_num=SVALS(inbuf,smb_vwv0);
5003 START_PROFILE(SMBfindclose);
5005 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5007 dptr_close(&dptr_num);
5009 outsize = set_message(outbuf,0,0,False);
5011 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5013 END_PROFILE(SMBfindclose);
5017 /****************************************************************************
5018 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5019 ****************************************************************************/
5021 int reply_findnclose(connection_struct *conn,
5022 char *inbuf,char *outbuf,int length,int bufsize)
5026 START_PROFILE(SMBfindnclose);
5028 dptr_num = SVAL(inbuf,smb_vwv0);
5030 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5032 /* We never give out valid handles for a
5033 findnotifyfirst - so any dptr_num is ok here.
5036 outsize = set_message(outbuf,0,0,False);
5038 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5040 END_PROFILE(SMBfindnclose);
5044 int handle_trans2(connection_struct *conn,
5045 struct trans_state *state,
5046 char *inbuf, char *outbuf, int size, int bufsize)
5050 if (Protocol >= PROTOCOL_NT1) {
5051 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5054 /* Now we must call the relevant TRANS2 function */
5055 switch(state->call) {
5056 case TRANSACT2_OPEN:
5058 START_PROFILE_NESTED(Trans2_open);
5059 outsize = call_trans2open(
5060 conn, inbuf, outbuf, bufsize,
5061 &state->param, state->total_param,
5062 &state->data, state->total_data,
5063 state->max_data_return);
5064 END_PROFILE_NESTED(Trans2_open);
5068 case TRANSACT2_FINDFIRST:
5070 START_PROFILE_NESTED(Trans2_findfirst);
5071 outsize = call_trans2findfirst(
5072 conn, inbuf, outbuf, bufsize,
5073 &state->param, state->total_param,
5074 &state->data, state->total_data,
5075 state->max_data_return);
5076 END_PROFILE_NESTED(Trans2_findfirst);
5080 case TRANSACT2_FINDNEXT:
5082 START_PROFILE_NESTED(Trans2_findnext);
5083 outsize = call_trans2findnext(
5084 conn, inbuf, outbuf, size, bufsize,
5085 &state->param, state->total_param,
5086 &state->data, state->total_data,
5087 state->max_data_return);
5088 END_PROFILE_NESTED(Trans2_findnext);
5092 case TRANSACT2_QFSINFO:
5094 START_PROFILE_NESTED(Trans2_qfsinfo);
5095 outsize = call_trans2qfsinfo(
5096 conn, inbuf, outbuf, size, bufsize,
5097 &state->param, state->total_param,
5098 &state->data, state->total_data,
5099 state->max_data_return);
5100 END_PROFILE_NESTED(Trans2_qfsinfo);
5104 case TRANSACT2_SETFSINFO:
5106 START_PROFILE_NESTED(Trans2_setfsinfo);
5107 outsize = call_trans2setfsinfo(
5108 conn, inbuf, outbuf, size, bufsize,
5109 &state->param, state->total_param,
5110 &state->data, state->total_data,
5111 state->max_data_return);
5112 END_PROFILE_NESTED(Trans2_setfsinfo);
5116 case TRANSACT2_QPATHINFO:
5117 case TRANSACT2_QFILEINFO:
5119 START_PROFILE_NESTED(Trans2_qpathinfo);
5120 outsize = call_trans2qfilepathinfo(
5121 conn, inbuf, outbuf, size, bufsize, state->call,
5122 &state->param, state->total_param,
5123 &state->data, state->total_data,
5124 state->max_data_return);
5125 END_PROFILE_NESTED(Trans2_qpathinfo);
5129 case TRANSACT2_SETPATHINFO:
5130 case TRANSACT2_SETFILEINFO:
5132 START_PROFILE_NESTED(Trans2_setpathinfo);
5133 outsize = call_trans2setfilepathinfo(
5134 conn, inbuf, outbuf, size, bufsize, state->call,
5135 &state->param, state->total_param,
5136 &state->data, state->total_data,
5137 state->max_data_return);
5138 END_PROFILE_NESTED(Trans2_setpathinfo);
5142 case TRANSACT2_FINDNOTIFYFIRST:
5144 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5145 outsize = call_trans2findnotifyfirst(
5146 conn, inbuf, outbuf, size, bufsize,
5147 &state->param, state->total_param,
5148 &state->data, state->total_data,
5149 state->max_data_return);
5150 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5154 case TRANSACT2_FINDNOTIFYNEXT:
5156 START_PROFILE_NESTED(Trans2_findnotifynext);
5157 outsize = call_trans2findnotifynext(
5158 conn, inbuf, outbuf, size, bufsize,
5159 &state->param, state->total_param,
5160 &state->data, state->total_data,
5161 state->max_data_return);
5162 END_PROFILE_NESTED(Trans2_findnotifynext);
5166 case TRANSACT2_MKDIR:
5168 START_PROFILE_NESTED(Trans2_mkdir);
5169 outsize = call_trans2mkdir(
5170 conn, inbuf, outbuf, size, bufsize,
5171 &state->param, state->total_param,
5172 &state->data, state->total_data,
5173 state->max_data_return);
5174 END_PROFILE_NESTED(Trans2_mkdir);
5178 case TRANSACT2_GET_DFS_REFERRAL:
5180 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5181 outsize = call_trans2getdfsreferral(
5182 conn, inbuf, outbuf, size, bufsize,
5183 &state->param, state->total_param,
5184 &state->data, state->total_data,
5185 state->max_data_return);
5186 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5190 case TRANSACT2_IOCTL:
5192 START_PROFILE_NESTED(Trans2_ioctl);
5193 outsize = call_trans2ioctl(
5194 conn, inbuf, outbuf, size, bufsize,
5195 &state->param, state->total_param,
5196 &state->data, state->total_data,
5197 state->max_data_return);
5198 END_PROFILE_NESTED(Trans2_ioctl);
5203 /* Error in request */
5204 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5205 outsize = ERROR_DOS(ERRSRV,ERRerror);
5211 /****************************************************************************
5212 Reply to a SMBtrans2.
5213 ****************************************************************************/
5215 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5216 int size, int bufsize)
5219 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5220 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5221 unsigned int psoff = SVAL(inbuf, smb_psoff);
5222 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5223 unsigned int tran_call = SVAL(inbuf, smb_setup0);
5224 struct trans_state *state;
5227 START_PROFILE(SMBtrans2);
5229 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5230 if (!NT_STATUS_IS_OK(result)) {
5231 DEBUG(2, ("Got invalid trans2 request: %s\n",
5232 nt_errstr(result)));
5233 END_PROFILE(SMBtrans2);
5234 return ERROR_NT(result);
5237 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5238 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5239 END_PROFILE(SMBtrans2);
5240 return ERROR_DOS(ERRSRV,ERRaccess);
5243 if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
5244 DEBUG(0, ("talloc failed\n"));
5245 END_PROFILE(SMBtrans2);
5246 return ERROR_NT(NT_STATUS_NO_MEMORY);
5249 state->cmd = SMBtrans2;
5251 state->mid = SVAL(inbuf, smb_mid);
5252 state->vuid = SVAL(inbuf, smb_uid);
5253 state->setup_count = SVAL(inbuf, smb_suwcnt);
5254 state->total_param = SVAL(inbuf, smb_tpscnt);
5255 state->param = NULL;
5256 state->total_data = SVAL(inbuf, smb_tdscnt);
5258 state->max_param_return = SVAL(inbuf, smb_mprcnt);
5259 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
5260 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5261 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5262 state->one_way = BITSETW(inbuf+smb_vwv5,1);
5264 state->call = tran_call;
5266 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5267 is so as a sanity check */
5268 if (state->setup_count != 1) {
5270 * Need to have rc=0 for ioctl to get job id for OS/2.
5271 * Network printing will fail if function is not successful.
5272 * Similar function in reply.c will be used if protocol
5273 * is LANMAN1.0 instead of LM1.2X002.
5274 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5275 * outbuf doesn't have to be set(only job id is used).
5277 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5278 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5279 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5280 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5282 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5283 DEBUG(2,("Transaction is %d\n",tran_call));
5285 END_PROFILE(SMBtrans2);
5286 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5290 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5293 if (state->total_data) {
5294 /* Can't use talloc here, the core routines do realloc on the
5295 * params and data. */
5296 state->data = (char *)SMB_MALLOC(state->total_data);
5297 if (state->data == NULL) {
5298 DEBUG(0,("reply_trans2: data malloc fail for %u "
5299 "bytes !\n", (unsigned int)state->total_data));
5301 END_PROFILE(SMBtrans2);
5302 return(ERROR_DOS(ERRDOS,ERRnomem));
5304 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5306 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5307 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5310 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5313 if (state->total_param) {
5314 /* Can't use talloc here, the core routines do realloc on the
5315 * params and data. */
5316 state->param = (char *)SMB_MALLOC(state->total_param);
5317 if (state->param == NULL) {
5318 DEBUG(0,("reply_trans: param malloc fail for %u "
5319 "bytes !\n", (unsigned int)state->total_param));
5320 SAFE_FREE(state->data);
5322 END_PROFILE(SMBtrans2);
5323 return(ERROR_DOS(ERRDOS,ERRnomem));
5325 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5327 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5328 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5331 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5334 state->received_data = dscnt;
5335 state->received_param = pscnt;
5337 if ((state->received_param == state->total_param) &&
5338 (state->received_data == state->total_data)) {
5340 outsize = handle_trans2(conn, state, inbuf, outbuf,
5342 SAFE_FREE(state->data);
5343 SAFE_FREE(state->param);
5345 END_PROFILE(SMBtrans2);
5349 DLIST_ADD(conn->pending_trans, state);
5351 /* We need to send an interim response then receive the rest
5352 of the parameter/data bytes */
5353 outsize = set_message(outbuf,0,0,False);
5355 END_PROFILE(SMBtrans2);
5360 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5361 SAFE_FREE(state->data);
5362 SAFE_FREE(state->param);
5364 END_PROFILE(SMBtrans2);
5365 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5369 /****************************************************************************
5370 Reply to a SMBtranss2
5371 ****************************************************************************/
5373 int reply_transs2(connection_struct *conn,
5374 char *inbuf,char *outbuf,int size,int bufsize)
5377 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5378 struct trans_state *state;
5380 START_PROFILE(SMBtranss2);
5384 for (state = conn->pending_trans; state != NULL;
5385 state = state->next) {
5386 if (state->mid == SVAL(inbuf,smb_mid)) {
5391 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5392 END_PROFILE(SMBtranss2);
5393 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5396 /* Revise state->total_param and state->total_data in case they have
5397 changed downwards */
5399 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5400 state->total_param = SVAL(inbuf, smb_tpscnt);
5401 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5402 state->total_data = SVAL(inbuf, smb_tdscnt);
5404 pcnt = SVAL(inbuf, smb_spscnt);
5405 poff = SVAL(inbuf, smb_spsoff);
5406 pdisp = SVAL(inbuf, smb_spsdisp);
5408 dcnt = SVAL(inbuf, smb_sdscnt);
5409 doff = SVAL(inbuf, smb_sdsoff);
5410 ddisp = SVAL(inbuf, smb_sdsdisp);
5412 state->received_param += pcnt;
5413 state->received_data += dcnt;
5415 if ((state->received_data > state->total_data) ||
5416 (state->received_param > state->total_param))
5420 if (pdisp+pcnt > state->total_param)
5422 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5424 if (pdisp > state->total_param)
5426 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5427 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5429 if (state->param + pdisp < state->param)
5432 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5437 if (ddisp+dcnt > state->total_data)
5439 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5441 if (ddisp > state->total_data)
5443 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5444 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5446 if (state->data + ddisp < state->data)
5449 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5453 if ((state->received_param < state->total_param) ||
5454 (state->received_data < state->total_data)) {
5455 END_PROFILE(SMBtranss2);
5459 /* construct_reply_common has done us the favor to pre-fill the
5460 * command field with SMBtranss2 which is wrong :-)
5462 SCVAL(outbuf,smb_com,SMBtrans2);
5464 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5466 DLIST_REMOVE(conn->pending_trans, state);
5467 SAFE_FREE(state->data);
5468 SAFE_FREE(state->param);
5472 END_PROFILE(SMBtranss2);
5473 return(ERROR_DOS(ERRSRV,ERRnosupport));
5476 END_PROFILE(SMBtranss2);
5481 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5482 DLIST_REMOVE(conn->pending_trans, state);
5483 SAFE_FREE(state->data);
5484 SAFE_FREE(state->param);
5486 END_PROFILE(SMBtranss2);
5487 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);