2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Steve French 2005
9 Extensively modified by Andrew Tridgell, 1995
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 /********************************************************************
38 Roundup a value to the nearest allocation roundup size boundary.
39 Only do this for Windows clients.
40 ********************************************************************/
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
44 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
46 /* Only roundup for Windows clients. */
47 enum remote_arch_types ra_type = get_remote_arch();
48 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49 val = SMB_ROUNDUP(val,rval);
54 /********************************************************************
55 Given a stat buffer return the allocated size on disk, taking into
57 ********************************************************************/
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
63 if(S_ISDIR(sbuf->st_mode)) {
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
70 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
73 if (fsp && fsp->initial_allocation_size)
74 ret = MAX(ret,fsp->initial_allocation_size);
76 return smb_roundup(conn, ret);
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 static const char *prohibited_ea_names[] = {
84 SAMBA_POSIX_INHERITANCE_EA_NAME,
85 SAMBA_XATTR_DOS_ATTRIB,
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
123 if (fsp && fsp->fh->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
138 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139 dump_data(10, val, sizeret);
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
147 pea->value.data = (unsigned char *)val;
148 pea->value.length = (size_t)sizeret;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157 const char *fname, size_t *pea_total_len)
159 /* Get a list of all xattrs. Max namesize is 64k. */
160 size_t ea_namelist_size = 1024;
165 struct ea_list *ea_list_head = NULL;
169 if (!lp_ea_support(SNUM(conn))) {
173 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
174 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
175 if (fsp && fsp->fh->fd != -1) {
176 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
178 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
181 if (sizeret == -1 && errno == ERANGE) {
182 ea_namelist_size *= 2;
191 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
194 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
195 struct ea_list *listp, *tmp;
197 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
200 listp = TALLOC_P(mem_ctx, struct ea_list);
204 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
210 push_ascii_fstring(dos_ea_name, listp->ea.name);
211 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
212 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
213 (unsigned int)*pea_total_len, dos_ea_name,
214 (unsigned int)listp->ea.value.length ));
216 DLIST_ADD_END(ea_list_head, listp, tmp);
218 /* Add on 4 for total length. */
219 if (*pea_total_len) {
224 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
228 /****************************************************************************
229 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
231 ****************************************************************************/
233 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
234 connection_struct *conn, struct ea_list *ea_list)
236 unsigned int ret_data_size = 4;
239 SMB_ASSERT(total_data_size >= 4);
241 if (!lp_ea_support(SNUM(conn))) {
246 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
249 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
250 dos_namelen = strlen(dos_ea_name);
251 if (dos_namelen > 255 || dos_namelen == 0) {
254 if (ea_list->ea.value.length > 65535) {
257 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
261 /* We know we have room. */
262 SCVAL(p,0,ea_list->ea.flags);
263 SCVAL(p,1,dos_namelen);
264 SSVAL(p,2,ea_list->ea.value.length);
265 fstrcpy(p+4, dos_ea_name);
266 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
268 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
269 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
272 ret_data_size = PTR_DIFF(p, pdata);
273 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
274 SIVAL(pdata,0,ret_data_size);
275 return ret_data_size;
278 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
280 size_t total_ea_len = 0;
281 TALLOC_CTX *mem_ctx = NULL;
283 if (!lp_ea_support(SNUM(conn))) {
286 mem_ctx = talloc_init("estimate_ea_size");
287 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
288 talloc_destroy(mem_ctx);
292 /****************************************************************************
293 Ensure the EA name is case insensitive by matching any existing EA name.
294 ****************************************************************************/
296 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
299 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
300 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
302 for (; ea_list; ea_list = ea_list->next) {
303 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
304 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
305 &unix_ea_name[5], ea_list->ea.name));
306 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
310 talloc_destroy(mem_ctx);
313 /****************************************************************************
314 Set or delete an extended attribute.
315 ****************************************************************************/
317 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
319 if (!lp_ea_support(SNUM(conn))) {
320 return NT_STATUS_EAS_NOT_SUPPORTED;
323 for (;ea_list; ea_list = ea_list->next) {
325 fstring unix_ea_name;
327 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
328 fstrcat(unix_ea_name, ea_list->ea.name);
330 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
332 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
334 if (samba_private_attr_name(unix_ea_name)) {
335 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
336 return NT_STATUS_ACCESS_DENIED;
339 if (ea_list->ea.value.length == 0) {
340 /* Remove the attribute. */
341 if (fsp && (fsp->fh->fd != -1)) {
342 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
343 unix_ea_name, fsp->fsp_name));
344 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
346 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
347 unix_ea_name, fname));
348 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
351 /* Removing a non existent attribute always succeeds. */
352 if (ret == -1 && errno == ENOATTR) {
353 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
359 if (fsp && (fsp->fh->fd != -1)) {
360 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
361 unix_ea_name, fsp->fsp_name));
362 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
363 ea_list->ea.value.data, ea_list->ea.value.length, 0);
365 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
366 unix_ea_name, fname));
367 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
368 ea_list->ea.value.data, ea_list->ea.value.length, 0);
374 if (errno == ENOTSUP) {
375 return NT_STATUS_EAS_NOT_SUPPORTED;
378 return map_nt_error_from_unix(errno);
384 /****************************************************************************
385 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
386 ****************************************************************************/
388 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
390 struct ea_list *ea_list_head = NULL;
393 while (offset + 2 < data_size) {
395 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
396 unsigned int namelen = CVAL(pdata,offset);
398 offset++; /* Go past the namelen byte. */
400 /* integer wrap paranioa. */
401 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
402 (offset > data_size) || (namelen > data_size) ||
403 (offset + namelen >= data_size)) {
406 /* Ensure the name is null terminated. */
407 if (pdata[offset + namelen] != '\0') {
410 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
415 offset += (namelen + 1); /* Go past the name + terminating zero. */
416 DLIST_ADD_END(ea_list_head, eal, tmp);
417 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
423 /****************************************************************************
424 Read one EA list entry from the buffer.
425 ****************************************************************************/
427 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
429 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
431 unsigned int namelen;
441 eal->ea.flags = CVAL(pdata,0);
442 namelen = CVAL(pdata,1);
443 val_len = SVAL(pdata,2);
445 if (4 + namelen + 1 + val_len > data_size) {
449 /* Ensure the name is null terminated. */
450 if (pdata[namelen + 4] != '\0') {
453 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
458 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
459 if (!eal->ea.value.data) {
463 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
465 /* Ensure we're null terminated just in case we print the value. */
466 eal->ea.value.data[val_len] = '\0';
467 /* But don't count the null. */
468 eal->ea.value.length--;
471 *pbytes_used = 4 + namelen + 1 + val_len;
474 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
475 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
480 /****************************************************************************
481 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
482 ****************************************************************************/
484 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
486 struct ea_list *ea_list_head = NULL;
488 size_t bytes_used = 0;
490 while (offset < data_size) {
492 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
498 DLIST_ADD_END(ea_list_head, eal, tmp);
499 offset += bytes_used;
505 /****************************************************************************
506 Count the total EA size needed.
507 ****************************************************************************/
509 static size_t ea_list_size(struct ea_list *ealist)
512 struct ea_list *listp;
515 for (listp = ealist; listp; listp = listp->next) {
516 push_ascii_fstring(dos_ea_name, listp->ea.name);
517 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
519 /* Add on 4 for total length. */
527 /****************************************************************************
528 Return a union of EA's from a file list and a list of names.
529 The TALLOC context for the two lists *MUST* be identical as we steal
530 memory from one list to add to another. JRA.
531 ****************************************************************************/
533 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
535 struct ea_list *nlistp, *flistp;
537 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
538 for (flistp = file_list; flistp; flistp = flistp->next) {
539 if (strequal(nlistp->ea.name, flistp->ea.name)) {
545 /* Copy the data from this entry. */
546 nlistp->ea.flags = flistp->ea.flags;
547 nlistp->ea.value = flistp->ea.value;
550 nlistp->ea.flags = 0;
551 ZERO_STRUCT(nlistp->ea.value);
555 *total_ea_len = ea_list_size(name_list);
559 /****************************************************************************
560 Send the required number of replies back.
561 We assume all fields other than the data fields are
562 set correctly for the type of call.
563 HACK ! Always assumes smb_setup field is zero.
564 ****************************************************************************/
566 int send_trans2_replies(char *outbuf,
573 /* As we are using a protocol > LANMAN1 then the max_send
574 variable must have been set in the sessetupX call.
575 This takes precedence over the max_xmit field in the
576 global struct. These different max_xmit variables should
577 be merged as this is now too confusing */
579 int data_to_send = datasize;
580 int params_to_send = paramsize;
584 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
585 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
586 int data_alignment_offset = 0;
588 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
590 set_message(outbuf,10,0,True);
592 /* If there genuinely are no parameters or data to send just send the empty packet */
594 if(params_to_send == 0 && data_to_send == 0) {
596 if (!send_smb(smbd_server_fd(),outbuf))
597 exit_server("send_trans2_replies: send_smb failed.");
601 /* When sending params and data ensure that both are nicely aligned */
602 /* Only do this alignment when there is also data to send - else
603 can cause NT redirector problems. */
605 if (((params_to_send % 4) != 0) && (data_to_send != 0))
606 data_alignment_offset = 4 - (params_to_send % 4);
608 /* Space is bufsize minus Netbios over TCP header minus SMB header */
609 /* The alignment_offset is to align the param bytes on an even byte
610 boundary. NT 4.0 Beta needs this to work correctly. */
612 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
614 /* useable_space can never be more than max_send minus the alignment offset. */
616 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
618 while (params_to_send || data_to_send) {
619 /* Calculate whether we will totally or partially fill this packet */
621 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
623 /* We can never send more than useable_space */
625 * Note that 'useable_space' does not include the alignment offsets,
626 * but we must include the alignment offsets in the calculation of
627 * the length of the data we send over the wire, as the alignment offsets
628 * are sent here. Fix from Marc_Jacobsen@hp.com.
631 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
633 set_message(outbuf, 10, total_sent_thistime, True);
635 /* Set total params and data to be sent */
636 SSVAL(outbuf,smb_tprcnt,paramsize);
637 SSVAL(outbuf,smb_tdrcnt,datasize);
639 /* Calculate how many parameters and data we can fit into
640 * this packet. Parameters get precedence
643 params_sent_thistime = MIN(params_to_send,useable_space);
644 data_sent_thistime = useable_space - params_sent_thistime;
645 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
647 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
649 /* smb_proff is the offset from the start of the SMB header to the
650 parameter bytes, however the first 4 bytes of outbuf are
651 the Netbios over TCP header. Thus use smb_base() to subtract
652 them from the calculation */
654 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
656 if(params_sent_thistime == 0)
657 SSVAL(outbuf,smb_prdisp,0);
659 /* Absolute displacement of param bytes sent in this packet */
660 SSVAL(outbuf,smb_prdisp,pp - params);
662 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
663 if(data_sent_thistime == 0) {
664 SSVAL(outbuf,smb_droff,0);
665 SSVAL(outbuf,smb_drdisp, 0);
667 /* The offset of the data bytes is the offset of the
668 parameter bytes plus the number of parameters being sent this time */
669 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
670 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
671 SSVAL(outbuf,smb_drdisp, pd - pdata);
674 /* Copy the param bytes into the packet */
676 if(params_sent_thistime)
677 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
679 /* Copy in the data bytes */
680 if(data_sent_thistime)
681 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
682 data_alignment_offset,pd,data_sent_thistime);
684 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
685 params_sent_thistime, data_sent_thistime, useable_space));
686 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
687 params_to_send, data_to_send, paramsize, datasize));
689 /* Send the packet */
691 if (!send_smb(smbd_server_fd(),outbuf))
692 exit_server("send_trans2_replies: send_smb failed.");
694 pp += params_sent_thistime;
695 pd += data_sent_thistime;
697 params_to_send -= params_sent_thistime;
698 data_to_send -= data_sent_thistime;
701 if(params_to_send < 0 || data_to_send < 0) {
702 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
703 params_to_send, data_to_send));
711 /****************************************************************************
712 Reply to a TRANSACT2_OPEN.
713 ****************************************************************************/
715 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
716 char **pparams, int total_params, char **ppdata, int total_data,
717 unsigned int max_data_bytes)
719 char *params = *pparams;
720 char *pdata = *ppdata;
725 BOOL return_additional_info;
736 SMB_STRUCT_STAT sbuf;
738 BOOL bad_path = False;
740 TALLOC_CTX *ctx = NULL;
741 struct ea_list *ea_list = NULL;
746 uint32 create_disposition;
747 uint32 create_options = 0;
750 * Ensure we have enough parameters to perform the operation.
753 if (total_params < 29) {
754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
757 flags = SVAL(params, 0);
758 deny_mode = SVAL(params, 2);
759 open_attr = SVAL(params,6);
760 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
761 if (oplock_request) {
762 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
766 return_additional_info = BITSETW(params,0);
767 open_sattr = SVAL(params, 4);
768 open_time = make_unix_date3(params+8);
770 open_ofun = SVAL(params,12);
771 open_size = IVAL(params,14);
775 return(ERROR_DOS(ERRSRV,ERRaccess));
778 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
779 if (!NT_STATUS_IS_OK(status)) {
780 return ERROR_NT(status);
783 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
784 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
785 (unsigned int)open_ofun, open_size));
787 /* XXXX we need to handle passed times, sattr and flags */
789 unix_convert(fname,conn,0,&bad_path,&sbuf);
791 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
794 if (!check_name(fname,conn)) {
795 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
798 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
803 return ERROR_DOS(ERRDOS, ERRbadaccess);
806 /* Any data in this call is an EA list. */
807 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
808 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
811 if (total_data != 4) {
812 if (total_data < 10) {
813 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
816 if (IVAL(pdata,0) > total_data) {
817 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
818 IVAL(pdata,0), (unsigned int)total_data));
819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
822 ctx = talloc_init("TRANS2_OPEN_SET_EA");
824 return ERROR_NT(NT_STATUS_NO_MEMORY);
826 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
829 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
831 } else if (IVAL(pdata,0) != 4) {
832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
835 fsp = open_file_ntcreate(conn,fname,&sbuf,
846 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
847 /* We have re-scheduled this call. */
850 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
853 size = get_file_size(sbuf);
854 fattr = dos_mode(conn,fname,&sbuf);
855 mtime = sbuf.st_mtime;
859 close_file(fsp,ERROR_CLOSE);
860 return(ERROR_DOS(ERRDOS,ERRnoaccess));
863 /* Save the requested allocation size. */
864 /* Allocate space for the file if a size hint is supplied */
865 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
866 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
867 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
868 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
869 if (fsp->is_directory) {
870 close_file(fsp,ERROR_CLOSE);
871 /* Can't set allocation size on a directory. */
872 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
874 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
875 close_file(fsp,ERROR_CLOSE);
876 return ERROR_NT(NT_STATUS_DISK_FULL);
879 /* Adjust size here to return the right size in the reply.
880 Windows does it this way. */
881 size = fsp->initial_allocation_size;
883 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
887 if (total_data && smb_action == FILE_WAS_CREATED) {
888 status = set_ea(conn, fsp, fname, ea_list);
890 if (!NT_STATUS_IS_OK(status)) {
891 close_file(fsp,ERROR_CLOSE);
892 return ERROR_NT(status);
896 /* Realloc the size of parameters and data we will return */
897 *pparams = SMB_REALLOC(*pparams, 30);
898 if(*pparams == NULL ) {
899 return ERROR_NT(NT_STATUS_NO_MEMORY);
903 SSVAL(params,0,fsp->fnum);
904 SSVAL(params,2,open_attr);
905 srv_put_dos_date2(params,4, mtime);
906 SIVAL(params,8, (uint32)size);
907 SSVAL(params,12,deny_mode);
908 SSVAL(params,14,0); /* open_type - file or directory. */
909 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
911 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
912 smb_action |= EXTENDED_OPLOCK_GRANTED;
915 SSVAL(params,18,smb_action);
918 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
920 SIVAL(params,20,inode);
921 SSVAL(params,24,0); /* Padding. */
923 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
924 SIVAL(params, 26, ea_size);
926 SIVAL(params, 26, 0);
929 /* Send the required number of replies */
930 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
935 /*********************************************************
936 Routine to check if a given string matches exactly.
937 as a special case a mask of "." does NOT match. That
938 is required for correct wildcard semantics
939 Case can be significant or not.
940 **********************************************************/
942 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
944 if (mask[0] == '.' && mask[1] == 0)
947 return strcmp(str,mask)==0;
948 if (StrCaseCmp(str,mask) != 0) {
951 if (ms_has_wild(str)) {
957 /****************************************************************************
958 Return the filetype for UNIX extensions.
959 ****************************************************************************/
961 static uint32 unix_filetype(mode_t mode)
964 return UNIX_TYPE_FILE;
965 else if(S_ISDIR(mode))
966 return UNIX_TYPE_DIR;
968 else if(S_ISLNK(mode))
969 return UNIX_TYPE_SYMLINK;
972 else if(S_ISCHR(mode))
973 return UNIX_TYPE_CHARDEV;
976 else if(S_ISBLK(mode))
977 return UNIX_TYPE_BLKDEV;
980 else if(S_ISFIFO(mode))
981 return UNIX_TYPE_FIFO;
984 else if(S_ISSOCK(mode))
985 return UNIX_TYPE_SOCKET;
988 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
989 return UNIX_TYPE_UNKNOWN;
992 /****************************************************************************
993 Map wire perms onto standard UNIX permissions. Obey share restrictions.
994 ****************************************************************************/
996 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
1000 if (perms == SMB_MODE_NO_CHANGE)
1001 return pst->st_mode;
1003 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1004 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1005 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1006 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1007 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1008 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1009 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1010 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1011 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1013 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1016 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1019 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1022 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
1023 ret &= lp_dir_mask(SNUM(conn));
1024 /* Add in force bits */
1025 ret |= lp_force_dir_mode(SNUM(conn));
1027 /* Apply mode mask */
1028 ret &= lp_create_mask(SNUM(conn));
1029 /* Add in force bits */
1030 ret |= lp_force_create_mode(SNUM(conn));
1036 /****************************************************************************
1037 Get a level dependent lanman2 dir entry.
1038 ****************************************************************************/
1040 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1041 void *inbuf, void *outbuf,
1042 char *path_mask,uint32 dirtype,int info_level,
1043 int requires_resume_key,
1044 BOOL dont_descend,char **ppdata,
1045 char *base_data, int space_remaining,
1046 BOOL *out_of_space, BOOL *got_exact_match,
1047 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1051 SMB_STRUCT_STAT sbuf;
1055 char *p, *q, *pdata = *ppdata;
1059 SMB_OFF_T file_size = 0;
1060 SMB_BIG_UINT allocation_size = 0;
1062 time_t mdate=0, adate=0, cdate=0;
1064 char *last_entry_ptr;
1066 uint32 nt_extmode; /* Used for NT connections instead of mode */
1067 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1068 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1071 *out_of_space = False;
1072 *got_exact_match = False;
1077 p = strrchr_m(path_mask,'/');
1080 pstrcpy(mask,"*.*");
1084 pstrcpy(mask, path_mask);
1089 /* Needed if we run out of space */
1090 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1091 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1094 * Due to bugs in NT client redirectors we are not using
1095 * resume keys any more - set them to zero.
1096 * Check out the related comments in findfirst/findnext.
1102 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1103 (long)conn->dirptr,curr_dirpos));
1108 pstrcpy(fname,dname);
1110 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1111 got_match = mask_match(fname, mask, conn->case_sensitive);
1113 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1116 * It turns out that NT matches wildcards against
1117 * both long *and* short names. This may explain some
1118 * of the wildcard wierdness from old DOS clients
1119 * that some people have been seeing.... JRA.
1123 pstrcpy( newname, fname);
1124 mangle_map( newname, True, False, SNUM(conn));
1125 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1126 got_match = mask_match(newname, mask, conn->case_sensitive);
1130 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1131 if (dont_descend && !isdots)
1134 pstrcpy(pathreal,conn->dirpath);
1136 pstrcat(pathreal,"/");
1137 pstrcat(pathreal,dname);
1139 if (INFO_LEVEL_IS_UNIX(info_level)) {
1140 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1141 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1142 pathreal,strerror(errno)));
1145 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1147 /* Needed to show the msdfs symlinks as
1150 if(lp_host_msdfs() &&
1151 lp_msdfs_root(SNUM(conn)) &&
1152 is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1155 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1156 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1160 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1161 pathreal,strerror(errno)));
1166 mode = dos_mode(conn,pathreal,&sbuf);
1168 if (!dir_check_ftype(conn,mode,dirtype)) {
1169 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1174 file_size = get_file_size(sbuf);
1175 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1176 mdate = sbuf.st_mtime;
1177 adate = sbuf.st_atime;
1178 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1180 if (lp_dos_filetime_resolution(SNUM(conn))) {
1187 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1191 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1195 mangle_map(fname,False,True,SNUM(conn));
1200 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1202 switch (info_level) {
1203 case SMB_FIND_INFO_STANDARD:
1204 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1205 if(requires_resume_key) {
1209 srv_put_dos_date2(p,0,cdate);
1210 srv_put_dos_date2(p,4,adate);
1211 srv_put_dos_date2(p,8,mdate);
1212 SIVAL(p,12,(uint32)file_size);
1213 SIVAL(p,16,(uint32)allocation_size);
1217 p += align_string(outbuf, p, 0);
1218 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1219 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1221 SCVAL(nameptr, -1, len - 2);
1223 SCVAL(nameptr, -1, 0);
1227 SCVAL(nameptr, -1, len - 1);
1229 SCVAL(nameptr, -1, 0);
1235 case SMB_FIND_EA_SIZE:
1236 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1237 if(requires_resume_key) {
1241 srv_put_dos_date2(p,0,cdate);
1242 srv_put_dos_date2(p,4,adate);
1243 srv_put_dos_date2(p,8,mdate);
1244 SIVAL(p,12,(uint32)file_size);
1245 SIVAL(p,16,(uint32)allocation_size);
1248 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1249 SIVAL(p,22,ea_size); /* Extended attributes */
1253 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1254 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1267 SCVAL(nameptr,0,len);
1269 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1272 case SMB_FIND_EA_LIST:
1274 struct ea_list *file_list = NULL;
1277 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1281 if(requires_resume_key) {
1285 srv_put_dos_date2(p,0,cdate);
1286 srv_put_dos_date2(p,4,adate);
1287 srv_put_dos_date2(p,8,mdate);
1288 SIVAL(p,12,(uint32)file_size);
1289 SIVAL(p,16,(uint32)allocation_size);
1291 p += 22; /* p now points to the EA area. */
1293 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1294 name_list = ea_list_union(name_list, file_list, &ea_len);
1296 /* We need to determine if this entry will fit in the space available. */
1297 /* Max string size is 255 bytes. */
1298 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1299 /* Move the dirptr back to prev_dirpos */
1300 dptr_SeekDir(conn->dirptr, prev_dirpos);
1301 *out_of_space = True;
1302 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1303 return False; /* Not finished - just out of space */
1306 /* Push the ea_data followed by the name. */
1307 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1309 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1310 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1323 SCVAL(nameptr,0,len);
1325 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1329 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1330 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1331 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1333 SIVAL(p,0,reskey); p += 4;
1334 put_long_date(p,cdate); p += 8;
1335 put_long_date(p,adate); p += 8;
1336 put_long_date(p,mdate); p += 8;
1337 put_long_date(p,mdate); p += 8;
1338 SOFF_T(p,0,file_size); p += 8;
1339 SOFF_T(p,0,allocation_size); p += 8;
1340 SIVAL(p,0,nt_extmode); p += 4;
1341 q = p; p += 4; /* q is placeholder for name length. */
1343 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1344 SIVAL(p,0,ea_size); /* Extended attributes */
1347 /* Clear the short name buffer. This is
1348 * IMPORTANT as not doing so will trigger
1349 * a Win2k client bug. JRA.
1351 if (!was_8_3 && check_mangled_names) {
1352 pstring mangled_name;
1353 pstrcpy(mangled_name, fname);
1354 mangle_map(mangled_name,True,True,SNUM(conn));
1355 mangled_name[12] = 0;
1356 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1358 memset(p + 2 + len,'\0',24 - len);
1365 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1368 SIVAL(p,0,0); /* Ensure any padding is null. */
1369 len = PTR_DIFF(p, pdata);
1370 len = (len + 3) & ~3;
1375 case SMB_FIND_FILE_DIRECTORY_INFO:
1376 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1378 SIVAL(p,0,reskey); p += 4;
1379 put_long_date(p,cdate); p += 8;
1380 put_long_date(p,adate); p += 8;
1381 put_long_date(p,mdate); p += 8;
1382 put_long_date(p,mdate); p += 8;
1383 SOFF_T(p,0,file_size); p += 8;
1384 SOFF_T(p,0,allocation_size); p += 8;
1385 SIVAL(p,0,nt_extmode); p += 4;
1386 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1389 SIVAL(p,0,0); /* Ensure any padding is null. */
1390 len = PTR_DIFF(p, pdata);
1391 len = (len + 3) & ~3;
1396 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1397 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1399 SIVAL(p,0,reskey); p += 4;
1400 put_long_date(p,cdate); p += 8;
1401 put_long_date(p,adate); p += 8;
1402 put_long_date(p,mdate); p += 8;
1403 put_long_date(p,mdate); p += 8;
1404 SOFF_T(p,0,file_size); p += 8;
1405 SOFF_T(p,0,allocation_size); p += 8;
1406 SIVAL(p,0,nt_extmode); p += 4;
1407 q = p; p += 4; /* q is placeholder for name length. */
1409 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1410 SIVAL(p,0,ea_size); /* Extended attributes */
1413 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1417 SIVAL(p,0,0); /* Ensure any padding is null. */
1418 len = PTR_DIFF(p, pdata);
1419 len = (len + 3) & ~3;
1424 case SMB_FIND_FILE_NAMES_INFO:
1425 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1427 SIVAL(p,0,reskey); p += 4;
1429 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1430 acl on a dir (tridge) */
1431 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1434 SIVAL(p,0,0); /* Ensure any padding is null. */
1435 len = PTR_DIFF(p, pdata);
1436 len = (len + 3) & ~3;
1441 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1442 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1444 SIVAL(p,0,reskey); p += 4;
1445 put_long_date(p,cdate); p += 8;
1446 put_long_date(p,adate); p += 8;
1447 put_long_date(p,mdate); p += 8;
1448 put_long_date(p,mdate); p += 8;
1449 SOFF_T(p,0,file_size); p += 8;
1450 SOFF_T(p,0,allocation_size); p += 8;
1451 SIVAL(p,0,nt_extmode); p += 4;
1452 q = p; p += 4; /* q is placeholder for name length. */
1454 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1455 SIVAL(p,0,ea_size); /* Extended attributes */
1458 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1459 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1460 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1461 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1464 SIVAL(p,0,0); /* Ensure any padding is null. */
1465 len = PTR_DIFF(p, pdata);
1466 len = (len + 3) & ~3;
1471 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1472 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1473 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1475 SIVAL(p,0,reskey); p += 4;
1476 put_long_date(p,cdate); p += 8;
1477 put_long_date(p,adate); p += 8;
1478 put_long_date(p,mdate); p += 8;
1479 put_long_date(p,mdate); p += 8;
1480 SOFF_T(p,0,file_size); p += 8;
1481 SOFF_T(p,0,allocation_size); p += 8;
1482 SIVAL(p,0,nt_extmode); p += 4;
1483 q = p; p += 4; /* q is placeholder for name length */
1485 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1486 SIVAL(p,0,ea_size); /* Extended attributes */
1489 /* Clear the short name buffer. This is
1490 * IMPORTANT as not doing so will trigger
1491 * a Win2k client bug. JRA.
1493 if (!was_8_3 && check_mangled_names) {
1494 pstring mangled_name;
1495 pstrcpy(mangled_name, fname);
1496 mangle_map(mangled_name,True,True,SNUM(conn));
1497 mangled_name[12] = 0;
1498 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1501 memset(p + 2 + len,'\0',24 - len);
1508 SSVAL(p,0,0); p += 2; /* Reserved ? */
1509 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1510 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1511 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1514 SIVAL(p,0,0); /* Ensure any padding is null. */
1515 len = PTR_DIFF(p, pdata);
1516 len = (len + 3) & ~3;
1521 /* CIFS UNIX Extension. */
1523 case SMB_FIND_FILE_UNIX:
1524 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1526 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1528 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1529 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1532 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1535 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1536 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1537 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1540 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1544 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1548 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1551 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1555 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1559 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1562 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1566 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1570 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1572 SIVAL(p,0,0); /* Ensure any padding is null. */
1574 len = PTR_DIFF(p, pdata);
1575 len = (len + 3) & ~3;
1576 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1578 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1587 if (PTR_DIFF(p,pdata) > space_remaining) {
1588 /* Move the dirptr back to prev_dirpos */
1589 dptr_SeekDir(conn->dirptr, prev_dirpos);
1590 *out_of_space = True;
1591 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1592 return False; /* Not finished - just out of space */
1595 /* Setup the last entry pointer, as an offset from base_data */
1596 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1597 /* Advance the data pointer to the next slot */
1603 /****************************************************************************
1604 Reply to a TRANS2_FINDFIRST.
1605 ****************************************************************************/
1607 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1608 char **pparams, int total_params, char **ppdata, int total_data,
1609 unsigned int max_data_bytes)
1611 /* We must be careful here that we don't return more than the
1612 allowed number of data bytes. If this means returning fewer than
1613 maxentries then so be it. We assume that the redirector has
1614 enough room for the fixed number of parameter bytes it has
1616 char *params = *pparams;
1617 char *pdata = *ppdata;
1618 uint32 dirtype = SVAL(params,0);
1619 int maxentries = SVAL(params,2);
1620 uint16 findfirst_flags = SVAL(params,4);
1621 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1622 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1623 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1624 int info_level = SVAL(params,6);
1628 int last_entry_off=0;
1632 BOOL finished = False;
1633 BOOL dont_descend = False;
1634 BOOL out_of_space = False;
1635 int space_remaining;
1636 BOOL bad_path = False;
1637 BOOL mask_contains_wcard = False;
1638 SMB_STRUCT_STAT sbuf;
1639 TALLOC_CTX *ea_ctx = NULL;
1640 struct ea_list *ea_list = NULL;
1641 NTSTATUS ntstatus = NT_STATUS_OK;
1643 if (total_params < 12) {
1644 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1647 *directory = *mask = 0;
1649 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1650 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1651 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1652 info_level, max_data_bytes));
1655 /* W2K3 seems to treat zero as 1. */
1659 switch (info_level) {
1660 case SMB_FIND_INFO_STANDARD:
1661 case SMB_FIND_EA_SIZE:
1662 case SMB_FIND_EA_LIST:
1663 case SMB_FIND_FILE_DIRECTORY_INFO:
1664 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1665 case SMB_FIND_FILE_NAMES_INFO:
1666 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1667 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1668 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1670 case SMB_FIND_FILE_UNIX:
1671 if (!lp_unix_extensions()) {
1672 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1676 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1679 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1680 if (!NT_STATUS_IS_OK(ntstatus)) {
1681 return ERROR_NT(ntstatus);
1684 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1686 unix_convert(directory,conn,0,&bad_path,&sbuf);
1688 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1690 if(!check_name(directory,conn)) {
1691 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1694 p = strrchr_m(directory,'/');
1696 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1697 if((directory[0] == '.') && (directory[1] == '\0')) {
1699 mask_contains_wcard = True;
1701 pstrcpy(mask,directory);
1703 pstrcpy(directory,"./");
1709 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1711 if (info_level == SMB_FIND_EA_LIST) {
1714 if (total_data < 4) {
1715 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1718 ea_size = IVAL(pdata,0);
1719 if (ea_size != total_data) {
1720 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1721 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1722 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1725 if (!lp_ea_support(SNUM(conn))) {
1726 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1729 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1730 return ERROR_NT(NT_STATUS_NO_MEMORY);
1733 /* Pull out the list of names. */
1734 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1736 talloc_destroy(ea_ctx);
1737 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1741 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1742 if(*ppdata == NULL ) {
1743 talloc_destroy(ea_ctx);
1744 return ERROR_NT(NT_STATUS_NO_MEMORY);
1748 /* Realloc the params space */
1749 *pparams = SMB_REALLOC(*pparams, 10);
1750 if (*pparams == NULL) {
1751 talloc_destroy(ea_ctx);
1752 return ERROR_NT(NT_STATUS_NO_MEMORY);
1756 /* Save the wildcard match and attribs we are using on this directory -
1757 needed as lanman2 assumes these are being saved between calls */
1759 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1761 talloc_destroy(ea_ctx);
1762 return(UNIXERROR(ERRDOS,ERRbadfile));
1765 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1767 /* We don't need to check for VOL here as this is returned by
1768 a different TRANS2 call. */
1770 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1771 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1772 dont_descend = True;
1775 space_remaining = max_data_bytes;
1776 out_of_space = False;
1778 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1779 BOOL got_exact_match = False;
1781 /* this is a heuristic to avoid seeking the dirptr except when
1782 absolutely necessary. It allows for a filename of about 40 chars */
1783 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1784 out_of_space = True;
1787 finished = !get_lanman2_dir_entry(conn,
1789 mask,dirtype,info_level,
1790 requires_resume_key,dont_descend,
1791 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1792 &last_entry_off, ea_list, ea_ctx);
1795 if (finished && out_of_space)
1798 if (!finished && !out_of_space)
1802 * As an optimisation if we know we aren't looking
1803 * for a wildcard name (ie. the name matches the wildcard exactly)
1804 * then we can finish on any (first) match.
1805 * This speeds up large directory searches. JRA.
1811 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1814 talloc_destroy(ea_ctx);
1816 /* Check if we can close the dirptr */
1817 if(close_after_first || (finished && close_if_end)) {
1818 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1819 dptr_close(&dptr_num);
1823 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1824 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1825 * the protocol level is less than NT1. Tested with smbclient. JRA.
1826 * This should fix the OS/2 client bug #2335.
1829 if(numentries == 0) {
1830 dptr_close(&dptr_num);
1831 if (Protocol < PROTOCOL_NT1) {
1832 return ERROR_DOS(ERRDOS,ERRnofiles);
1834 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1838 /* At this point pdata points to numentries directory entries. */
1840 /* Set up the return parameter block */
1841 SSVAL(params,0,dptr_num);
1842 SSVAL(params,2,numentries);
1843 SSVAL(params,4,finished);
1844 SSVAL(params,6,0); /* Never an EA error */
1845 SSVAL(params,8,last_entry_off);
1847 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1849 if ((! *directory) && dptr_path(dptr_num))
1850 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1852 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1853 smb_fn_name(CVAL(inbuf,smb_com)),
1854 mask, directory, dirtype, numentries ) );
1857 * Force a name mangle here to ensure that the
1858 * mask as an 8.3 name is top of the mangled cache.
1859 * The reasons for this are subtle. Don't remove
1860 * this code unless you know what you are doing
1861 * (see PR#13758). JRA.
1864 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1865 mangle_map(mask, True, True, SNUM(conn));
1870 /****************************************************************************
1871 Reply to a TRANS2_FINDNEXT.
1872 ****************************************************************************/
1874 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1875 char **pparams, int total_params, char **ppdata, int total_data,
1876 unsigned int max_data_bytes)
1878 /* We must be careful here that we don't return more than the
1879 allowed number of data bytes. If this means returning fewer than
1880 maxentries then so be it. We assume that the redirector has
1881 enough room for the fixed number of parameter bytes it has
1883 char *params = *pparams;
1884 char *pdata = *ppdata;
1885 int dptr_num = SVAL(params,0);
1886 int maxentries = SVAL(params,2);
1887 uint16 info_level = SVAL(params,4);
1888 uint32 resume_key = IVAL(params,6);
1889 uint16 findnext_flags = SVAL(params,10);
1890 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1891 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1892 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1893 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1894 BOOL mask_contains_wcard = False;
1895 pstring resume_name;
1901 int i, last_entry_off=0;
1902 BOOL finished = False;
1903 BOOL dont_descend = False;
1904 BOOL out_of_space = False;
1905 int space_remaining;
1906 TALLOC_CTX *ea_ctx = NULL;
1907 struct ea_list *ea_list = NULL;
1908 NTSTATUS ntstatus = NT_STATUS_OK;
1910 if (total_params < 12) {
1911 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1914 *mask = *directory = *resume_name = 0;
1916 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1917 if (!NT_STATUS_IS_OK(ntstatus)) {
1918 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1919 complain (it thinks we're asking for the directory above the shared
1920 path or an invalid name). Catch this as the resume name is only compared, never used in
1921 a file access. JRA. */
1922 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1923 pstrcpy(resume_name, "..");
1924 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1925 pstrcpy(resume_name, ".");
1927 return ERROR_NT(ntstatus);
1931 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1932 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1933 resume_key = %d resume name = %s continue=%d level = %d\n",
1934 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1935 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1938 /* W2K3 seems to treat zero as 1. */
1942 switch (info_level) {
1943 case SMB_FIND_INFO_STANDARD:
1944 case SMB_FIND_EA_SIZE:
1945 case SMB_FIND_EA_LIST:
1946 case SMB_FIND_FILE_DIRECTORY_INFO:
1947 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1948 case SMB_FIND_FILE_NAMES_INFO:
1949 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1950 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1951 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1953 case SMB_FIND_FILE_UNIX:
1954 if (!lp_unix_extensions()) {
1955 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1959 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1962 if (info_level == SMB_FIND_EA_LIST) {
1965 if (total_data < 4) {
1966 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1969 ea_size = IVAL(pdata,0);
1970 if (ea_size != total_data) {
1971 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1972 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1973 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1976 if (!lp_ea_support(SNUM(conn))) {
1977 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1980 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1981 return ERROR_NT(NT_STATUS_NO_MEMORY);
1984 /* Pull out the list of names. */
1985 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1987 talloc_destroy(ea_ctx);
1988 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1992 *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1993 if(*ppdata == NULL) {
1994 talloc_destroy(ea_ctx);
1995 return ERROR_NT(NT_STATUS_NO_MEMORY);
2000 /* Realloc the params space */
2001 *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2002 if(*pparams == NULL ) {
2003 talloc_destroy(ea_ctx);
2004 return ERROR_NT(NT_STATUS_NO_MEMORY);
2009 /* Check that the dptr is valid */
2010 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2011 talloc_destroy(ea_ctx);
2012 return ERROR_DOS(ERRDOS,ERRnofiles);
2015 string_set(&conn->dirpath,dptr_path(dptr_num));
2017 /* Get the wildcard mask from the dptr */
2018 if((p = dptr_wcard(dptr_num))== NULL) {
2019 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2020 talloc_destroy(ea_ctx);
2021 return ERROR_DOS(ERRDOS,ERRnofiles);
2025 pstrcpy(directory,conn->dirpath);
2027 /* Get the attr mask from the dptr */
2028 dirtype = dptr_attr(dptr_num);
2030 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2031 dptr_num, mask, dirtype,
2033 dptr_TellDir(conn->dirptr)));
2035 /* We don't need to check for VOL here as this is returned by
2036 a different TRANS2 call. */
2038 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2039 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2040 dont_descend = True;
2043 space_remaining = max_data_bytes;
2044 out_of_space = False;
2047 * Seek to the correct position. We no longer use the resume key but
2048 * depend on the last file name instead.
2051 if(*resume_name && !continue_bit) {
2054 long current_pos = 0;
2056 * Remember, mangle_map is called by
2057 * get_lanman2_dir_entry(), so the resume name
2058 * could be mangled. Ensure we check the unmangled name.
2061 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2062 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2066 * Fix for NT redirector problem triggered by resume key indexes
2067 * changing between directory scans. We now return a resume key of 0
2068 * and instead look for the filename to continue from (also given
2069 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2070 * findfirst/findnext (as is usual) then the directory pointer
2071 * should already be at the correct place.
2074 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2075 } /* end if resume_name && !continue_bit */
2077 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2078 BOOL got_exact_match = False;
2080 /* this is a heuristic to avoid seeking the dirptr except when
2081 absolutely necessary. It allows for a filename of about 40 chars */
2082 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2083 out_of_space = True;
2086 finished = !get_lanman2_dir_entry(conn,
2088 mask,dirtype,info_level,
2089 requires_resume_key,dont_descend,
2090 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2091 &last_entry_off, ea_list, ea_ctx);
2094 if (finished && out_of_space)
2097 if (!finished && !out_of_space)
2101 * As an optimisation if we know we aren't looking
2102 * for a wildcard name (ie. the name matches the wildcard exactly)
2103 * then we can finish on any (first) match.
2104 * This speeds up large directory searches. JRA.
2110 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2113 talloc_destroy(ea_ctx);
2115 /* Check if we can close the dirptr */
2116 if(close_after_request || (finished && close_if_end)) {
2117 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2118 dptr_close(&dptr_num); /* This frees up the saved mask */
2121 /* Set up the return parameter block */
2122 SSVAL(params,0,numentries);
2123 SSVAL(params,2,finished);
2124 SSVAL(params,4,0); /* Never an EA error */
2125 SSVAL(params,6,last_entry_off);
2127 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2129 if ((! *directory) && dptr_path(dptr_num))
2130 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2132 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2133 smb_fn_name(CVAL(inbuf,smb_com)),
2134 mask, directory, dirtype, numentries ) );
2139 /****************************************************************************
2140 Reply to a TRANS2_QFSINFO (query filesystem info).
2141 ****************************************************************************/
2143 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2144 char **pparams, int total_params, char **ppdata, int total_data,
2145 unsigned int max_data_bytes)
2147 char *pdata = *ppdata;
2148 char *params = *pparams;
2149 uint16 info_level = SVAL(params,0);
2152 char *vname = volume_label(SNUM(conn));
2153 int snum = SNUM(conn);
2154 char *fstype = lp_fstype(SNUM(conn));
2157 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2159 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2160 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2161 return ERROR_DOS(ERRSRV,ERRinvdevice);
2164 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2165 if (*ppdata == NULL ) {
2166 return ERROR_NT(NT_STATUS_NO_MEMORY);
2170 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2172 switch (info_level) {
2173 case SMB_INFO_ALLOCATION:
2175 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2177 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2178 return(UNIXERROR(ERRHRD,ERRgeneral));
2181 block_size = lp_block_size(snum);
2182 if (bsize < block_size) {
2183 SMB_BIG_UINT factor = block_size/bsize;
2188 if (bsize > block_size) {
2189 SMB_BIG_UINT factor = bsize/block_size;
2194 bytes_per_sector = 512;
2195 sectors_per_unit = bsize/bytes_per_sector;
2197 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2198 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2199 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2201 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2202 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2203 SIVAL(pdata,l1_cUnit,dsize);
2204 SIVAL(pdata,l1_cUnitAvail,dfree);
2205 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2209 case SMB_INFO_VOLUME:
2210 /* Return volume name */
2212 * Add volume serial number - hash of a combination of
2213 * the called hostname and the service name.
2215 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2217 * Win2k3 and previous mess this up by sending a name length
2218 * one byte short. I believe only older clients (OS/2 Win9x) use
2219 * this call so try fixing this by adding a terminating null to
2220 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2222 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2223 SCVAL(pdata,l2_vol_cch,len);
2224 data_len = l2_vol_szVolLabel + len;
2225 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2226 (unsigned)st.st_ctime, len, vname));
2229 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2230 case SMB_FS_ATTRIBUTE_INFORMATION:
2233 #if defined(HAVE_SYS_QUOTAS)
2234 quota_flag = FILE_VOLUME_QUOTAS;
2237 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2238 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2239 quota_flag); /* FS ATTRIBUTES */
2241 SIVAL(pdata,4,255); /* Max filename component length */
2242 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2243 and will think we can't do long filenames */
2244 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2246 data_len = 12 + len;
2249 case SMB_QUERY_FS_LABEL_INFO:
2250 case SMB_FS_LABEL_INFORMATION:
2251 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2256 case SMB_QUERY_FS_VOLUME_INFO:
2257 case SMB_FS_VOLUME_INFORMATION:
2260 * Add volume serial number - hash of a combination of
2261 * the called hostname and the service name.
2263 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2264 (str_checksum(get_local_machine_name())<<16));
2266 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2267 SIVAL(pdata,12,len);
2269 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2270 (int)strlen(vname),vname, lp_servicename(snum)));
2273 case SMB_QUERY_FS_SIZE_INFO:
2274 case SMB_FS_SIZE_INFORMATION:
2276 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2278 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2279 return(UNIXERROR(ERRHRD,ERRgeneral));
2281 block_size = lp_block_size(snum);
2282 if (bsize < block_size) {
2283 SMB_BIG_UINT factor = block_size/bsize;
2288 if (bsize > block_size) {
2289 SMB_BIG_UINT factor = bsize/block_size;
2294 bytes_per_sector = 512;
2295 sectors_per_unit = bsize/bytes_per_sector;
2296 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2297 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2298 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2299 SBIG_UINT(pdata,0,dsize);
2300 SBIG_UINT(pdata,8,dfree);
2301 SIVAL(pdata,16,sectors_per_unit);
2302 SIVAL(pdata,20,bytes_per_sector);
2306 case SMB_FS_FULL_SIZE_INFORMATION:
2308 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2310 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2311 return(UNIXERROR(ERRHRD,ERRgeneral));
2313 block_size = lp_block_size(snum);
2314 if (bsize < block_size) {
2315 SMB_BIG_UINT factor = block_size/bsize;
2320 if (bsize > block_size) {
2321 SMB_BIG_UINT factor = bsize/block_size;
2326 bytes_per_sector = 512;
2327 sectors_per_unit = bsize/bytes_per_sector;
2328 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2329 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2330 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2331 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2332 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2333 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2334 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2335 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2339 case SMB_QUERY_FS_DEVICE_INFO:
2340 case SMB_FS_DEVICE_INFORMATION:
2342 SIVAL(pdata,0,0); /* dev type */
2343 SIVAL(pdata,4,0); /* characteristics */
2346 #ifdef HAVE_SYS_QUOTAS
2347 case SMB_FS_QUOTA_INFORMATION:
2349 * what we have to send --metze:
2351 * Unknown1: 24 NULL bytes
2352 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2353 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2354 * Quota Flags: 2 byte :
2355 * Unknown3: 6 NULL bytes
2359 * details for Quota Flags:
2361 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2362 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2363 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2364 * 0x0001 Enable Quotas: enable quota for this fs
2368 /* we need to fake up a fsp here,
2369 * because its not send in this call
2372 SMB_NTQUOTA_STRUCT quotas;
2375 ZERO_STRUCT(quotas);
2381 if (current_user.ut.uid != 0) {
2382 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2383 lp_servicename(SNUM(conn)),conn->user));
2384 return ERROR_DOS(ERRDOS,ERRnoaccess);
2387 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2388 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2389 return ERROR_DOS(ERRSRV,ERRerror);
2394 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2396 /* Unknown1 24 NULL bytes*/
2397 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2398 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2399 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2401 /* Default Soft Quota 8 bytes */
2402 SBIG_UINT(pdata,24,quotas.softlim);
2404 /* Default Hard Quota 8 bytes */
2405 SBIG_UINT(pdata,32,quotas.hardlim);
2407 /* Quota flag 2 bytes */
2408 SSVAL(pdata,40,quotas.qflags);
2410 /* Unknown3 6 NULL bytes */
2416 #endif /* HAVE_SYS_QUOTAS */
2417 case SMB_FS_OBJECTID_INFORMATION:
2422 * Query the version and capabilities of the CIFS UNIX extensions
2426 case SMB_QUERY_CIFS_UNIX_INFO:
2427 if (!lp_unix_extensions()) {
2428 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2431 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2432 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2433 /* We have POSIX ACLs, pathname and locking capability. */
2434 #if defined(DEVELOPER) /* Not quite finished yet... */
2435 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2436 CIFS_UNIX_POSIX_ACLS_CAP|
2437 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2438 CIFS_UNIX_FCNTL_LOCKS_CAP)));
2440 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2441 CIFS_UNIX_POSIX_ACLS_CAP|
2442 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2447 case SMB_QUERY_POSIX_FS_INFO:
2450 vfs_statvfs_struct svfs;
2452 if (!lp_unix_extensions()) {
2453 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2456 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2460 SIVAL(pdata,0,svfs.OptimalTransferSize);
2461 SIVAL(pdata,4,svfs.BlockSize);
2462 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2463 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2464 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2465 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2466 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2467 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2468 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2470 } else if (rc == EOPNOTSUPP) {
2471 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2472 #endif /* EOPNOTSUPP */
2474 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2475 return ERROR_DOS(ERRSRV,ERRerror);
2480 case SMB_MAC_QUERY_FS_INFO:
2482 * Thursby MAC extension... ONLY on NTFS filesystems
2483 * once we do streams then we don't need this
2485 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2487 SIVAL(pdata,84,0x100); /* Don't support mac... */
2492 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2496 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2498 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2503 /****************************************************************************
2504 Reply to a TRANS2_SETFSINFO (set filesystem info).
2505 ****************************************************************************/
2507 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2508 char **pparams, int total_params, char **ppdata, int total_data,
2509 unsigned int max_data_bytes)
2511 char *pdata = *ppdata;
2512 char *params = *pparams;
2516 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2519 if (total_params < 4) {
2520 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2522 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2525 info_level = SVAL(params,2);
2527 switch(info_level) {
2528 case SMB_SET_CIFS_UNIX_INFO:
2530 uint16 client_unix_major;
2531 uint16 client_unix_minor;
2532 uint32 client_unix_cap_low;
2533 uint32 client_unix_cap_high;
2535 if (!lp_unix_extensions()) {
2536 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2539 /* There should be 12 bytes of capabilities set. */
2540 if (total_data < 8) {
2541 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2543 client_unix_major = SVAL(pdata,0);
2544 client_unix_minor = SVAL(pdata,2);
2545 client_unix_cap_low = IVAL(pdata,4);
2546 client_unix_cap_high = IVAL(pdata,8);
2547 /* Just print these values for now. */
2548 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2549 cap_low = 0x%x, cap_high = 0x%x\n",
2550 (unsigned int)client_unix_major,
2551 (unsigned int)client_unix_minor,
2552 (unsigned int)client_unix_cap_low,
2553 (unsigned int)client_unix_cap_high ));
2555 /* Here is where we must switch to posix pathname processing... */
2556 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2557 lp_set_posix_pathnames();
2558 mangle_change_to_posix();
2560 #if defined(DEVELOPER)
2561 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2562 lp_set_posix_cifsx_locktype(POSIX_LOCK);
2567 case SMB_FS_QUOTA_INFORMATION:
2569 files_struct *fsp = NULL;
2570 SMB_NTQUOTA_STRUCT quotas;
2572 ZERO_STRUCT(quotas);
2575 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2576 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2577 lp_servicename(SNUM(conn)),conn->user));
2578 return ERROR_DOS(ERRSRV,ERRaccess);
2581 /* note: normaly there're 48 bytes,
2582 * but we didn't use the last 6 bytes for now
2585 fsp = file_fsp(params,0);
2586 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2587 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2588 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2591 if (total_data < 42) {
2592 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2594 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2597 /* unknown_1 24 NULL bytes in pdata*/
2599 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2600 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2601 #ifdef LARGE_SMB_OFF_T
2602 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2603 #else /* LARGE_SMB_OFF_T */
2604 if ((IVAL(pdata,28) != 0)&&
2605 ((quotas.softlim != 0xFFFFFFFF)||
2606 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2607 /* more than 32 bits? */
2608 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2610 #endif /* LARGE_SMB_OFF_T */
2612 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2613 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2614 #ifdef LARGE_SMB_OFF_T
2615 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2616 #else /* LARGE_SMB_OFF_T */
2617 if ((IVAL(pdata,36) != 0)&&
2618 ((quotas.hardlim != 0xFFFFFFFF)||
2619 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2620 /* more than 32 bits? */
2621 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2623 #endif /* LARGE_SMB_OFF_T */
2625 /* quota_flags 2 bytes **/
2626 quotas.qflags = SVAL(pdata,40);
2628 /* unknown_2 6 NULL bytes follow*/
2630 /* now set the quotas */
2631 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2632 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2633 return ERROR_DOS(ERRSRV,ERRerror);
2639 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2641 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2646 * sending this reply works fine,
2647 * but I'm not sure it's the same
2648 * like windows do...
2651 outsize = set_message(outbuf,10,0,True);
2656 /****************************************************************************
2657 Utility function to set bad path error.
2658 ****************************************************************************/
2660 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2662 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2663 err, (int)bad_path ));
2667 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2669 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2672 return UNIXERROR(def_class,def_code);
2675 #if defined(HAVE_POSIX_ACLS)
2676 /****************************************************************************
2677 Utility function to count the number of entries in a POSIX acl.
2678 ****************************************************************************/
2680 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2682 unsigned int ace_count = 0;
2683 int entry_id = SMB_ACL_FIRST_ENTRY;
2684 SMB_ACL_ENTRY_T entry;
2686 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2688 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2689 entry_id = SMB_ACL_NEXT_ENTRY;
2696 /****************************************************************************
2697 Utility function to marshall a POSIX acl into wire format.
2698 ****************************************************************************/
2700 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2702 int entry_id = SMB_ACL_FIRST_ENTRY;
2703 SMB_ACL_ENTRY_T entry;
2705 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2706 SMB_ACL_TAG_T tagtype;
2707 SMB_ACL_PERMSET_T permset;
2708 unsigned char perms = 0;
2709 unsigned int own_grp;
2712 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2713 entry_id = SMB_ACL_NEXT_ENTRY;
2716 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2717 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2721 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2722 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2726 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2727 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2728 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2730 SCVAL(pdata,1,perms);
2733 case SMB_ACL_USER_OBJ:
2734 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2735 own_grp = (unsigned int)pst->st_uid;
2736 SIVAL(pdata,2,own_grp);
2741 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2743 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2745 own_grp = (unsigned int)*puid;
2746 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2747 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2748 SIVAL(pdata,2,own_grp);
2752 case SMB_ACL_GROUP_OBJ:
2753 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2754 own_grp = (unsigned int)pst->st_gid;
2755 SIVAL(pdata,2,own_grp);
2760 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2762 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2764 own_grp = (unsigned int)*pgid;
2765 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2766 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2767 SIVAL(pdata,2,own_grp);
2772 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2773 SIVAL(pdata,2,0xFFFFFFFF);
2774 SIVAL(pdata,6,0xFFFFFFFF);
2777 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2778 SIVAL(pdata,2,0xFFFFFFFF);
2779 SIVAL(pdata,6,0xFFFFFFFF);
2782 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2785 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2792 /****************************************************************************
2793 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2794 file name or file id).
2795 ****************************************************************************/
2797 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2798 unsigned int tran_call,
2799 char **pparams, int total_params, char **ppdata, int total_data,
2800 unsigned int max_data_bytes)
2802 char *params = *pparams;
2803 char *pdata = *ppdata;
2807 SMB_OFF_T file_size=0;
2808 SMB_BIG_UINT allocation_size=0;
2809 unsigned int data_size = 0;
2810 unsigned int param_size = 2;
2811 SMB_STRUCT_STAT sbuf;
2812 pstring fname, dos_fname;
2816 char *lock_data = NULL;
2818 BOOL bad_path = False;
2819 BOOL delete_pending = False;
2822 files_struct *fsp = NULL;
2823 TALLOC_CTX *data_ctx = NULL;
2824 struct ea_list *ea_list = NULL;
2825 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2828 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2832 if (tran_call == TRANSACT2_QFILEINFO) {
2833 if (total_params < 4) {
2834 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2837 fsp = file_fsp(params,0);
2838 info_level = SVAL(params,2);
2840 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2842 if(fsp && (fsp->fake_file_handle)) {
2844 * This is actually for the QUOTA_FAKE_FILE --metze
2847 pstrcpy(fname, fsp->fsp_name);
2848 /* We know this name is ok, it's already passed the checks. */
2850 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2852 * This is actually a QFILEINFO on a directory
2853 * handle (returned from an NT SMB). NT5.0 seems
2854 * to do this call. JRA.
2856 /* We know this name is ok, it's already passed the checks. */
2857 pstrcpy(fname, fsp->fsp_name);
2859 if (INFO_LEVEL_IS_UNIX(info_level)) {
2860 /* Always do lstat for UNIX calls. */
2861 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2862 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2863 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2865 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2866 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2867 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2870 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2873 * Original code - this is an open file.
2875 CHECK_FSP(fsp,conn);
2877 pstrcpy(fname, fsp->fsp_name);
2878 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2879 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2880 return(UNIXERROR(ERRDOS,ERRbadfid));
2882 pos = fsp->fh->position_information;
2883 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2884 access_mask = fsp->access_mask;
2887 NTSTATUS status = NT_STATUS_OK;
2890 if (total_params < 6) {
2891 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2894 info_level = SVAL(params,0);
2896 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2898 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2899 if (!NT_STATUS_IS_OK(status)) {
2900 return ERROR_NT(status);
2903 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2905 unix_convert(fname,conn,0,&bad_path,&sbuf);
2907 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2909 if (!check_name(fname,conn)) {
2910 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2911 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2914 if (INFO_LEVEL_IS_UNIX(info_level)) {
2915 /* Always do lstat for UNIX calls. */
2916 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2917 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2918 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2920 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2921 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2922 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2925 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2926 if (delete_pending) {
2927 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2931 nlink = sbuf.st_nlink;
2933 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2934 /* NTFS does not seem to count ".." */
2938 if ((nlink > 0) && delete_pending) {
2942 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2943 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2946 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2947 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2949 p = strrchr_m(fname,'/');
2955 mode = dos_mode(conn,fname,&sbuf);
2957 mode = FILE_ATTRIBUTE_NORMAL;
2959 fullpathname = fname;
2961 file_size = get_file_size(sbuf);
2963 /* Pull out any data sent here before we realloc. */
2964 switch (info_level) {
2965 case SMB_INFO_QUERY_EAS_FROM_LIST:
2967 /* Pull any EA list from the data portion. */
2970 if (total_data < 4) {
2971 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2973 ea_size = IVAL(pdata,0);
2975 if (total_data > 0 && ea_size != total_data) {
2976 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2977 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2978 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2981 if (!lp_ea_support(SNUM(conn))) {
2982 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2985 if ((data_ctx = talloc_init("ea_list")) == NULL) {
2986 return ERROR_NT(NT_STATUS_NO_MEMORY);
2989 /* Pull out the list of names. */
2990 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
2992 talloc_destroy(data_ctx);
2993 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2997 #if defined(DEVELOPER)
2998 case SMB_QUERY_POSIX_LOCK:
3000 if (fsp == NULL || fsp->fh->fd == -1) {
3001 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3004 if (total_data != POSIX_LOCK_DATA_SIZE) {
3005 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3008 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3009 return ERROR_NT(NT_STATUS_NO_MEMORY);
3012 /* Copy the lock range data. */
3013 lock_data = talloc_memdup(data_ctx, pdata, total_data);
3015 talloc_destroy(data_ctx);
3016 return ERROR_NT(NT_STATUS_NO_MEMORY);
3024 *pparams = SMB_REALLOC(*pparams,2);
3025 if (*pparams == NULL) {
3026 talloc_destroy(data_ctx);
3027 return ERROR_NT(NT_STATUS_NO_MEMORY);
3031 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3032 *ppdata = SMB_REALLOC(*ppdata, data_size);
3033 if (*ppdata == NULL ) {
3034 talloc_destroy(data_ctx);
3035 return ERROR_NT(NT_STATUS_NO_MEMORY);
3039 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3041 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3044 if (fsp->pending_modtime) {
3045 /* the pending modtime overrides the current modtime */
3046 sbuf.st_mtime = fsp->pending_modtime;
3049 /* Do we have this path open ? */
3050 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3051 if (fsp1 && fsp1->pending_modtime) {
3052 /* the pending modtime overrides the current modtime */
3053 sbuf.st_mtime = fsp1->pending_modtime;
3055 if (fsp1 && fsp1->initial_allocation_size) {
3056 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3060 if (lp_dos_filetime_resolution(SNUM(conn))) {
3062 sbuf.st_atime &= ~1;
3063 sbuf.st_ctime &= ~1;
3064 sbuf.st_mtime &= ~1;
3067 /* NT expects the name to be in an exact form of the *full*
3068 filename. See the trans2 torture test */
3069 if (strequal(base_name,".")) {
3070 pstrcpy(dos_fname, "\\");
3072 pstr_sprintf(dos_fname, "\\%s", fname);
3073 string_replace(dos_fname, '/', '\\');
3076 switch (info_level) {
3077 case SMB_INFO_STANDARD:
3078 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3080 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3081 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3082 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3083 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3084 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3085 SSVAL(pdata,l1_attrFile,mode);
3088 case SMB_INFO_QUERY_EA_SIZE:
3090 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3091 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3093 srv_put_dos_date2(pdata,0,c_time);
3094 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3095 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3096 SIVAL(pdata,12,(uint32)file_size);
3097 SIVAL(pdata,16,(uint32)allocation_size);
3098 SSVAL(pdata,20,mode);
3099 SIVAL(pdata,22,ea_size);
3103 case SMB_INFO_IS_NAME_VALID:
3104 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3105 if (tran_call == TRANSACT2_QFILEINFO) {
3106 /* os/2 needs this ? really ?*/
3107 return ERROR_DOS(ERRDOS,ERRbadfunc);
3113 case SMB_INFO_QUERY_EAS_FROM_LIST:
3115 size_t total_ea_len = 0;
3116 struct ea_list *ea_file_list = NULL;
3118 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3120 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3121 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3123 if (!ea_list || (total_ea_len > data_size)) {
3124 talloc_destroy(data_ctx);
3126 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3130 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3131 talloc_destroy(data_ctx);
3135 case SMB_INFO_QUERY_ALL_EAS:
3137 /* We have data_size bytes to put EA's into. */
3138 size_t total_ea_len = 0;
3140 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3142 data_ctx = talloc_init("ea_ctx");
3144 return ERROR_NT(NT_STATUS_NO_MEMORY);
3147 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3148 if (!ea_list || (total_ea_len > data_size)) {
3149 talloc_destroy(data_ctx);
3151 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3155 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3156 talloc_destroy(data_ctx);
3160 case SMB_FILE_BASIC_INFORMATION:
3161 case SMB_QUERY_FILE_BASIC_INFO:
3163 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3164 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3165 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3167 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3171 put_long_date(pdata,c_time);
3172 put_long_date(pdata+8,sbuf.st_atime);
3173 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3174 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3175 SIVAL(pdata,32,mode);
3177 DEBUG(5,("SMB_QFBI - "));
3179 time_t create_time = c_time;
3180 DEBUG(5,("create: %s ", ctime(&create_time)));
3182 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3183 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3184 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3185 DEBUG(5,("mode: %x\n", mode));
3188 case SMB_FILE_STANDARD_INFORMATION:
3189 case SMB_QUERY_FILE_STANDARD_INFO:
3191 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3193 SOFF_T(pdata,0,allocation_size);
3194 SOFF_T(pdata,8,file_size);
3195 SIVAL(pdata,16,nlink);
3196 SCVAL(pdata,20,delete_pending?1:0);
3197 SCVAL(pdata,21,(mode&aDIR)?1:0);
3198 SSVAL(pdata,22,0); /* Padding. */
3201 case SMB_FILE_EA_INFORMATION:
3202 case SMB_QUERY_FILE_EA_INFO:
3204 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3205 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3207 SIVAL(pdata,0,ea_size);
3211 /* Get the 8.3 name - used if NT SMB was negotiated. */
3212 case SMB_QUERY_FILE_ALT_NAME_INFO:
3213 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3217 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3218 pstrcpy(short_name,base_name);
3219 /* Mangle if not already 8.3 */
3220 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3221 mangle_map(short_name,True,True,SNUM(conn));
3223 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3224 data_size = 4 + len;
3229 case SMB_QUERY_FILE_NAME_INFO:
3231 this must be *exactly* right for ACLs on mapped drives to work
3233 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3234 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3235 data_size = 4 + len;
3239 case SMB_FILE_ALLOCATION_INFORMATION:
3240 case SMB_QUERY_FILE_ALLOCATION_INFO:
3241 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3243 SOFF_T(pdata,0,allocation_size);
3246 case SMB_FILE_END_OF_FILE_INFORMATION:
3247 case SMB_QUERY_FILE_END_OF_FILEINFO:
3248 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3250 SOFF_T(pdata,0,file_size);
3253 case SMB_QUERY_FILE_ALL_INFO:
3254 case SMB_FILE_ALL_INFORMATION:
3256 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3257 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3258 put_long_date(pdata,c_time);
3259 put_long_date(pdata+8,sbuf.st_atime);
3260 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3261 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3262 SIVAL(pdata,32,mode);
3263 SIVAL(pdata,36,0); /* padding. */
3265 SOFF_T(pdata,0,allocation_size);
3266 SOFF_T(pdata,8,file_size);
3267 SIVAL(pdata,16,nlink);
3268 SCVAL(pdata,20,delete_pending);
3269 SCVAL(pdata,21,(mode&aDIR)?1:0);
3272 SIVAL(pdata,0,ea_size);
3273 pdata += 4; /* EA info */
3274 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3277 data_size = PTR_DIFF(pdata,(*ppdata));
3280 case SMB_FILE_INTERNAL_INFORMATION:
3281 /* This should be an index number - looks like
3284 I think this causes us to fail the IFSKIT
3285 BasicFileInformationTest. -tpot */
3287 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3288 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3289 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3293 case SMB_FILE_ACCESS_INFORMATION:
3294 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3295 SIVAL(pdata,0,access_mask);
3299 case SMB_FILE_NAME_INFORMATION:
3300 /* Pathname with leading '\'. */
3303 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3304 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3305 SIVAL(pdata,0,byte_len);
3306 data_size = 4 + byte_len;
3310 case SMB_FILE_DISPOSITION_INFORMATION:
3311 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3313 SCVAL(pdata,0,delete_pending);
3316 case SMB_FILE_POSITION_INFORMATION:
3317 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3319 SOFF_T(pdata,0,pos);
3322 case SMB_FILE_MODE_INFORMATION:
3323 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3324 SIVAL(pdata,0,mode);
3328 case SMB_FILE_ALIGNMENT_INFORMATION:
3329 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3330 SIVAL(pdata,0,0); /* No alignment needed. */
3336 * NT4 server just returns "invalid query" to this - if we try to answer
3337 * it then NTws gets a BSOD! (tridge).
3338 * W2K seems to want this. JRA.
3340 case SMB_QUERY_FILE_STREAM_INFO:
3342 case SMB_FILE_STREAM_INFORMATION:
3343 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3347 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3348 SIVAL(pdata,0,0); /* ??? */
3349 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3350 SOFF_T(pdata,8,file_size);
3351 SIVAL(pdata,16,allocation_size);
3352 SIVAL(pdata,20,0); /* ??? */
3353 data_size = 24 + byte_len;
3357 case SMB_QUERY_COMPRESSION_INFO:
3358 case SMB_FILE_COMPRESSION_INFORMATION:
3359 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3360 SOFF_T(pdata,0,file_size);
3361 SIVAL(pdata,8,0); /* ??? */
3362 SIVAL(pdata,12,0); /* ??? */
3366 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3367 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3368 put_long_date(pdata,c_time);
3369 put_long_date(pdata+8,sbuf.st_atime);
3370 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3371 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3372 SIVAL(pdata,32,allocation_size);
3373 SOFF_T(pdata,40,file_size);
3374 SIVAL(pdata,48,mode);
3375 SIVAL(pdata,52,0); /* ??? */
3379 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3380 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3381 SIVAL(pdata,0,mode);
3387 * CIFS UNIX Extensions.
3390 case SMB_QUERY_FILE_UNIX_BASIC:
3392 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3393 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3395 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3398 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3401 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3402 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3403 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3406 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3410 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3414 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3417 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3421 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3425 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3428 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3432 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3435 data_size = PTR_DIFF(pdata,(*ppdata));
3439 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3441 for (i=0; i<100; i++)
3442 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3448 case SMB_QUERY_FILE_UNIX_LINK:
3452 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3454 if(!S_ISLNK(sbuf.st_mode))
3455 return(UNIXERROR(ERRSRV,ERRbadlink));
3457 return(UNIXERROR(ERRDOS,ERRbadlink));
3459 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3461 return(UNIXERROR(ERRDOS,ERRnoaccess));
3463 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3465 data_size = PTR_DIFF(pdata,(*ppdata));
3470 #if defined(HAVE_POSIX_ACLS)
3471 case SMB_QUERY_POSIX_ACL:
3473 SMB_ACL_T file_acl = NULL;
3474 SMB_ACL_T def_acl = NULL;
3475 uint16 num_file_acls = 0;
3476 uint16 num_def_acls = 0;
3478 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3479 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3481 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3484 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3485 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3487 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3490 if (S_ISDIR(sbuf.st_mode)) {
3491 if (fsp && fsp->is_directory) {
3492 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3494 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3496 def_acl = free_empty_sys_acl(conn, def_acl);
3499 num_file_acls = count_acl_entries(conn, file_acl);
3500 num_def_acls = count_acl_entries(conn, def_acl);
3502 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3503 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3505 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3506 SMB_POSIX_ACL_HEADER_SIZE) ));
3508 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3511 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3513 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3516 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3517 SSVAL(pdata,2,num_file_acls);
3518 SSVAL(pdata,4,num_def_acls);
3519 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3521 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3524 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3526 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3528 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_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);
3539 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3542 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3544 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3550 #if defined(DEVELOPER)
3551 case SMB_QUERY_POSIX_LOCK:
3553 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3555 SMB_BIG_UINT offset;
3557 enum brl_type lock_type;
3559 if (total_data != POSIX_LOCK_DATA_SIZE) {
3560 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3563 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3564 case POSIX_LOCK_TYPE_READ:
3565 lock_type = READ_LOCK;
3567 case POSIX_LOCK_TYPE_WRITE:
3568 lock_type = WRITE_LOCK;
3570 case POSIX_LOCK_TYPE_UNLOCK:
3572 /* There's no point in asking for an unlock... */
3573 talloc_destroy(data_ctx);
3574 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3577 lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3578 #if defined(HAVE_LONGLONG)
3579 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3580 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3581 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3582 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3583 #else /* HAVE_LONGLONG */
3584 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3585 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3586 #endif /* HAVE_LONGLONG */
3588 status = query_lock(fsp,
3595 if (ERROR_WAS_LOCK_DENIED(status)) {
3596 /* Here we need to report who has it locked... */
3597 data_size = POSIX_LOCK_DATA_SIZE;
3599 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3600 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3601 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3602 #if defined(HAVE_LONGLONG)
3603 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3604 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3605 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3606 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3607 #else /* HAVE_LONGLONG */
3608 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3609 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3610 #endif /* HAVE_LONGLONG */
3612 } else if (NT_STATUS_IS_OK(status)) {
3613 /* For success we just return a copy of what we sent
3614 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3615 data_size = POSIX_LOCK_DATA_SIZE;
3616 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3617 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3619 return ERROR_NT(status);
3626 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3629 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3634 /****************************************************************************
3635 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3637 ****************************************************************************/
3639 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3641 BOOL bad_path_oldname = False;
3642 BOOL bad_path_newname = False;
3643 SMB_STRUCT_STAT sbuf1, sbuf2;
3644 pstring last_component_oldname;
3645 pstring last_component_newname;
3646 NTSTATUS status = NT_STATUS_OK;
3652 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3653 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3656 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3657 if (bad_path_oldname) {
3658 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3661 /* Quick check for "." and ".." */
3662 if (last_component_oldname[0] == '.') {
3663 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3664 return NT_STATUS_OBJECT_NAME_INVALID;
3668 /* source must already exist. */
3669 if (!VALID_STAT(sbuf1)) {
3670 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3673 if (!check_name(oldname,conn)) {
3674 return NT_STATUS_ACCESS_DENIED;
3677 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3678 if (bad_path_newname) {
3679 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3682 /* Quick check for "." and ".." */
3683 if (last_component_newname[0] == '.') {
3684 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3685 return NT_STATUS_OBJECT_NAME_INVALID;
3689 /* Disallow if newname already exists. */
3690 if (VALID_STAT(sbuf2)) {
3691 return NT_STATUS_OBJECT_NAME_COLLISION;
3694 if (!check_name(newname,conn)) {
3695 return NT_STATUS_ACCESS_DENIED;
3698 /* No links from a directory. */
3699 if (S_ISDIR(sbuf1.st_mode)) {
3700 return NT_STATUS_FILE_IS_A_DIRECTORY;
3703 /* Ensure this is within the share. */
3704 if (!reduce_name(conn, oldname) != 0)
3705 return NT_STATUS_ACCESS_DENIED;
3707 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3709 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3710 status = map_nt_error_from_unix(errno);
3711 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3712 nt_errstr(status), newname, oldname));
3718 /****************************************************************************
3719 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3720 ****************************************************************************/
3722 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3723 unsigned int tran_call,
3724 char **pparams, int total_params, char **ppdata, int total_data,
3725 unsigned int max_data_bytes)
3727 char *params = *pparams;
3728 char *pdata = *ppdata;
3733 SMB_STRUCT_STAT sbuf;
3736 BOOL bad_path = False;
3737 files_struct *fsp = NULL;
3738 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3739 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3740 mode_t unixmode = 0;
3741 NTSTATUS status = NT_STATUS_OK;
3744 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3749 if (tran_call == TRANSACT2_SETFILEINFO) {
3750 if (total_params < 4) {
3751 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3754 fsp = file_fsp(params,0);
3755 info_level = SVAL(params,2);
3757 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3759 * This is actually a SETFILEINFO on a directory
3760 * handle (returned from an NT SMB). NT5.0 seems
3761 * to do this call. JRA.
3763 pstrcpy(fname, fsp->fsp_name);
3764 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3765 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3766 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3768 } else if (fsp && fsp->print_file) {
3770 * Doing a DELETE_ON_CLOSE should cancel a print job.
3772 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3773 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3775 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3778 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3781 return (UNIXERROR(ERRDOS,ERRbadpath));
3784 * Original code - this is an open file.
3786 CHECK_FSP(fsp,conn);
3788 pstrcpy(fname, fsp->fsp_name);
3791 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3792 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3793 return(UNIXERROR(ERRDOS,ERRbadfid));
3798 if (total_params < 6) {
3799 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3802 info_level = SVAL(params,0);
3803 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3804 if (!NT_STATUS_IS_OK(status)) {
3805 return ERROR_NT(status);
3807 unix_convert(fname,conn,0,&bad_path,&sbuf);
3809 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3813 * For CIFS UNIX extensions the target name may not exist.
3816 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3817 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3818 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3821 if(!check_name(fname, conn)) {
3822 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3827 if (!CAN_WRITE(conn))
3828 return ERROR_DOS(ERRSRV,ERRaccess);
3830 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3831 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3834 if (VALID_STAT(sbuf))
3835 unixmode = sbuf.st_mode;
3837 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3838 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3840 /* Realloc the parameter size */
3841 *pparams = SMB_REALLOC(*pparams,2);
3842 if (*pparams == NULL) {
3843 return ERROR_NT(NT_STATUS_NO_MEMORY);
3849 if (fsp && fsp->pending_modtime) {
3850 /* the pending modtime overrides the current modtime */
3851 sbuf.st_mtime = fsp->pending_modtime;
3854 size = get_file_size(sbuf);
3855 tvs.modtime = sbuf.st_mtime;
3856 tvs.actime = sbuf.st_atime;
3857 dosmode = dos_mode(conn,fname,&sbuf);
3858 unixmode = sbuf.st_mode;
3860 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3861 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3863 switch (info_level) {
3864 case SMB_INFO_STANDARD:
3866 if (total_data < 12) {
3867 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3871 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3873 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3877 case SMB_INFO_SET_EA:
3879 struct ea_list *ea_list = NULL;
3880 TALLOC_CTX *ctx = NULL;
3882 if (total_data < 10) {
3884 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3885 length. They seem to have no effect. Bug #3212. JRA */
3887 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3888 /* We're done. We only get EA info in this call. */
3890 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3894 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3897 if (IVAL(pdata,0) > total_data) {
3898 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3899 IVAL(pdata,0), (unsigned int)total_data));
3900 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3903 ctx = talloc_init("SMB_INFO_SET_EA");
3905 return ERROR_NT(NT_STATUS_NO_MEMORY);
3907 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3909 talloc_destroy(ctx);
3910 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3912 status = set_ea(conn, fsp, fname, ea_list);
3913 talloc_destroy(ctx);
3915 if (!NT_STATUS_IS_OK(status)) {
3916 return ERROR_NT(status);
3919 /* We're done. We only get EA info in this call. */
3921 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3926 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3927 /* XXXX um, i don't think this is right.
3928 it's also not in the cifs6.txt spec.
3930 case SMB_INFO_QUERY_EAS_FROM_LIST:
3931 if (total_data < 28)
3932 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3934 tvs.actime = make_unix_date2(pdata+8);
3935 tvs.modtime = make_unix_date2(pdata+12);
3936 size = IVAL(pdata,16);
3937 dosmode = IVAL(pdata,24);
3940 /* XXXX nor this. not in cifs6.txt, either. */
3941 case SMB_INFO_QUERY_ALL_EAS:
3942 if (total_data < 28)
3943 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3945 tvs.actime = make_unix_date2(pdata+8);
3946 tvs.modtime = make_unix_date2(pdata+12);
3947 size = IVAL(pdata,16);
3948 dosmode = IVAL(pdata,24);
3952 case SMB_SET_FILE_BASIC_INFO:
3953 case SMB_FILE_BASIC_INFORMATION:
3955 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3957 time_t changed_time;
3959 if (total_data < 36) {
3960 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3963 /* Ignore create time at offset pdata. */
3966 tvs.actime = interpret_long_date(pdata+8);
3968 write_time = interpret_long_date(pdata+16);
3969 changed_time = interpret_long_date(pdata+24);
3971 tvs.modtime = MIN(write_time, changed_time);
3973 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3974 tvs.modtime = write_time;
3976 /* Prefer a defined time to an undefined one. */
3977 if (null_mtime(tvs.modtime)) {
3978 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3982 dosmode = IVAL(pdata,32);
3986 case SMB_FILE_ALLOCATION_INFORMATION:
3987 case SMB_SET_FILE_ALLOCATION_INFO:
3990 SMB_BIG_UINT allocation_size;
3992 if (total_data < 8) {
3993 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3996 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3997 #ifdef LARGE_SMB_OFF_T
3998 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3999 #else /* LARGE_SMB_OFF_T */
4000 if (IVAL(pdata,4) != 0) {
4001 /* more than 32 bits? */
4002 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4004 #endif /* LARGE_SMB_OFF_T */
4005 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4006 fname, (double)allocation_size ));
4008 if (allocation_size) {
4009 allocation_size = smb_roundup(conn, allocation_size);
4012 if(allocation_size != get_file_size(sbuf)) {
4013 SMB_STRUCT_STAT new_sbuf;
4015 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4016 fname, (double)allocation_size ));
4019 files_struct *new_fsp = NULL;
4021 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4023 FILE_SHARE_READ|FILE_SHARE_WRITE,
4026 FILE_ATTRIBUTE_NORMAL,
4030 if (new_fsp == NULL) {
4031 return(UNIXERROR(ERRDOS,ERRbadpath));
4033 ret = vfs_allocate_file_space(new_fsp, allocation_size);
4034 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4035 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4036 new_fsp->fnum, strerror(errno)));
4039 close_file(new_fsp,NORMAL_CLOSE);
4041 ret = vfs_allocate_file_space(fsp, allocation_size);
4042 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4043 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4044 fsp->fnum, strerror(errno)));
4049 return ERROR_NT(NT_STATUS_DISK_FULL);
4051 /* Allocate can truncate size... */
4052 size = get_file_size(new_sbuf);
4058 case SMB_FILE_END_OF_FILE_INFORMATION:
4059 case SMB_SET_FILE_END_OF_FILE_INFO:
4061 if (total_data < 8) {
4062 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4065 size = IVAL(pdata,0);
4066 #ifdef LARGE_SMB_OFF_T
4067 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4068 #else /* LARGE_SMB_OFF_T */
4069 if (IVAL(pdata,4) != 0) {
4070 /* more than 32 bits? */
4071 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4073 #endif /* LARGE_SMB_OFF_T */
4074 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4078 case SMB_FILE_DISPOSITION_INFORMATION:
4079 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4081 BOOL delete_on_close;
4083 if (total_data < 1) {
4084 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4087 delete_on_close = (CVAL(pdata,0) ? True : False);
4089 /* Just ignore this set on a path. */
4090 if (tran_call != TRANSACT2_SETFILEINFO)
4094 return(UNIXERROR(ERRDOS,ERRbadfid));
4096 status = can_set_delete_on_close(fsp, delete_on_close,
4099 if (!NT_STATUS_IS_OK(status)) {
4100 return ERROR_NT(status);
4103 /* The set is across all open files on this dev/inode pair. */
4104 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4105 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4109 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4113 case SMB_FILE_POSITION_INFORMATION:
4115 SMB_BIG_UINT position_information;
4117 if (total_data < 8) {
4118 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4121 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4122 #ifdef LARGE_SMB_OFF_T
4123 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4124 #else /* LARGE_SMB_OFF_T */
4125 if (IVAL(pdata,4) != 0) {
4126 /* more than 32 bits? */
4127 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4129 #endif /* LARGE_SMB_OFF_T */
4130 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4131 fname, (double)position_information ));
4133 fsp->fh->position_information = position_information;
4136 /* We're done. We only get position info in this call. */
4138 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4142 /* From tridge Samba4 :
4143 * MODE_INFORMATION in setfileinfo (I have no
4144 * idea what "mode information" on a file is - it takes a value of 0,
4145 * 2, 4 or 6. What could it be?).
4148 case SMB_FILE_MODE_INFORMATION:
4152 if (total_data < 4) {
4153 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4155 mode = IVAL(pdata,0);
4156 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4157 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4160 /* We're done. We only get mode info in this call. */
4162 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4167 * CIFS UNIX extensions.
4170 case SMB_SET_FILE_UNIX_BASIC:
4172 uint32 raw_unixmode;
4174 if (total_data < 100) {
4175 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4178 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4179 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4180 size=IVAL(pdata,0); /* first 8 Bytes are size */
4181 #ifdef LARGE_SMB_OFF_T
4182 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4183 #else /* LARGE_SMB_OFF_T */
4184 if (IVAL(pdata,4) != 0) {
4185 /* more than 32 bits? */
4186 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4188 #endif /* LARGE_SMB_OFF_T */
4190 pdata+=24; /* ctime & st_blocks are not changed */
4191 tvs.actime = interpret_long_date(pdata); /* access_time */
4192 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4194 set_owner = (uid_t)IVAL(pdata,0);
4196 set_grp = (gid_t)IVAL(pdata,0);
4198 raw_unixmode = IVAL(pdata,28);
4199 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4200 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4202 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4203 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4204 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4206 if (!VALID_STAT(sbuf)) {
4209 * The only valid use of this is to create character and block
4210 * devices, and named pipes. This is deprecated (IMHO) and
4211 * a new info level should be used for mknod. JRA.
4214 uint32 file_type = IVAL(pdata,0);
4215 #if defined(HAVE_MAKEDEV)
4216 uint32 dev_major = IVAL(pdata,4);
4217 uint32 dev_minor = IVAL(pdata,12);
4220 uid_t myuid = geteuid();
4221 gid_t mygid = getegid();
4222 SMB_DEV_T dev = (SMB_DEV_T)0;
4224 if (tran_call == TRANSACT2_SETFILEINFO)
4225 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4227 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4228 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4231 #if defined(HAVE_MAKEDEV)
4232 dev = makedev(dev_major, dev_minor);
4235 /* We can only create as the owner/group we are. */
4237 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4238 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4239 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4240 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4242 switch (file_type) {
4243 #if defined(S_IFIFO)
4244 case UNIX_TYPE_FIFO:
4245 unixmode |= S_IFIFO;
4248 #if defined(S_IFSOCK)
4249 case UNIX_TYPE_SOCKET:
4250 unixmode |= S_IFSOCK;
4253 #if defined(S_IFCHR)
4254 case UNIX_TYPE_CHARDEV:
4255 unixmode |= S_IFCHR;
4258 #if defined(S_IFBLK)
4259 case UNIX_TYPE_BLKDEV:
4260 unixmode |= S_IFBLK;
4264 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4267 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4268 0%o for file %s\n", (double)dev, unixmode, fname ));
4270 /* Ok - do the mknod. */
4271 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4272 return(UNIXERROR(ERRDOS,ERRnoaccess));
4274 inherit_access_acl(conn, fname, unixmode);
4277 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4282 * Deal with the UNIX specific mode set.
4285 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4286 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4287 (unsigned int)unixmode, fname ));
4288 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4289 return(UNIXERROR(ERRDOS,ERRnoaccess));
4293 * Deal with the UNIX specific uid set.
4296 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4297 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4298 (unsigned int)set_owner, fname ));
4299 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4300 return(UNIXERROR(ERRDOS,ERRnoaccess));
4304 * Deal with the UNIX specific gid set.
4307 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4308 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4309 (unsigned int)set_owner, fname ));
4310 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4311 return(UNIXERROR(ERRDOS,ERRnoaccess));
4316 case SMB_SET_FILE_UNIX_LINK:
4318 pstring link_target;
4319 char *newname = fname;
4321 /* Set a symbolic link. */
4322 /* Don't allow this if follow links is false. */
4324 if (!lp_symlinks(SNUM(conn)))
4325 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4327 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4329 /* !widelinks forces the target path to be within the share. */
4330 /* This means we can interpret the target as a pathname. */
4331 if (!lp_widelinks(SNUM(conn))) {
4333 char *last_dirp = NULL;
4335 unix_format(link_target);
4336 if (*link_target == '/') {
4337 /* No absolute paths allowed. */
4338 return(UNIXERROR(ERRDOS,ERRnoaccess));
4340 pstrcpy(rel_name, newname);
4341 last_dirp = strrchr_m(rel_name, '/');
4343 last_dirp[1] = '\0';
4345 pstrcpy(rel_name, "./");
4347 pstrcat(rel_name, link_target);
4349 if (!check_name(rel_name, conn)) {
4350 return(UNIXERROR(ERRDOS,ERRnoaccess));
4354 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4355 fname, link_target ));
4357 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4358 return(UNIXERROR(ERRDOS,ERRnoaccess));
4360 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4364 case SMB_SET_FILE_UNIX_HLINK:
4367 char *newname = fname;
4369 /* Set a hard link. */
4370 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4371 if (!NT_STATUS_IS_OK(status)) {
4372 return ERROR_NT(status);
4375 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4378 status = hardlink_internals(conn, oldname, newname);
4379 if (!NT_STATUS_IS_OK(status)) {
4380 return ERROR_NT(status);
4384 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4388 case SMB_FILE_RENAME_INFORMATION:
4397 if (total_data < 12) {
4398 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4401 overwrite = (CVAL(pdata,0) ? True : False);
4402 root_fid = IVAL(pdata,4);
4403 len = IVAL(pdata,8);
4404 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4405 if (!NT_STATUS_IS_OK(status)) {
4406 return ERROR_NT(status);
4409 /* Check the new name has no '/' characters. */
4410 if (strchr_m(newname, '/'))
4411 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4413 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4415 /* Create the base directory. */
4416 pstrcpy(base_name, fname);
4417 p = strrchr_m(base_name, '/');
4420 /* Append the new name. */
4421 pstrcat(base_name, "/");
4422 pstrcat(base_name, newname);
4425 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4426 fsp->fnum, fsp->fsp_name, base_name ));
4427 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4429 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4431 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4433 if (!NT_STATUS_IS_OK(status)) {
4434 return ERROR_NT(status);
4436 process_pending_change_notify_queue((time_t)0);
4438 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4442 #if defined(HAVE_POSIX_ACLS)
4443 case SMB_SET_POSIX_ACL:
4445 uint16 posix_acl_version;
4446 uint16 num_file_acls;
4447 uint16 num_def_acls;
4448 BOOL valid_file_acls = True;
4449 BOOL valid_def_acls = True;
4451 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4452 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4454 posix_acl_version = SVAL(pdata,0);
4455 num_file_acls = SVAL(pdata,2);
4456 num_def_acls = SVAL(pdata,4);
4458 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4459 valid_file_acls = False;
4463 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4464 valid_def_acls = False;
4468 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4469 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4472 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4473 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4474 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4477 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4478 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4479 return(UNIXERROR(ERRDOS,ERRnoaccess));
4482 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4483 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4484 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4485 return(UNIXERROR(ERRDOS,ERRnoaccess));
4489 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4494 #if defined(DEVELOPER)
4495 case SMB_SET_POSIX_LOCK:
4498 SMB_BIG_UINT offset;
4501 enum brl_type lock_type;
4504 if (fsp == NULL || fsp->fh->fd == -1) {
4505 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4508 if (total_data != POSIX_LOCK_DATA_SIZE) {
4509 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4512 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4513 case POSIX_LOCK_TYPE_READ:
4514 lock_type = READ_LOCK;
4516 case POSIX_LOCK_TYPE_WRITE:
4517 /* Return the right POSIX-mappable error code for files opened read-only. */
4518 if (!fsp->can_write) {
4519 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4521 lock_type = WRITE_LOCK;
4523 case POSIX_LOCK_TYPE_UNLOCK:
4524 lock_type = UNLOCK_LOCK;
4527 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4530 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4531 lock_blocking = False;
4532 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4533 lock_blocking = True;
4535 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4538 lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4539 #if defined(HAVE_LONGLONG)
4540 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4541 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4542 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4543 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4544 #else /* HAVE_LONGLONG */
4545 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4546 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4547 #endif /* HAVE_LONGLONG */
4549 if (lock_type == UNLOCK_LOCK) {
4550 status = do_unlock(fsp,
4556 status = do_lock(fsp,
4564 /* TODO: Deal with rescheduling blocking lock fail here... */
4565 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4567 * A blocking lock was requested. Package up
4568 * this smb into a queued request and push it
4569 * onto the blocking lock queue.
4571 if(push_blocking_lock_request(inbuf, length,
4573 -1, /* infinite timeout. */
4585 if (!NT_STATUS_IS_OK(status)) {
4586 return ERROR_NT(status);
4590 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4596 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4599 /* get some defaults (no modifications) if any info is zero or -1. */
4600 if (null_mtime(tvs.actime)) {
4601 tvs.actime = sbuf.st_atime;
4604 if (null_mtime(tvs.modtime)) {
4605 tvs.modtime = sbuf.st_mtime;
4608 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4609 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4610 DEBUG(6,("size: %.0f ", (double)size));
4613 if (S_ISDIR(sbuf.st_mode))
4619 DEBUG(6,("dosmode: %x\n" , dosmode));
4621 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4622 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4623 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4624 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4627 * Only do this test if we are not explicitly
4628 * changing the size of a file.
4631 size = get_file_size(sbuf);
4635 * Try and set the times, size and mode of this file -
4636 * if they are different from the current values
4639 /* check the mode isn't different, before changing it */
4640 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4642 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4644 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4645 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4646 return(UNIXERROR(ERRDOS,ERRnoaccess));
4651 if (size != get_file_size(sbuf)) {
4655 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4656 fname, (double)size ));
4659 files_struct *new_fsp = NULL;
4661 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4663 FILE_SHARE_READ|FILE_SHARE_WRITE,
4666 FILE_ATTRIBUTE_NORMAL,
4670 if (new_fsp == NULL) {
4671 return(UNIXERROR(ERRDOS,ERRbadpath));
4673 ret = vfs_set_filelen(new_fsp, size);
4674 close_file(new_fsp,NORMAL_CLOSE);
4676 ret = vfs_set_filelen(fsp, size);
4680 return (UNIXERROR(ERRHRD,ERRdiskfull));
4685 * Finally the times.
4687 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4690 * This was a setfileinfo on an open file.
4691 * NT does this a lot. We also need to
4692 * set the time here, as it can be read by
4693 * FindFirst/FindNext and with the patch for bug #2045
4694 * in smbd/fileio.c it ensures that this timestamp is
4695 * kept sticky even after a write. We save the request
4696 * away and will set it on file close and after a write. JRA.
4699 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4700 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4701 fsp_set_pending_modtime(fsp, tvs.modtime);
4705 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4707 if(file_utime(conn, fname, &tvs)!=0) {
4708 return(UNIXERROR(ERRDOS,ERRnoaccess));
4713 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4718 /****************************************************************************
4719 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4720 ****************************************************************************/
4722 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4723 char **pparams, int total_params, char **ppdata, int total_data,
4724 unsigned int max_data_bytes)
4726 char *params = *pparams;
4727 char *pdata = *ppdata;
4730 SMB_STRUCT_STAT sbuf;
4731 BOOL bad_path = False;
4732 NTSTATUS status = NT_STATUS_OK;
4733 TALLOC_CTX *ctx = NULL;
4734 struct ea_list *ea_list = NULL;
4736 if (!CAN_WRITE(conn))
4737 return ERROR_DOS(ERRSRV,ERRaccess);
4739 if (total_params < 4) {
4740 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4743 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
4744 if (!NT_STATUS_IS_OK(status)) {
4745 return ERROR_NT(status);
4748 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4750 unix_convert(directory,conn,0,&bad_path,&sbuf);
4752 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4755 /* Any data in this call is an EA list. */
4756 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4757 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4761 * OS/2 workplace shell seems to send SET_EA requests of "null"
4762 * length (4 bytes containing IVAL 4).
4763 * They seem to have no effect. Bug #3212. JRA.
4766 if (total_data != 4) {
4767 if (total_data < 10) {
4768 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4771 if (IVAL(pdata,0) > total_data) {
4772 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4773 IVAL(pdata,0), (unsigned int)total_data));
4774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4777 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4779 return ERROR_NT(NT_STATUS_NO_MEMORY);
4781 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4783 talloc_destroy(ctx);
4784 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4786 } else if (IVAL(pdata,0) != 4) {
4787 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4790 if (check_name(directory,conn)) {
4791 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4795 talloc_destroy(ctx);
4796 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4797 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4800 /* Try and set any given EA. */
4802 status = set_ea(conn, NULL, directory, ea_list);
4803 talloc_destroy(ctx);
4804 if (!NT_STATUS_IS_OK(status)) {
4805 return ERROR_NT(status);
4809 /* Realloc the parameter and data sizes */
4810 *pparams = SMB_REALLOC(*pparams,2);
4811 if(*pparams == NULL) {
4812 return ERROR_NT(NT_STATUS_NO_MEMORY);
4818 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4823 /****************************************************************************
4824 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4825 We don't actually do this - we just send a null response.
4826 ****************************************************************************/
4828 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4829 char **pparams, int total_params, char **ppdata, int total_data,
4830 unsigned int max_data_bytes)
4832 static uint16 fnf_handle = 257;
4833 char *params = *pparams;
4836 if (total_params < 6) {
4837 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4840 info_level = SVAL(params,4);
4841 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4843 switch (info_level) {
4848 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4851 /* Realloc the parameter and data sizes */
4852 *pparams = SMB_REALLOC(*pparams,6);
4853 if (*pparams == NULL) {
4854 return ERROR_NT(NT_STATUS_NO_MEMORY);
4858 SSVAL(params,0,fnf_handle);
4859 SSVAL(params,2,0); /* No changes */
4860 SSVAL(params,4,0); /* No EA errors */
4867 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4872 /****************************************************************************
4873 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4874 changes). Currently this does nothing.
4875 ****************************************************************************/
4877 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4878 char **pparams, int total_params, char **ppdata, int total_data,
4879 unsigned int max_data_bytes)
4881 char *params = *pparams;
4883 DEBUG(3,("call_trans2findnotifynext\n"));
4885 /* Realloc the parameter and data sizes */
4886 *pparams = SMB_REALLOC(*pparams,4);
4887 if (*pparams == NULL) {
4888 return ERROR_NT(NT_STATUS_NO_MEMORY);
4892 SSVAL(params,0,0); /* No changes */
4893 SSVAL(params,2,0); /* No EA errors */
4895 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4900 /****************************************************************************
4901 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4902 ****************************************************************************/
4904 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4905 char **pparams, int total_params, char **ppdata, int total_data,
4906 unsigned int max_data_bytes)
4908 char *params = *pparams;
4911 int max_referral_level;
4913 DEBUG(10,("call_trans2getdfsreferral\n"));
4915 if (total_params < 2) {
4916 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4919 max_referral_level = SVAL(params,0);
4921 if(!lp_host_msdfs())
4922 return ERROR_DOS(ERRDOS,ERRbadfunc);
4924 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4925 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4926 return UNIXERROR(ERRDOS,ERRbadfile);
4928 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4929 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4934 #define LMCAT_SPL 0x53
4935 #define LMFUNC_GETJOBID 0x60
4937 /****************************************************************************
4938 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4939 ****************************************************************************/
4941 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4942 char **pparams, int total_params, char **ppdata, int total_data,
4943 unsigned int max_data_bytes)
4945 char *pdata = *ppdata;
4946 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4948 /* check for an invalid fid before proceeding */
4951 return(ERROR_DOS(ERRDOS,ERRbadfid));
4953 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4954 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4955 *ppdata = SMB_REALLOC(*ppdata, 32);
4956 if (*ppdata == NULL) {
4957 return ERROR_NT(NT_STATUS_NO_MEMORY);
4961 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4962 CAN ACCEPT THIS IN UNICODE. JRA. */
4964 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4965 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4966 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4967 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4970 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4971 return ERROR_DOS(ERRSRV,ERRerror);
4975 /****************************************************************************
4976 Reply to a SMBfindclose (stop trans2 directory search).
4977 ****************************************************************************/
4979 int reply_findclose(connection_struct *conn,
4980 char *inbuf,char *outbuf,int length,int bufsize)
4983 int dptr_num=SVALS(inbuf,smb_vwv0);
4984 START_PROFILE(SMBfindclose);
4986 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4988 dptr_close(&dptr_num);
4990 outsize = set_message(outbuf,0,0,False);
4992 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4994 END_PROFILE(SMBfindclose);
4998 /****************************************************************************
4999 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5000 ****************************************************************************/
5002 int reply_findnclose(connection_struct *conn,
5003 char *inbuf,char *outbuf,int length,int bufsize)
5007 START_PROFILE(SMBfindnclose);
5009 dptr_num = SVAL(inbuf,smb_vwv0);
5011 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5013 /* We never give out valid handles for a
5014 findnotifyfirst - so any dptr_num is ok here.
5017 outsize = set_message(outbuf,0,0,False);
5019 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5021 END_PROFILE(SMBfindnclose);
5025 int handle_trans2(connection_struct *conn,
5026 struct trans_state *state,
5027 char *inbuf, char *outbuf, int size, int bufsize)
5031 if (Protocol >= PROTOCOL_NT1) {
5032 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5035 /* Now we must call the relevant TRANS2 function */
5036 switch(state->call) {
5037 case TRANSACT2_OPEN:
5039 START_PROFILE_NESTED(Trans2_open);
5040 outsize = call_trans2open(
5041 conn, inbuf, outbuf, bufsize,
5042 &state->param, state->total_param,
5043 &state->data, state->total_data,
5044 state->max_data_return);
5045 END_PROFILE_NESTED(Trans2_open);
5049 case TRANSACT2_FINDFIRST:
5051 START_PROFILE_NESTED(Trans2_findfirst);
5052 outsize = call_trans2findfirst(
5053 conn, inbuf, outbuf, bufsize,
5054 &state->param, state->total_param,
5055 &state->data, state->total_data,
5056 state->max_data_return);
5057 END_PROFILE_NESTED(Trans2_findfirst);
5061 case TRANSACT2_FINDNEXT:
5063 START_PROFILE_NESTED(Trans2_findnext);
5064 outsize = call_trans2findnext(
5065 conn, inbuf, outbuf, size, bufsize,
5066 &state->param, state->total_param,
5067 &state->data, state->total_data,
5068 state->max_data_return);
5069 END_PROFILE_NESTED(Trans2_findnext);
5073 case TRANSACT2_QFSINFO:
5075 START_PROFILE_NESTED(Trans2_qfsinfo);
5076 outsize = call_trans2qfsinfo(
5077 conn, inbuf, outbuf, size, bufsize,
5078 &state->param, state->total_param,
5079 &state->data, state->total_data,
5080 state->max_data_return);
5081 END_PROFILE_NESTED(Trans2_qfsinfo);
5085 case TRANSACT2_SETFSINFO:
5087 START_PROFILE_NESTED(Trans2_setfsinfo);
5088 outsize = call_trans2setfsinfo(
5089 conn, inbuf, outbuf, size, bufsize,
5090 &state->param, state->total_param,
5091 &state->data, state->total_data,
5092 state->max_data_return);
5093 END_PROFILE_NESTED(Trans2_setfsinfo);
5097 case TRANSACT2_QPATHINFO:
5098 case TRANSACT2_QFILEINFO:
5100 START_PROFILE_NESTED(Trans2_qpathinfo);
5101 outsize = call_trans2qfilepathinfo(
5102 conn, inbuf, outbuf, size, bufsize, state->call,
5103 &state->param, state->total_param,
5104 &state->data, state->total_data,
5105 state->max_data_return);
5106 END_PROFILE_NESTED(Trans2_qpathinfo);
5110 case TRANSACT2_SETPATHINFO:
5111 case TRANSACT2_SETFILEINFO:
5113 START_PROFILE_NESTED(Trans2_setpathinfo);
5114 outsize = call_trans2setfilepathinfo(
5115 conn, inbuf, outbuf, size, bufsize, state->call,
5116 &state->param, state->total_param,
5117 &state->data, state->total_data,
5118 state->max_data_return);
5119 END_PROFILE_NESTED(Trans2_setpathinfo);
5123 case TRANSACT2_FINDNOTIFYFIRST:
5125 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5126 outsize = call_trans2findnotifyfirst(
5127 conn, inbuf, outbuf, size, bufsize,
5128 &state->param, state->total_param,
5129 &state->data, state->total_data,
5130 state->max_data_return);
5131 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5135 case TRANSACT2_FINDNOTIFYNEXT:
5137 START_PROFILE_NESTED(Trans2_findnotifynext);
5138 outsize = call_trans2findnotifynext(
5139 conn, inbuf, outbuf, size, bufsize,
5140 &state->param, state->total_param,
5141 &state->data, state->total_data,
5142 state->max_data_return);
5143 END_PROFILE_NESTED(Trans2_findnotifynext);
5147 case TRANSACT2_MKDIR:
5149 START_PROFILE_NESTED(Trans2_mkdir);
5150 outsize = call_trans2mkdir(
5151 conn, inbuf, outbuf, size, bufsize,
5152 &state->param, state->total_param,
5153 &state->data, state->total_data,
5154 state->max_data_return);
5155 END_PROFILE_NESTED(Trans2_mkdir);
5159 case TRANSACT2_GET_DFS_REFERRAL:
5161 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5162 outsize = call_trans2getdfsreferral(
5163 conn, inbuf, outbuf, size, bufsize,
5164 &state->param, state->total_param,
5165 &state->data, state->total_data,
5166 state->max_data_return);
5167 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5171 case TRANSACT2_IOCTL:
5173 START_PROFILE_NESTED(Trans2_ioctl);
5174 outsize = call_trans2ioctl(
5175 conn, inbuf, outbuf, size, bufsize,
5176 &state->param, state->total_param,
5177 &state->data, state->total_data,
5178 state->max_data_return);
5179 END_PROFILE_NESTED(Trans2_ioctl);
5184 /* Error in request */
5185 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5186 outsize = ERROR_DOS(ERRSRV,ERRerror);
5192 /****************************************************************************
5193 Reply to a SMBtrans2.
5194 ****************************************************************************/
5196 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5197 int size, int bufsize)
5200 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5201 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5202 unsigned int psoff = SVAL(inbuf, smb_psoff);
5203 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5204 unsigned int tran_call = SVAL(inbuf, smb_setup0);
5205 struct trans_state *state;
5208 START_PROFILE(SMBtrans2);
5210 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5211 if (!NT_STATUS_IS_OK(result)) {
5212 DEBUG(2, ("Got invalid trans2 request: %s\n",
5213 nt_errstr(result)));
5214 END_PROFILE(SMBtrans2);
5215 return ERROR_NT(result);
5218 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5219 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5220 END_PROFILE(SMBtrans2);
5221 return ERROR_DOS(ERRSRV,ERRaccess);
5224 if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
5225 DEBUG(0, ("talloc failed\n"));
5226 END_PROFILE(SMBtrans2);
5227 return ERROR_NT(NT_STATUS_NO_MEMORY);
5230 state->cmd = SMBtrans2;
5232 state->mid = SVAL(inbuf, smb_mid);
5233 state->vuid = SVAL(inbuf, smb_uid);
5234 state->setup_count = SVAL(inbuf, smb_suwcnt);
5235 state->total_param = SVAL(inbuf, smb_tpscnt);
5236 state->param = NULL;
5237 state->total_data = SVAL(inbuf, smb_tdscnt);
5239 state->max_param_return = SVAL(inbuf, smb_mprcnt);
5240 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
5241 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5242 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5243 state->one_way = BITSETW(inbuf+smb_vwv5,1);
5245 state->call = tran_call;
5247 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5248 is so as a sanity check */
5249 if (state->setup_count != 1) {
5251 * Need to have rc=0 for ioctl to get job id for OS/2.
5252 * Network printing will fail if function is not successful.
5253 * Similar function in reply.c will be used if protocol
5254 * is LANMAN1.0 instead of LM1.2X002.
5255 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5256 * outbuf doesn't have to be set(only job id is used).
5258 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5259 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5260 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5261 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5263 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5264 DEBUG(2,("Transaction is %d\n",tran_call));
5266 END_PROFILE(SMBtrans2);
5267 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5271 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5274 if (state->total_data) {
5275 /* Can't use talloc here, the core routines do realloc on the
5276 * params and data. */
5277 state->data = SMB_MALLOC(state->total_data);
5278 if (state->data == NULL) {
5279 DEBUG(0,("reply_trans2: data malloc fail for %u "
5280 "bytes !\n", state->total_data));
5282 END_PROFILE(SMBtrans2);
5283 return(ERROR_DOS(ERRDOS,ERRnomem));
5285 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5287 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5288 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5291 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5294 if (state->total_param) {
5295 /* Can't use talloc here, the core routines do realloc on the
5296 * params and data. */
5297 state->param = SMB_MALLOC(state->total_param);
5298 if (state->param == NULL) {
5299 DEBUG(0,("reply_trans: param malloc fail for %u "
5300 "bytes !\n", state->total_param));
5301 SAFE_FREE(state->data);
5303 END_PROFILE(SMBtrans2);
5304 return(ERROR_DOS(ERRDOS,ERRnomem));
5306 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5308 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5309 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5312 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5315 state->received_data = dscnt;
5316 state->received_param = pscnt;
5318 if ((state->received_param == state->total_param) &&
5319 (state->received_data == state->total_data)) {
5321 outsize = handle_trans2(conn, state, inbuf, outbuf,
5323 SAFE_FREE(state->data);
5324 SAFE_FREE(state->param);
5326 END_PROFILE(SMBtrans2);
5330 DLIST_ADD(conn->pending_trans, state);
5332 /* We need to send an interim response then receive the rest
5333 of the parameter/data bytes */
5334 outsize = set_message(outbuf,0,0,False);
5336 END_PROFILE(SMBtrans2);
5341 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5342 SAFE_FREE(state->data);
5343 SAFE_FREE(state->param);
5345 END_PROFILE(SMBtrans2);
5346 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5350 /****************************************************************************
5351 Reply to a SMBtranss2
5352 ****************************************************************************/
5354 int reply_transs2(connection_struct *conn,
5355 char *inbuf,char *outbuf,int size,int bufsize)
5358 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5359 struct trans_state *state;
5361 START_PROFILE(SMBtranss2);
5365 for (state = conn->pending_trans; state != NULL;
5366 state = state->next) {
5367 if (state->mid == SVAL(inbuf,smb_mid)) {
5372 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5373 END_PROFILE(SMBtranss2);
5374 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5377 /* Revise state->total_param and state->total_data in case they have
5378 changed downwards */
5380 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5381 state->total_param = SVAL(inbuf, smb_tpscnt);
5382 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5383 state->total_data = SVAL(inbuf, smb_tdscnt);
5385 pcnt = SVAL(inbuf, smb_spscnt);
5386 poff = SVAL(inbuf, smb_spsoff);
5387 pdisp = SVAL(inbuf, smb_spsdisp);
5389 dcnt = SVAL(inbuf, smb_sdscnt);
5390 doff = SVAL(inbuf, smb_sdsoff);
5391 ddisp = SVAL(inbuf, smb_sdsdisp);
5393 state->received_param += pcnt;
5394 state->received_data += dcnt;
5396 if ((state->received_data > state->total_data) ||
5397 (state->received_param > state->total_param))
5401 if (pdisp+pcnt > state->total_param)
5403 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5405 if (pdisp > state->total_param)
5407 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5408 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5410 if (state->param + pdisp < state->param)
5413 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5418 if (ddisp+dcnt > state->total_data)
5420 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5422 if (ddisp > state->total_data)
5424 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5425 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5427 if (state->data + ddisp < state->data)
5430 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5434 if ((state->received_param < state->total_param) ||
5435 (state->received_data < state->total_data)) {
5436 END_PROFILE(SMBtranss2);
5440 /* construct_reply_common has done us the favor to pre-fill the
5441 * command field with SMBtranss2 which is wrong :-)
5443 SCVAL(outbuf,smb_com,SMBtrans2);
5445 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5447 DLIST_REMOVE(conn->pending_trans, state);
5448 SAFE_FREE(state->data);
5449 SAFE_FREE(state->param);
5453 END_PROFILE(SMBtranss2);
5454 return(ERROR_DOS(ERRSRV,ERRnosupport));
5457 END_PROFILE(SMBtranss2);
5462 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5463 DLIST_REMOVE(conn->pending_trans, state);
5464 SAFE_FREE(state->data);
5465 SAFE_FREE(state->param);
5467 END_PROFILE(SMBtranss2);
5468 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);