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 if (total_data && smb_action == FILE_WAS_CREATED) {
864 status = set_ea(conn, fsp, fname, ea_list);
866 if (!NT_STATUS_IS_OK(status)) {
867 close_file(fsp,ERROR_CLOSE);
868 return ERROR_NT(status);
872 /* Realloc the size of parameters and data we will return */
873 *pparams = SMB_REALLOC(*pparams, 30);
874 if(*pparams == NULL ) {
875 return ERROR_NT(NT_STATUS_NO_MEMORY);
879 SSVAL(params,0,fsp->fnum);
880 SSVAL(params,2,open_attr);
881 srv_put_dos_date2(params,4, mtime);
882 SIVAL(params,8, (uint32)size);
883 SSVAL(params,12,deny_mode);
884 SSVAL(params,14,0); /* open_type - file or directory. */
885 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
887 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
888 smb_action |= EXTENDED_OPLOCK_GRANTED;
891 SSVAL(params,18,smb_action);
894 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
896 SIVAL(params,20,inode);
897 SSVAL(params,24,0); /* Padding. */
899 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
900 SIVAL(params, 26, ea_size);
902 SIVAL(params, 26, 0);
905 /* Send the required number of replies */
906 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
911 /*********************************************************
912 Routine to check if a given string matches exactly.
913 as a special case a mask of "." does NOT match. That
914 is required for correct wildcard semantics
915 Case can be significant or not.
916 **********************************************************/
918 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
920 if (mask[0] == '.' && mask[1] == 0)
923 return strcmp(str,mask)==0;
924 if (StrCaseCmp(str,mask) != 0) {
927 if (ms_has_wild(str)) {
933 /****************************************************************************
934 Return the filetype for UNIX extensions.
935 ****************************************************************************/
937 static uint32 unix_filetype(mode_t mode)
940 return UNIX_TYPE_FILE;
941 else if(S_ISDIR(mode))
942 return UNIX_TYPE_DIR;
944 else if(S_ISLNK(mode))
945 return UNIX_TYPE_SYMLINK;
948 else if(S_ISCHR(mode))
949 return UNIX_TYPE_CHARDEV;
952 else if(S_ISBLK(mode))
953 return UNIX_TYPE_BLKDEV;
956 else if(S_ISFIFO(mode))
957 return UNIX_TYPE_FIFO;
960 else if(S_ISSOCK(mode))
961 return UNIX_TYPE_SOCKET;
964 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
965 return UNIX_TYPE_UNKNOWN;
968 /****************************************************************************
969 Map wire perms onto standard UNIX permissions. Obey share restrictions.
970 ****************************************************************************/
972 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
976 if (perms == SMB_MODE_NO_CHANGE)
979 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
980 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
981 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
982 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
983 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
984 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
985 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
986 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
987 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
989 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
992 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
995 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
998 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
999 ret &= lp_dir_mask(SNUM(conn));
1000 /* Add in force bits */
1001 ret |= lp_force_dir_mode(SNUM(conn));
1003 /* Apply mode mask */
1004 ret &= lp_create_mask(SNUM(conn));
1005 /* Add in force bits */
1006 ret |= lp_force_create_mode(SNUM(conn));
1012 /****************************************************************************
1013 Get a level dependent lanman2 dir entry.
1014 ****************************************************************************/
1016 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1017 void *inbuf, void *outbuf,
1018 char *path_mask,uint32 dirtype,int info_level,
1019 int requires_resume_key,
1020 BOOL dont_descend,char **ppdata,
1021 char *base_data, int space_remaining,
1022 BOOL *out_of_space, BOOL *got_exact_match,
1023 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1027 SMB_STRUCT_STAT sbuf;
1031 char *p, *q, *pdata = *ppdata;
1035 SMB_OFF_T file_size = 0;
1036 SMB_BIG_UINT allocation_size = 0;
1038 time_t mdate=0, adate=0, cdate=0;
1040 char *last_entry_ptr;
1042 uint32 nt_extmode; /* Used for NT connections instead of mode */
1043 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1044 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1047 *out_of_space = False;
1048 *got_exact_match = False;
1053 p = strrchr_m(path_mask,'/');
1056 pstrcpy(mask,"*.*");
1060 pstrcpy(mask, path_mask);
1065 /* Needed if we run out of space */
1066 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1067 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1070 * Due to bugs in NT client redirectors we are not using
1071 * resume keys any more - set them to zero.
1072 * Check out the related comments in findfirst/findnext.
1078 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1079 (long)conn->dirptr,curr_dirpos));
1084 pstrcpy(fname,dname);
1086 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1087 got_match = mask_match(fname, mask, conn->case_sensitive);
1089 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1092 * It turns out that NT matches wildcards against
1093 * both long *and* short names. This may explain some
1094 * of the wildcard wierdness from old DOS clients
1095 * that some people have been seeing.... JRA.
1099 pstrcpy( newname, fname);
1100 mangle_map( newname, True, False, SNUM(conn));
1101 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1102 got_match = mask_match(newname, mask, conn->case_sensitive);
1106 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1107 if (dont_descend && !isdots)
1110 pstrcpy(pathreal,conn->dirpath);
1112 pstrcat(pathreal,"/");
1113 pstrcat(pathreal,dname);
1115 if (INFO_LEVEL_IS_UNIX(info_level)) {
1116 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1117 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1118 pathreal,strerror(errno)));
1121 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1123 /* Needed to show the msdfs symlinks as
1126 if(lp_host_msdfs() &&
1127 lp_msdfs_root(SNUM(conn)) &&
1128 is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1131 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1132 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1136 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1137 pathreal,strerror(errno)));
1142 mode = dos_mode(conn,pathreal,&sbuf);
1144 if (!dir_check_ftype(conn,mode,dirtype)) {
1145 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1150 file_size = get_file_size(sbuf);
1151 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1152 mdate = sbuf.st_mtime;
1153 adate = sbuf.st_atime;
1154 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1156 if (lp_dos_filetime_resolution(SNUM(conn))) {
1163 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1167 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1171 mangle_map(fname,False,True,SNUM(conn));
1176 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1178 switch (info_level) {
1179 case SMB_FIND_INFO_STANDARD:
1180 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1181 if(requires_resume_key) {
1185 srv_put_dos_date2(p,0,cdate);
1186 srv_put_dos_date2(p,4,adate);
1187 srv_put_dos_date2(p,8,mdate);
1188 SIVAL(p,12,(uint32)file_size);
1189 SIVAL(p,16,(uint32)allocation_size);
1193 p += align_string(outbuf, p, 0);
1194 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1195 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1197 SCVAL(nameptr, -1, len - 2);
1199 SCVAL(nameptr, -1, 0);
1203 SCVAL(nameptr, -1, len - 1);
1205 SCVAL(nameptr, -1, 0);
1211 case SMB_FIND_EA_SIZE:
1212 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1213 if(requires_resume_key) {
1217 srv_put_dos_date2(p,0,cdate);
1218 srv_put_dos_date2(p,4,adate);
1219 srv_put_dos_date2(p,8,mdate);
1220 SIVAL(p,12,(uint32)file_size);
1221 SIVAL(p,16,(uint32)allocation_size);
1224 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1225 SIVAL(p,22,ea_size); /* Extended attributes */
1229 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1230 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1243 SCVAL(nameptr,0,len);
1245 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1248 case SMB_FIND_EA_LIST:
1250 struct ea_list *file_list = NULL;
1253 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1257 if(requires_resume_key) {
1261 srv_put_dos_date2(p,0,cdate);
1262 srv_put_dos_date2(p,4,adate);
1263 srv_put_dos_date2(p,8,mdate);
1264 SIVAL(p,12,(uint32)file_size);
1265 SIVAL(p,16,(uint32)allocation_size);
1267 p += 22; /* p now points to the EA area. */
1269 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1270 name_list = ea_list_union(name_list, file_list, &ea_len);
1272 /* We need to determine if this entry will fit in the space available. */
1273 /* Max string size is 255 bytes. */
1274 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1275 /* Move the dirptr back to prev_dirpos */
1276 dptr_SeekDir(conn->dirptr, prev_dirpos);
1277 *out_of_space = True;
1278 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1279 return False; /* Not finished - just out of space */
1282 /* Push the ea_data followed by the name. */
1283 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1285 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1286 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1299 SCVAL(nameptr,0,len);
1301 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1305 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1306 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1307 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1309 SIVAL(p,0,reskey); p += 4;
1310 put_long_date(p,cdate); p += 8;
1311 put_long_date(p,adate); p += 8;
1312 put_long_date(p,mdate); p += 8;
1313 put_long_date(p,mdate); p += 8;
1314 SOFF_T(p,0,file_size); p += 8;
1315 SOFF_T(p,0,allocation_size); p += 8;
1316 SIVAL(p,0,nt_extmode); p += 4;
1317 q = p; p += 4; /* q is placeholder for name length. */
1319 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1320 SIVAL(p,0,ea_size); /* Extended attributes */
1323 /* Clear the short name buffer. This is
1324 * IMPORTANT as not doing so will trigger
1325 * a Win2k client bug. JRA.
1327 if (!was_8_3 && check_mangled_names) {
1328 pstring mangled_name;
1329 pstrcpy(mangled_name, fname);
1330 mangle_map(mangled_name,True,True,SNUM(conn));
1331 mangled_name[12] = 0;
1332 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1334 memset(p + 2 + len,'\0',24 - len);
1341 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1344 SIVAL(p,0,0); /* Ensure any padding is null. */
1345 len = PTR_DIFF(p, pdata);
1346 len = (len + 3) & ~3;
1351 case SMB_FIND_FILE_DIRECTORY_INFO:
1352 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1354 SIVAL(p,0,reskey); p += 4;
1355 put_long_date(p,cdate); p += 8;
1356 put_long_date(p,adate); p += 8;
1357 put_long_date(p,mdate); p += 8;
1358 put_long_date(p,mdate); p += 8;
1359 SOFF_T(p,0,file_size); p += 8;
1360 SOFF_T(p,0,allocation_size); p += 8;
1361 SIVAL(p,0,nt_extmode); p += 4;
1362 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1365 SIVAL(p,0,0); /* Ensure any padding is null. */
1366 len = PTR_DIFF(p, pdata);
1367 len = (len + 3) & ~3;
1372 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1373 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1375 SIVAL(p,0,reskey); p += 4;
1376 put_long_date(p,cdate); p += 8;
1377 put_long_date(p,adate); p += 8;
1378 put_long_date(p,mdate); p += 8;
1379 put_long_date(p,mdate); p += 8;
1380 SOFF_T(p,0,file_size); p += 8;
1381 SOFF_T(p,0,allocation_size); p += 8;
1382 SIVAL(p,0,nt_extmode); p += 4;
1383 q = p; p += 4; /* q is placeholder for name length. */
1385 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1386 SIVAL(p,0,ea_size); /* Extended attributes */
1389 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1393 SIVAL(p,0,0); /* Ensure any padding is null. */
1394 len = PTR_DIFF(p, pdata);
1395 len = (len + 3) & ~3;
1400 case SMB_FIND_FILE_NAMES_INFO:
1401 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1403 SIVAL(p,0,reskey); p += 4;
1405 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1406 acl on a dir (tridge) */
1407 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1410 SIVAL(p,0,0); /* Ensure any padding is null. */
1411 len = PTR_DIFF(p, pdata);
1412 len = (len + 3) & ~3;
1417 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1418 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1420 SIVAL(p,0,reskey); p += 4;
1421 put_long_date(p,cdate); p += 8;
1422 put_long_date(p,adate); p += 8;
1423 put_long_date(p,mdate); p += 8;
1424 put_long_date(p,mdate); p += 8;
1425 SOFF_T(p,0,file_size); p += 8;
1426 SOFF_T(p,0,allocation_size); p += 8;
1427 SIVAL(p,0,nt_extmode); p += 4;
1428 q = p; p += 4; /* q is placeholder for name length. */
1430 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1431 SIVAL(p,0,ea_size); /* Extended attributes */
1434 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1435 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1436 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1437 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1440 SIVAL(p,0,0); /* Ensure any padding is null. */
1441 len = PTR_DIFF(p, pdata);
1442 len = (len + 3) & ~3;
1447 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1448 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1449 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1451 SIVAL(p,0,reskey); p += 4;
1452 put_long_date(p,cdate); p += 8;
1453 put_long_date(p,adate); p += 8;
1454 put_long_date(p,mdate); p += 8;
1455 put_long_date(p,mdate); p += 8;
1456 SOFF_T(p,0,file_size); p += 8;
1457 SOFF_T(p,0,allocation_size); p += 8;
1458 SIVAL(p,0,nt_extmode); p += 4;
1459 q = p; p += 4; /* q is placeholder for name length */
1461 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1462 SIVAL(p,0,ea_size); /* Extended attributes */
1465 /* Clear the short name buffer. This is
1466 * IMPORTANT as not doing so will trigger
1467 * a Win2k client bug. JRA.
1469 if (!was_8_3 && check_mangled_names) {
1470 pstring mangled_name;
1471 pstrcpy(mangled_name, fname);
1472 mangle_map(mangled_name,True,True,SNUM(conn));
1473 mangled_name[12] = 0;
1474 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1477 memset(p + 2 + len,'\0',24 - len);
1484 SSVAL(p,0,0); p += 2; /* Reserved ? */
1485 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1486 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1487 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1490 SIVAL(p,0,0); /* Ensure any padding is null. */
1491 len = PTR_DIFF(p, pdata);
1492 len = (len + 3) & ~3;
1497 /* CIFS UNIX Extension. */
1499 case SMB_FIND_FILE_UNIX:
1500 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1502 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1504 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1505 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1508 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1511 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1512 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1513 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1516 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1520 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1524 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1527 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1531 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1535 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1538 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1542 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1546 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1548 SIVAL(p,0,0); /* Ensure any padding is null. */
1550 len = PTR_DIFF(p, pdata);
1551 len = (len + 3) & ~3;
1552 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1554 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1563 if (PTR_DIFF(p,pdata) > space_remaining) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566 *out_of_space = True;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False; /* Not finished - just out of space */
1571 /* Setup the last entry pointer, as an offset from base_data */
1572 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1573 /* Advance the data pointer to the next slot */
1579 /****************************************************************************
1580 Reply to a TRANS2_FINDFIRST.
1581 ****************************************************************************/
1583 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1584 char **pparams, int total_params, char **ppdata, int total_data,
1585 unsigned int max_data_bytes)
1587 /* We must be careful here that we don't return more than the
1588 allowed number of data bytes. If this means returning fewer than
1589 maxentries then so be it. We assume that the redirector has
1590 enough room for the fixed number of parameter bytes it has
1592 char *params = *pparams;
1593 char *pdata = *ppdata;
1594 uint32 dirtype = SVAL(params,0);
1595 int maxentries = SVAL(params,2);
1596 uint16 findfirst_flags = SVAL(params,4);
1597 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1598 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1599 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1600 int info_level = SVAL(params,6);
1604 int last_entry_off=0;
1608 BOOL finished = False;
1609 BOOL dont_descend = False;
1610 BOOL out_of_space = False;
1611 int space_remaining;
1612 BOOL bad_path = False;
1613 BOOL mask_contains_wcard = False;
1614 SMB_STRUCT_STAT sbuf;
1615 TALLOC_CTX *ea_ctx = NULL;
1616 struct ea_list *ea_list = NULL;
1617 NTSTATUS ntstatus = NT_STATUS_OK;
1619 if (total_params < 12) {
1620 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1623 *directory = *mask = 0;
1625 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1626 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1627 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1628 info_level, max_data_bytes));
1631 /* W2K3 seems to treat zero as 1. */
1635 switch (info_level) {
1636 case SMB_FIND_INFO_STANDARD:
1637 case SMB_FIND_EA_SIZE:
1638 case SMB_FIND_EA_LIST:
1639 case SMB_FIND_FILE_DIRECTORY_INFO:
1640 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1641 case SMB_FIND_FILE_NAMES_INFO:
1642 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1643 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1644 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1646 case SMB_FIND_FILE_UNIX:
1647 if (!lp_unix_extensions()) {
1648 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1652 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1655 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1656 if (!NT_STATUS_IS_OK(ntstatus)) {
1657 return ERROR_NT(ntstatus);
1660 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1662 unix_convert(directory,conn,0,&bad_path,&sbuf);
1664 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1666 if(!check_name(directory,conn)) {
1667 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1670 p = strrchr_m(directory,'/');
1672 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1673 if((directory[0] == '.') && (directory[1] == '\0')) {
1675 mask_contains_wcard = True;
1677 pstrcpy(mask,directory);
1679 pstrcpy(directory,"./");
1685 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1687 if (info_level == SMB_FIND_EA_LIST) {
1690 if (total_data < 4) {
1691 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1694 ea_size = IVAL(pdata,0);
1695 if (ea_size != total_data) {
1696 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1697 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1698 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1701 if (!lp_ea_support(SNUM(conn))) {
1702 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1705 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1706 return ERROR_NT(NT_STATUS_NO_MEMORY);
1709 /* Pull out the list of names. */
1710 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1712 talloc_destroy(ea_ctx);
1713 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1717 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1718 if(*ppdata == NULL ) {
1719 talloc_destroy(ea_ctx);
1720 return ERROR_NT(NT_STATUS_NO_MEMORY);
1724 /* Realloc the params space */
1725 *pparams = SMB_REALLOC(*pparams, 10);
1726 if (*pparams == NULL) {
1727 talloc_destroy(ea_ctx);
1728 return ERROR_NT(NT_STATUS_NO_MEMORY);
1732 /* Save the wildcard match and attribs we are using on this directory -
1733 needed as lanman2 assumes these are being saved between calls */
1735 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1737 talloc_destroy(ea_ctx);
1738 return(UNIXERROR(ERRDOS,ERRbadfile));
1741 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1743 /* We don't need to check for VOL here as this is returned by
1744 a different TRANS2 call. */
1746 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1747 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1748 dont_descend = True;
1751 space_remaining = max_data_bytes;
1752 out_of_space = False;
1754 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1755 BOOL got_exact_match = False;
1757 /* this is a heuristic to avoid seeking the dirptr except when
1758 absolutely necessary. It allows for a filename of about 40 chars */
1759 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1760 out_of_space = True;
1763 finished = !get_lanman2_dir_entry(conn,
1765 mask,dirtype,info_level,
1766 requires_resume_key,dont_descend,
1767 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1768 &last_entry_off, ea_list, ea_ctx);
1771 if (finished && out_of_space)
1774 if (!finished && !out_of_space)
1778 * As an optimisation if we know we aren't looking
1779 * for a wildcard name (ie. the name matches the wildcard exactly)
1780 * then we can finish on any (first) match.
1781 * This speeds up large directory searches. JRA.
1787 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1790 talloc_destroy(ea_ctx);
1792 /* Check if we can close the dirptr */
1793 if(close_after_first || (finished && close_if_end)) {
1794 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1795 dptr_close(&dptr_num);
1799 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1800 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1801 * the protocol level is less than NT1. Tested with smbclient. JRA.
1802 * This should fix the OS/2 client bug #2335.
1805 if(numentries == 0) {
1806 dptr_close(&dptr_num);
1807 if (Protocol < PROTOCOL_NT1) {
1808 return ERROR_DOS(ERRDOS,ERRnofiles);
1810 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1814 /* At this point pdata points to numentries directory entries. */
1816 /* Set up the return parameter block */
1817 SSVAL(params,0,dptr_num);
1818 SSVAL(params,2,numentries);
1819 SSVAL(params,4,finished);
1820 SSVAL(params,6,0); /* Never an EA error */
1821 SSVAL(params,8,last_entry_off);
1823 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1825 if ((! *directory) && dptr_path(dptr_num))
1826 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1828 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1829 smb_fn_name(CVAL(inbuf,smb_com)),
1830 mask, directory, dirtype, numentries ) );
1833 * Force a name mangle here to ensure that the
1834 * mask as an 8.3 name is top of the mangled cache.
1835 * The reasons for this are subtle. Don't remove
1836 * this code unless you know what you are doing
1837 * (see PR#13758). JRA.
1840 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1841 mangle_map(mask, True, True, SNUM(conn));
1846 /****************************************************************************
1847 Reply to a TRANS2_FINDNEXT.
1848 ****************************************************************************/
1850 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1851 char **pparams, int total_params, char **ppdata, int total_data,
1852 unsigned int max_data_bytes)
1854 /* We must be careful here that we don't return more than the
1855 allowed number of data bytes. If this means returning fewer than
1856 maxentries then so be it. We assume that the redirector has
1857 enough room for the fixed number of parameter bytes it has
1859 char *params = *pparams;
1860 char *pdata = *ppdata;
1861 int dptr_num = SVAL(params,0);
1862 int maxentries = SVAL(params,2);
1863 uint16 info_level = SVAL(params,4);
1864 uint32 resume_key = IVAL(params,6);
1865 uint16 findnext_flags = SVAL(params,10);
1866 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1867 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1868 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1869 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1870 BOOL mask_contains_wcard = False;
1871 pstring resume_name;
1877 int i, last_entry_off=0;
1878 BOOL finished = False;
1879 BOOL dont_descend = False;
1880 BOOL out_of_space = False;
1881 int space_remaining;
1882 TALLOC_CTX *ea_ctx = NULL;
1883 struct ea_list *ea_list = NULL;
1884 NTSTATUS ntstatus = NT_STATUS_OK;
1886 if (total_params < 12) {
1887 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1890 *mask = *directory = *resume_name = 0;
1892 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1893 if (!NT_STATUS_IS_OK(ntstatus)) {
1894 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1895 complain (it thinks we're asking for the directory above the shared
1896 path or an invalid name). Catch this as the resume name is only compared, never used in
1897 a file access. JRA. */
1898 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1899 pstrcpy(resume_name, "..");
1900 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1901 pstrcpy(resume_name, ".");
1903 return ERROR_NT(ntstatus);
1907 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1908 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1909 resume_key = %d resume name = %s continue=%d level = %d\n",
1910 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1911 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1914 /* W2K3 seems to treat zero as 1. */
1918 switch (info_level) {
1919 case SMB_FIND_INFO_STANDARD:
1920 case SMB_FIND_EA_SIZE:
1921 case SMB_FIND_EA_LIST:
1922 case SMB_FIND_FILE_DIRECTORY_INFO:
1923 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1924 case SMB_FIND_FILE_NAMES_INFO:
1925 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1926 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1927 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1929 case SMB_FIND_FILE_UNIX:
1930 if (!lp_unix_extensions()) {
1931 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1935 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1938 if (info_level == SMB_FIND_EA_LIST) {
1941 if (total_data < 4) {
1942 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1945 ea_size = IVAL(pdata,0);
1946 if (ea_size != total_data) {
1947 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1948 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1949 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1952 if (!lp_ea_support(SNUM(conn))) {
1953 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1956 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1957 return ERROR_NT(NT_STATUS_NO_MEMORY);
1960 /* Pull out the list of names. */
1961 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1963 talloc_destroy(ea_ctx);
1964 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1968 *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1969 if(*ppdata == NULL) {
1970 talloc_destroy(ea_ctx);
1971 return ERROR_NT(NT_STATUS_NO_MEMORY);
1976 /* Realloc the params space */
1977 *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1978 if(*pparams == NULL ) {
1979 talloc_destroy(ea_ctx);
1980 return ERROR_NT(NT_STATUS_NO_MEMORY);
1985 /* Check that the dptr is valid */
1986 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1987 talloc_destroy(ea_ctx);
1988 return ERROR_DOS(ERRDOS,ERRnofiles);
1991 string_set(&conn->dirpath,dptr_path(dptr_num));
1993 /* Get the wildcard mask from the dptr */
1994 if((p = dptr_wcard(dptr_num))== NULL) {
1995 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1996 talloc_destroy(ea_ctx);
1997 return ERROR_DOS(ERRDOS,ERRnofiles);
2001 pstrcpy(directory,conn->dirpath);
2003 /* Get the attr mask from the dptr */
2004 dirtype = dptr_attr(dptr_num);
2006 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2007 dptr_num, mask, dirtype,
2009 dptr_TellDir(conn->dirptr)));
2011 /* We don't need to check for VOL here as this is returned by
2012 a different TRANS2 call. */
2014 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2015 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2016 dont_descend = True;
2019 space_remaining = max_data_bytes;
2020 out_of_space = False;
2023 * Seek to the correct position. We no longer use the resume key but
2024 * depend on the last file name instead.
2027 if(*resume_name && !continue_bit) {
2030 long current_pos = 0;
2032 * Remember, mangle_map is called by
2033 * get_lanman2_dir_entry(), so the resume name
2034 * could be mangled. Ensure we check the unmangled name.
2037 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2038 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2042 * Fix for NT redirector problem triggered by resume key indexes
2043 * changing between directory scans. We now return a resume key of 0
2044 * and instead look for the filename to continue from (also given
2045 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2046 * findfirst/findnext (as is usual) then the directory pointer
2047 * should already be at the correct place.
2050 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2051 } /* end if resume_name && !continue_bit */
2053 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2054 BOOL got_exact_match = False;
2056 /* this is a heuristic to avoid seeking the dirptr except when
2057 absolutely necessary. It allows for a filename of about 40 chars */
2058 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2059 out_of_space = True;
2062 finished = !get_lanman2_dir_entry(conn,
2064 mask,dirtype,info_level,
2065 requires_resume_key,dont_descend,
2066 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2067 &last_entry_off, ea_list, ea_ctx);
2070 if (finished && out_of_space)
2073 if (!finished && !out_of_space)
2077 * As an optimisation if we know we aren't looking
2078 * for a wildcard name (ie. the name matches the wildcard exactly)
2079 * then we can finish on any (first) match.
2080 * This speeds up large directory searches. JRA.
2086 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2089 talloc_destroy(ea_ctx);
2091 /* Check if we can close the dirptr */
2092 if(close_after_request || (finished && close_if_end)) {
2093 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2094 dptr_close(&dptr_num); /* This frees up the saved mask */
2097 /* Set up the return parameter block */
2098 SSVAL(params,0,numentries);
2099 SSVAL(params,2,finished);
2100 SSVAL(params,4,0); /* Never an EA error */
2101 SSVAL(params,6,last_entry_off);
2103 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2105 if ((! *directory) && dptr_path(dptr_num))
2106 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2108 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2109 smb_fn_name(CVAL(inbuf,smb_com)),
2110 mask, directory, dirtype, numentries ) );
2115 /****************************************************************************
2116 Reply to a TRANS2_QFSINFO (query filesystem info).
2117 ****************************************************************************/
2119 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2120 char **pparams, int total_params, char **ppdata, int total_data,
2121 unsigned int max_data_bytes)
2123 char *pdata = *ppdata;
2124 char *params = *pparams;
2125 uint16 info_level = SVAL(params,0);
2128 char *vname = volume_label(SNUM(conn));
2129 int snum = SNUM(conn);
2130 char *fstype = lp_fstype(SNUM(conn));
2133 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2135 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2136 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2137 return ERROR_DOS(ERRSRV,ERRinvdevice);
2140 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2141 if (*ppdata == NULL ) {
2142 return ERROR_NT(NT_STATUS_NO_MEMORY);
2146 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2148 switch (info_level) {
2149 case SMB_INFO_ALLOCATION:
2151 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2153 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2154 return(UNIXERROR(ERRHRD,ERRgeneral));
2157 block_size = lp_block_size(snum);
2158 if (bsize < block_size) {
2159 SMB_BIG_UINT factor = block_size/bsize;
2164 if (bsize > block_size) {
2165 SMB_BIG_UINT factor = bsize/block_size;
2170 bytes_per_sector = 512;
2171 sectors_per_unit = bsize/bytes_per_sector;
2173 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2174 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2175 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2177 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2178 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2179 SIVAL(pdata,l1_cUnit,dsize);
2180 SIVAL(pdata,l1_cUnitAvail,dfree);
2181 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2185 case SMB_INFO_VOLUME:
2186 /* Return volume name */
2188 * Add volume serial number - hash of a combination of
2189 * the called hostname and the service name.
2191 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2193 * Win2k3 and previous mess this up by sending a name length
2194 * one byte short. I believe only older clients (OS/2 Win9x) use
2195 * this call so try fixing this by adding a terminating null to
2196 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2198 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2199 SCVAL(pdata,l2_vol_cch,len);
2200 data_len = l2_vol_szVolLabel + len;
2201 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2202 (unsigned)st.st_ctime, len, vname));
2205 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2206 case SMB_FS_ATTRIBUTE_INFORMATION:
2209 #if defined(HAVE_SYS_QUOTAS)
2210 quota_flag = FILE_VOLUME_QUOTAS;
2213 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2214 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2215 quota_flag); /* FS ATTRIBUTES */
2217 SIVAL(pdata,4,255); /* Max filename component length */
2218 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2219 and will think we can't do long filenames */
2220 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2222 data_len = 12 + len;
2225 case SMB_QUERY_FS_LABEL_INFO:
2226 case SMB_FS_LABEL_INFORMATION:
2227 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2232 case SMB_QUERY_FS_VOLUME_INFO:
2233 case SMB_FS_VOLUME_INFORMATION:
2236 * Add volume serial number - hash of a combination of
2237 * the called hostname and the service name.
2239 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2240 (str_checksum(get_local_machine_name())<<16));
2242 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2243 SIVAL(pdata,12,len);
2245 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2246 (int)strlen(vname),vname, lp_servicename(snum)));
2249 case SMB_QUERY_FS_SIZE_INFO:
2250 case SMB_FS_SIZE_INFORMATION:
2252 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2254 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2255 return(UNIXERROR(ERRHRD,ERRgeneral));
2257 block_size = lp_block_size(snum);
2258 if (bsize < block_size) {
2259 SMB_BIG_UINT factor = block_size/bsize;
2264 if (bsize > block_size) {
2265 SMB_BIG_UINT factor = bsize/block_size;
2270 bytes_per_sector = 512;
2271 sectors_per_unit = bsize/bytes_per_sector;
2272 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2273 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2274 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2275 SBIG_UINT(pdata,0,dsize);
2276 SBIG_UINT(pdata,8,dfree);
2277 SIVAL(pdata,16,sectors_per_unit);
2278 SIVAL(pdata,20,bytes_per_sector);
2282 case SMB_FS_FULL_SIZE_INFORMATION:
2284 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2286 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2287 return(UNIXERROR(ERRHRD,ERRgeneral));
2289 block_size = lp_block_size(snum);
2290 if (bsize < block_size) {
2291 SMB_BIG_UINT factor = block_size/bsize;
2296 if (bsize > block_size) {
2297 SMB_BIG_UINT factor = bsize/block_size;
2302 bytes_per_sector = 512;
2303 sectors_per_unit = bsize/bytes_per_sector;
2304 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2305 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2306 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2307 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2308 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2309 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2310 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2311 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2315 case SMB_QUERY_FS_DEVICE_INFO:
2316 case SMB_FS_DEVICE_INFORMATION:
2318 SIVAL(pdata,0,0); /* dev type */
2319 SIVAL(pdata,4,0); /* characteristics */
2322 #ifdef HAVE_SYS_QUOTAS
2323 case SMB_FS_QUOTA_INFORMATION:
2325 * what we have to send --metze:
2327 * Unknown1: 24 NULL bytes
2328 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2329 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2330 * Quota Flags: 2 byte :
2331 * Unknown3: 6 NULL bytes
2335 * details for Quota Flags:
2337 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2338 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2339 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2340 * 0x0001 Enable Quotas: enable quota for this fs
2344 /* we need to fake up a fsp here,
2345 * because its not send in this call
2348 SMB_NTQUOTA_STRUCT quotas;
2351 ZERO_STRUCT(quotas);
2357 if (current_user.ut.uid != 0) {
2358 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2359 lp_servicename(SNUM(conn)),conn->user));
2360 return ERROR_DOS(ERRDOS,ERRnoaccess);
2363 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2364 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2365 return ERROR_DOS(ERRSRV,ERRerror);
2370 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2372 /* Unknown1 24 NULL bytes*/
2373 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2374 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2375 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2377 /* Default Soft Quota 8 bytes */
2378 SBIG_UINT(pdata,24,quotas.softlim);
2380 /* Default Hard Quota 8 bytes */
2381 SBIG_UINT(pdata,32,quotas.hardlim);
2383 /* Quota flag 2 bytes */
2384 SSVAL(pdata,40,quotas.qflags);
2386 /* Unknown3 6 NULL bytes */
2392 #endif /* HAVE_SYS_QUOTAS */
2393 case SMB_FS_OBJECTID_INFORMATION:
2398 * Query the version and capabilities of the CIFS UNIX extensions
2402 case SMB_QUERY_CIFS_UNIX_INFO:
2403 if (!lp_unix_extensions()) {
2404 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2407 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2408 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2409 /* We have POSIX ACLs, pathname and locking capability. */
2410 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2411 CIFS_UNIX_POSIX_ACLS_CAP|
2412 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2413 #if defined(DEVELOPER) /* Not quite finished yet... */
2414 CIFS_UNIX_FCNTL_LOCKS_CAP)));
2420 case SMB_QUERY_POSIX_FS_INFO:
2423 vfs_statvfs_struct svfs;
2425 if (!lp_unix_extensions()) {
2426 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2429 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2433 SIVAL(pdata,0,svfs.OptimalTransferSize);
2434 SIVAL(pdata,4,svfs.BlockSize);
2435 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2436 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2437 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2438 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2439 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2440 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2441 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2443 } else if (rc == EOPNOTSUPP) {
2444 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2445 #endif /* EOPNOTSUPP */
2447 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2448 return ERROR_DOS(ERRSRV,ERRerror);
2453 case SMB_MAC_QUERY_FS_INFO:
2455 * Thursby MAC extension... ONLY on NTFS filesystems
2456 * once we do streams then we don't need this
2458 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2460 SIVAL(pdata,84,0x100); /* Don't support mac... */
2465 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2469 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2471 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2476 /****************************************************************************
2477 Reply to a TRANS2_SETFSINFO (set filesystem info).
2478 ****************************************************************************/
2480 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2481 char **pparams, int total_params, char **ppdata, int total_data,
2482 unsigned int max_data_bytes)
2484 char *pdata = *ppdata;
2485 char *params = *pparams;
2489 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2492 if (total_params < 4) {
2493 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2495 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2498 info_level = SVAL(params,2);
2500 switch(info_level) {
2501 case SMB_SET_CIFS_UNIX_INFO:
2503 uint16 client_unix_major;
2504 uint16 client_unix_minor;
2505 uint32 client_unix_cap_low;
2506 uint32 client_unix_cap_high;
2508 if (!lp_unix_extensions()) {
2509 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2512 /* There should be 12 bytes of capabilities set. */
2513 if (total_data < 8) {
2514 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2516 client_unix_major = SVAL(pdata,0);
2517 client_unix_minor = SVAL(pdata,2);
2518 client_unix_cap_low = IVAL(pdata,4);
2519 client_unix_cap_high = IVAL(pdata,8);
2520 /* Just print these values for now. */
2521 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2522 cap_low = 0x%x, cap_high = 0x%x\n",
2523 (unsigned int)client_unix_major,
2524 (unsigned int)client_unix_minor,
2525 (unsigned int)client_unix_cap_low,
2526 (unsigned int)client_unix_cap_high ));
2528 /* Here is where we must switch to posix pathname processing... */
2529 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2530 lp_set_posix_pathnames();
2531 mangle_change_to_posix();
2533 #if defined(DEVELOPER)
2534 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2535 lp_set_posix_cifsx_locktype(POSIX_LOCK);
2540 case SMB_FS_QUOTA_INFORMATION:
2542 files_struct *fsp = NULL;
2543 SMB_NTQUOTA_STRUCT quotas;
2545 ZERO_STRUCT(quotas);
2548 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2549 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2550 lp_servicename(SNUM(conn)),conn->user));
2551 return ERROR_DOS(ERRSRV,ERRaccess);
2554 /* note: normaly there're 48 bytes,
2555 * but we didn't use the last 6 bytes for now
2558 fsp = file_fsp(params,0);
2559 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2560 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2561 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2564 if (total_data < 42) {
2565 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2567 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2570 /* unknown_1 24 NULL bytes in pdata*/
2572 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2573 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2574 #ifdef LARGE_SMB_OFF_T
2575 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2576 #else /* LARGE_SMB_OFF_T */
2577 if ((IVAL(pdata,28) != 0)&&
2578 ((quotas.softlim != 0xFFFFFFFF)||
2579 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2580 /* more than 32 bits? */
2581 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2583 #endif /* LARGE_SMB_OFF_T */
2585 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2586 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2587 #ifdef LARGE_SMB_OFF_T
2588 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2589 #else /* LARGE_SMB_OFF_T */
2590 if ((IVAL(pdata,36) != 0)&&
2591 ((quotas.hardlim != 0xFFFFFFFF)||
2592 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2593 /* more than 32 bits? */
2594 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2596 #endif /* LARGE_SMB_OFF_T */
2598 /* quota_flags 2 bytes **/
2599 quotas.qflags = SVAL(pdata,40);
2601 /* unknown_2 6 NULL bytes follow*/
2603 /* now set the quotas */
2604 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2605 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2606 return ERROR_DOS(ERRSRV,ERRerror);
2612 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2614 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2619 * sending this reply works fine,
2620 * but I'm not sure it's the same
2621 * like windows do...
2624 outsize = set_message(outbuf,10,0,True);
2629 /****************************************************************************
2630 Utility function to set bad path error.
2631 ****************************************************************************/
2633 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2635 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2636 err, (int)bad_path ));
2640 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2642 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2645 return UNIXERROR(def_class,def_code);
2648 #if defined(HAVE_POSIX_ACLS)
2649 /****************************************************************************
2650 Utility function to count the number of entries in a POSIX acl.
2651 ****************************************************************************/
2653 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2655 unsigned int ace_count = 0;
2656 int entry_id = SMB_ACL_FIRST_ENTRY;
2657 SMB_ACL_ENTRY_T entry;
2659 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2661 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2662 entry_id = SMB_ACL_NEXT_ENTRY;
2669 /****************************************************************************
2670 Utility function to marshall a POSIX acl into wire format.
2671 ****************************************************************************/
2673 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2675 int entry_id = SMB_ACL_FIRST_ENTRY;
2676 SMB_ACL_ENTRY_T entry;
2678 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2679 SMB_ACL_TAG_T tagtype;
2680 SMB_ACL_PERMSET_T permset;
2681 unsigned char perms = 0;
2682 unsigned int own_grp;
2685 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2686 entry_id = SMB_ACL_NEXT_ENTRY;
2689 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2690 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2694 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2695 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2699 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2700 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2701 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2703 SCVAL(pdata,1,perms);
2706 case SMB_ACL_USER_OBJ:
2707 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2708 own_grp = (unsigned int)pst->st_uid;
2709 SIVAL(pdata,2,own_grp);
2714 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2716 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2718 own_grp = (unsigned int)*puid;
2719 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2720 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2721 SIVAL(pdata,2,own_grp);
2725 case SMB_ACL_GROUP_OBJ:
2726 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2727 own_grp = (unsigned int)pst->st_gid;
2728 SIVAL(pdata,2,own_grp);
2733 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2735 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2737 own_grp = (unsigned int)*pgid;
2738 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2739 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2740 SIVAL(pdata,2,own_grp);
2745 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2746 SIVAL(pdata,2,0xFFFFFFFF);
2747 SIVAL(pdata,6,0xFFFFFFFF);
2750 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2751 SIVAL(pdata,2,0xFFFFFFFF);
2752 SIVAL(pdata,6,0xFFFFFFFF);
2755 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2758 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2765 /****************************************************************************
2766 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2767 file name or file id).
2768 ****************************************************************************/
2770 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2771 unsigned int tran_call,
2772 char **pparams, int total_params, char **ppdata, int total_data,
2773 unsigned int max_data_bytes)
2775 char *params = *pparams;
2776 char *pdata = *ppdata;
2780 SMB_OFF_T file_size=0;
2781 SMB_BIG_UINT allocation_size=0;
2782 unsigned int data_size = 0;
2783 unsigned int param_size = 2;
2784 SMB_STRUCT_STAT sbuf;
2785 pstring fname, dos_fname;
2789 char *lock_data = NULL;
2791 BOOL bad_path = False;
2792 BOOL delete_pending = False;
2795 files_struct *fsp = NULL;
2796 TALLOC_CTX *data_ctx = NULL;
2797 struct ea_list *ea_list = NULL;
2798 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2801 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2805 if (tran_call == TRANSACT2_QFILEINFO) {
2806 if (total_params < 4) {
2807 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2810 fsp = file_fsp(params,0);
2811 info_level = SVAL(params,2);
2813 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2815 if(fsp && (fsp->fake_file_handle)) {
2817 * This is actually for the QUOTA_FAKE_FILE --metze
2820 pstrcpy(fname, fsp->fsp_name);
2821 /* We know this name is ok, it's already passed the checks. */
2823 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2825 * This is actually a QFILEINFO on a directory
2826 * handle (returned from an NT SMB). NT5.0 seems
2827 * to do this call. JRA.
2829 /* We know this name is ok, it's already passed the checks. */
2830 pstrcpy(fname, fsp->fsp_name);
2832 if (INFO_LEVEL_IS_UNIX(info_level)) {
2833 /* Always do lstat for UNIX calls. */
2834 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2835 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2836 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2838 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2839 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2840 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2843 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2846 * Original code - this is an open file.
2848 CHECK_FSP(fsp,conn);
2850 pstrcpy(fname, fsp->fsp_name);
2851 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2852 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2853 return(UNIXERROR(ERRDOS,ERRbadfid));
2855 pos = fsp->fh->position_information;
2856 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2857 access_mask = fsp->access_mask;
2860 NTSTATUS status = NT_STATUS_OK;
2863 if (total_params < 6) {
2864 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2867 info_level = SVAL(params,0);
2869 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2871 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2872 if (!NT_STATUS_IS_OK(status)) {
2873 return ERROR_NT(status);
2876 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2878 unix_convert(fname,conn,0,&bad_path,&sbuf);
2880 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2882 if (!check_name(fname,conn)) {
2883 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2884 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2887 if (INFO_LEVEL_IS_UNIX(info_level)) {
2888 /* Always do lstat for UNIX calls. */
2889 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2890 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2891 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2893 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2894 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2895 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2898 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2899 if (delete_pending) {
2900 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2904 nlink = sbuf.st_nlink;
2906 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2907 /* NTFS does not seem to count ".." */
2911 if ((nlink > 0) && delete_pending) {
2915 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2916 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2919 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2920 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2922 p = strrchr_m(fname,'/');
2928 mode = dos_mode(conn,fname,&sbuf);
2930 mode = FILE_ATTRIBUTE_NORMAL;
2932 fullpathname = fname;
2934 file_size = get_file_size(sbuf);
2936 /* Pull out any data sent here before we realloc. */
2937 switch (info_level) {
2938 case SMB_INFO_QUERY_EAS_FROM_LIST:
2940 /* Pull any EA list from the data portion. */
2943 if (total_data < 4) {
2944 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2946 ea_size = IVAL(pdata,0);
2948 if (total_data > 0 && ea_size != total_data) {
2949 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2950 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2951 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2954 if (!lp_ea_support(SNUM(conn))) {
2955 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2958 if ((data_ctx = talloc_init("ea_list")) == NULL) {
2959 return ERROR_NT(NT_STATUS_NO_MEMORY);
2962 /* Pull out the list of names. */
2963 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
2965 talloc_destroy(data_ctx);
2966 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2970 #if defined(DEVELOPER)
2971 case SMB_QUERY_POSIX_LOCK:
2973 if (fsp == NULL || fsp->fh->fd == -1) {
2974 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2977 if (total_data != POSIX_LOCK_DATA_SIZE) {
2978 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2981 if ((data_ctx = talloc_init("lock_request")) == NULL) {
2982 return ERROR_NT(NT_STATUS_NO_MEMORY);
2985 /* Copy the lock range data. */
2986 lock_data = talloc_memdup(data_ctx, pdata, total_data);
2988 talloc_destroy(data_ctx);
2989 return ERROR_NT(NT_STATUS_NO_MEMORY);
2997 *pparams = SMB_REALLOC(*pparams,2);
2998 if (*pparams == NULL) {
2999 talloc_destroy(data_ctx);
3000 return ERROR_NT(NT_STATUS_NO_MEMORY);
3004 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3005 *ppdata = SMB_REALLOC(*ppdata, data_size);
3006 if (*ppdata == NULL ) {
3007 talloc_destroy(data_ctx);
3008 return ERROR_NT(NT_STATUS_NO_MEMORY);
3012 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3014 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3017 if (fsp->pending_modtime) {
3018 /* the pending modtime overrides the current modtime */
3019 sbuf.st_mtime = fsp->pending_modtime;
3022 /* Do we have this path open ? */
3023 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3024 if (fsp1 && fsp1->pending_modtime) {
3025 /* the pending modtime overrides the current modtime */
3026 sbuf.st_mtime = fsp1->pending_modtime;
3028 if (fsp1 && fsp1->initial_allocation_size) {
3029 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3033 if (lp_dos_filetime_resolution(SNUM(conn))) {
3035 sbuf.st_atime &= ~1;
3036 sbuf.st_ctime &= ~1;
3037 sbuf.st_mtime &= ~1;
3040 /* NT expects the name to be in an exact form of the *full*
3041 filename. See the trans2 torture test */
3042 if (strequal(base_name,".")) {
3043 pstrcpy(dos_fname, "\\");
3045 pstr_sprintf(dos_fname, "\\%s", fname);
3046 string_replace(dos_fname, '/', '\\');
3049 switch (info_level) {
3050 case SMB_INFO_STANDARD:
3051 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3053 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3054 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3055 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3056 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3057 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3058 SSVAL(pdata,l1_attrFile,mode);
3061 case SMB_INFO_QUERY_EA_SIZE:
3063 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3064 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3066 srv_put_dos_date2(pdata,0,c_time);
3067 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3068 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3069 SIVAL(pdata,12,(uint32)file_size);
3070 SIVAL(pdata,16,(uint32)allocation_size);
3071 SSVAL(pdata,20,mode);
3072 SIVAL(pdata,22,ea_size);
3076 case SMB_INFO_IS_NAME_VALID:
3077 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3078 if (tran_call == TRANSACT2_QFILEINFO) {
3079 /* os/2 needs this ? really ?*/
3080 return ERROR_DOS(ERRDOS,ERRbadfunc);
3086 case SMB_INFO_QUERY_EAS_FROM_LIST:
3088 size_t total_ea_len = 0;
3089 struct ea_list *ea_file_list = NULL;
3091 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3093 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3094 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3096 if (!ea_list || (total_ea_len > data_size)) {
3097 talloc_destroy(data_ctx);
3099 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3103 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3104 talloc_destroy(data_ctx);
3108 case SMB_INFO_QUERY_ALL_EAS:
3110 /* We have data_size bytes to put EA's into. */
3111 size_t total_ea_len = 0;
3113 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3115 data_ctx = talloc_init("ea_ctx");
3117 return ERROR_NT(NT_STATUS_NO_MEMORY);
3120 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3121 if (!ea_list || (total_ea_len > data_size)) {
3122 talloc_destroy(data_ctx);
3124 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3128 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3129 talloc_destroy(data_ctx);
3133 case SMB_FILE_BASIC_INFORMATION:
3134 case SMB_QUERY_FILE_BASIC_INFO:
3136 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3137 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3138 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3140 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3144 put_long_date(pdata,c_time);
3145 put_long_date(pdata+8,sbuf.st_atime);
3146 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3147 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3148 SIVAL(pdata,32,mode);
3150 DEBUG(5,("SMB_QFBI - "));
3152 time_t create_time = c_time;
3153 DEBUG(5,("create: %s ", ctime(&create_time)));
3155 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3156 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3157 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3158 DEBUG(5,("mode: %x\n", mode));
3161 case SMB_FILE_STANDARD_INFORMATION:
3162 case SMB_QUERY_FILE_STANDARD_INFO:
3164 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3166 SOFF_T(pdata,0,allocation_size);
3167 SOFF_T(pdata,8,file_size);
3168 SIVAL(pdata,16,nlink);
3169 SCVAL(pdata,20,delete_pending?1:0);
3170 SCVAL(pdata,21,(mode&aDIR)?1:0);
3171 SSVAL(pdata,22,0); /* Padding. */
3174 case SMB_FILE_EA_INFORMATION:
3175 case SMB_QUERY_FILE_EA_INFO:
3177 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3178 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3180 SIVAL(pdata,0,ea_size);
3184 /* Get the 8.3 name - used if NT SMB was negotiated. */
3185 case SMB_QUERY_FILE_ALT_NAME_INFO:
3186 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3190 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3191 pstrcpy(short_name,base_name);
3192 /* Mangle if not already 8.3 */
3193 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3194 mangle_map(short_name,True,True,SNUM(conn));
3196 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3197 data_size = 4 + len;
3202 case SMB_QUERY_FILE_NAME_INFO:
3204 this must be *exactly* right for ACLs on mapped drives to work
3206 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3207 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3208 data_size = 4 + len;
3212 case SMB_FILE_ALLOCATION_INFORMATION:
3213 case SMB_QUERY_FILE_ALLOCATION_INFO:
3214 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3216 SOFF_T(pdata,0,allocation_size);
3219 case SMB_FILE_END_OF_FILE_INFORMATION:
3220 case SMB_QUERY_FILE_END_OF_FILEINFO:
3221 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3223 SOFF_T(pdata,0,file_size);
3226 case SMB_QUERY_FILE_ALL_INFO:
3227 case SMB_FILE_ALL_INFORMATION:
3229 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3230 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3231 put_long_date(pdata,c_time);
3232 put_long_date(pdata+8,sbuf.st_atime);
3233 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3234 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3235 SIVAL(pdata,32,mode);
3236 SIVAL(pdata,36,0); /* padding. */
3238 SOFF_T(pdata,0,allocation_size);
3239 SOFF_T(pdata,8,file_size);
3240 SIVAL(pdata,16,nlink);
3241 SCVAL(pdata,20,delete_pending);
3242 SCVAL(pdata,21,(mode&aDIR)?1:0);
3245 SIVAL(pdata,0,ea_size);
3246 pdata += 4; /* EA info */
3247 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3250 data_size = PTR_DIFF(pdata,(*ppdata));
3253 case SMB_FILE_INTERNAL_INFORMATION:
3254 /* This should be an index number - looks like
3257 I think this causes us to fail the IFSKIT
3258 BasicFileInformationTest. -tpot */
3260 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3261 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3262 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3266 case SMB_FILE_ACCESS_INFORMATION:
3267 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3268 SIVAL(pdata,0,access_mask);
3272 case SMB_FILE_NAME_INFORMATION:
3273 /* Pathname with leading '\'. */
3276 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3277 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3278 SIVAL(pdata,0,byte_len);
3279 data_size = 4 + byte_len;
3283 case SMB_FILE_DISPOSITION_INFORMATION:
3284 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3286 SCVAL(pdata,0,delete_pending);
3289 case SMB_FILE_POSITION_INFORMATION:
3290 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3292 SOFF_T(pdata,0,pos);
3295 case SMB_FILE_MODE_INFORMATION:
3296 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3297 SIVAL(pdata,0,mode);
3301 case SMB_FILE_ALIGNMENT_INFORMATION:
3302 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3303 SIVAL(pdata,0,0); /* No alignment needed. */
3309 * NT4 server just returns "invalid query" to this - if we try to answer
3310 * it then NTws gets a BSOD! (tridge).
3311 * W2K seems to want this. JRA.
3313 case SMB_QUERY_FILE_STREAM_INFO:
3315 case SMB_FILE_STREAM_INFORMATION:
3316 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3320 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3321 SIVAL(pdata,0,0); /* ??? */
3322 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3323 SOFF_T(pdata,8,file_size);
3324 SIVAL(pdata,16,allocation_size);
3325 SIVAL(pdata,20,0); /* ??? */
3326 data_size = 24 + byte_len;
3330 case SMB_QUERY_COMPRESSION_INFO:
3331 case SMB_FILE_COMPRESSION_INFORMATION:
3332 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3333 SOFF_T(pdata,0,file_size);
3334 SIVAL(pdata,8,0); /* ??? */
3335 SIVAL(pdata,12,0); /* ??? */
3339 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3340 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3341 put_long_date(pdata,c_time);
3342 put_long_date(pdata+8,sbuf.st_atime);
3343 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3344 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3345 SIVAL(pdata,32,allocation_size);
3346 SOFF_T(pdata,40,file_size);
3347 SIVAL(pdata,48,mode);
3348 SIVAL(pdata,52,0); /* ??? */
3352 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3353 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3354 SIVAL(pdata,0,mode);
3360 * CIFS UNIX Extensions.
3363 case SMB_QUERY_FILE_UNIX_BASIC:
3365 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3366 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3368 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3371 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3374 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3375 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3376 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3379 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3383 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3387 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3390 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3394 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3398 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3401 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3405 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3408 data_size = PTR_DIFF(pdata,(*ppdata));
3412 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3414 for (i=0; i<100; i++)
3415 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3421 case SMB_QUERY_FILE_UNIX_LINK:
3425 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3427 if(!S_ISLNK(sbuf.st_mode))
3428 return(UNIXERROR(ERRSRV,ERRbadlink));
3430 return(UNIXERROR(ERRDOS,ERRbadlink));
3432 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3434 return(UNIXERROR(ERRDOS,ERRnoaccess));
3436 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3438 data_size = PTR_DIFF(pdata,(*ppdata));
3443 #if defined(HAVE_POSIX_ACLS)
3444 case SMB_QUERY_POSIX_ACL:
3446 SMB_ACL_T file_acl = NULL;
3447 SMB_ACL_T def_acl = NULL;
3448 uint16 num_file_acls = 0;
3449 uint16 num_def_acls = 0;
3451 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3452 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3454 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3457 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3458 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3460 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3463 if (S_ISDIR(sbuf.st_mode)) {
3464 if (fsp && fsp->is_directory) {
3465 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3467 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3469 def_acl = free_empty_sys_acl(conn, def_acl);
3472 num_file_acls = count_acl_entries(conn, file_acl);
3473 num_def_acls = count_acl_entries(conn, def_acl);
3475 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3476 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3478 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3479 SMB_POSIX_ACL_HEADER_SIZE) ));
3481 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3484 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3486 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3489 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3490 SSVAL(pdata,2,num_file_acls);
3491 SSVAL(pdata,4,num_def_acls);
3492 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3494 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3497 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3499 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3501 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3503 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3506 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3508 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3512 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3515 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3517 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3523 #if defined(DEVELOPER)
3524 case SMB_QUERY_POSIX_LOCK:
3526 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3528 SMB_BIG_UINT offset;
3530 enum brl_type lock_type;
3532 if (total_data != POSIX_LOCK_DATA_SIZE) {
3533 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3536 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3537 case POSIX_LOCK_TYPE_READ:
3538 lock_type = READ_LOCK;
3540 case POSIX_LOCK_TYPE_WRITE:
3541 lock_type = WRITE_LOCK;
3543 case POSIX_LOCK_TYPE_UNLOCK:
3545 /* There's no point in asking for an unlock... */
3546 talloc_destroy(data_ctx);
3547 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3550 lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3551 #if defined(HAVE_LONGLONG)
3552 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3553 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3554 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3555 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3556 #else /* HAVE_LONGLONG */
3557 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3558 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3559 #endif /* HAVE_LONGLONG */
3561 status = query_lock(fsp,
3568 if (ERROR_WAS_LOCK_DENIED(status)) {
3569 /* Here we need to report who has it locked... */
3570 data_size = POSIX_LOCK_DATA_SIZE;
3572 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3573 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3574 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3575 #if defined(HAVE_LONGLONG)
3576 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3577 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3578 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3579 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3580 #else /* HAVE_LONGLONG */
3581 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3582 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3583 #endif /* HAVE_LONGLONG */
3585 } else if (NT_STATUS_IS_OK(status)) {
3586 /* For success we just return a copy of what we sent
3587 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3588 data_size = POSIX_LOCK_DATA_SIZE;
3589 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3590 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3592 return ERROR_NT(status);
3599 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3602 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3607 /****************************************************************************
3608 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3610 ****************************************************************************/
3612 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3614 BOOL bad_path_oldname = False;
3615 BOOL bad_path_newname = False;
3616 SMB_STRUCT_STAT sbuf1, sbuf2;
3617 pstring last_component_oldname;
3618 pstring last_component_newname;
3619 NTSTATUS status = NT_STATUS_OK;
3625 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3626 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3629 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3630 if (bad_path_oldname) {
3631 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3634 /* Quick check for "." and ".." */
3635 if (last_component_oldname[0] == '.') {
3636 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3637 return NT_STATUS_OBJECT_NAME_INVALID;
3641 /* source must already exist. */
3642 if (!VALID_STAT(sbuf1)) {
3643 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3646 if (!check_name(oldname,conn)) {
3647 return NT_STATUS_ACCESS_DENIED;
3650 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3651 if (bad_path_newname) {
3652 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3655 /* Quick check for "." and ".." */
3656 if (last_component_newname[0] == '.') {
3657 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3658 return NT_STATUS_OBJECT_NAME_INVALID;
3662 /* Disallow if newname already exists. */
3663 if (VALID_STAT(sbuf2)) {
3664 return NT_STATUS_OBJECT_NAME_COLLISION;
3667 if (!check_name(newname,conn)) {
3668 return NT_STATUS_ACCESS_DENIED;
3671 /* No links from a directory. */
3672 if (S_ISDIR(sbuf1.st_mode)) {
3673 return NT_STATUS_FILE_IS_A_DIRECTORY;
3676 /* Ensure this is within the share. */
3677 if (!reduce_name(conn, oldname) != 0)
3678 return NT_STATUS_ACCESS_DENIED;
3680 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3682 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3683 status = map_nt_error_from_unix(errno);
3684 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3685 nt_errstr(status), newname, oldname));
3691 /****************************************************************************
3692 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3693 ****************************************************************************/
3695 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3696 unsigned int tran_call,
3697 char **pparams, int total_params, char **ppdata, int total_data,
3698 unsigned int max_data_bytes)
3700 char *params = *pparams;
3701 char *pdata = *ppdata;
3706 SMB_STRUCT_STAT sbuf;
3709 BOOL bad_path = False;
3710 files_struct *fsp = NULL;
3711 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3712 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3713 mode_t unixmode = 0;
3714 NTSTATUS status = NT_STATUS_OK;
3717 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3722 if (tran_call == TRANSACT2_SETFILEINFO) {
3723 if (total_params < 4) {
3724 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3727 fsp = file_fsp(params,0);
3728 info_level = SVAL(params,2);
3730 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3732 * This is actually a SETFILEINFO on a directory
3733 * handle (returned from an NT SMB). NT5.0 seems
3734 * to do this call. JRA.
3736 pstrcpy(fname, fsp->fsp_name);
3737 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3738 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3739 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3741 } else if (fsp && fsp->print_file) {
3743 * Doing a DELETE_ON_CLOSE should cancel a print job.
3745 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3746 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3748 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3751 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3754 return (UNIXERROR(ERRDOS,ERRbadpath));
3757 * Original code - this is an open file.
3759 CHECK_FSP(fsp,conn);
3761 pstrcpy(fname, fsp->fsp_name);
3764 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3765 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3766 return(UNIXERROR(ERRDOS,ERRbadfid));
3771 if (total_params < 6) {
3772 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3775 info_level = SVAL(params,0);
3776 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3777 if (!NT_STATUS_IS_OK(status)) {
3778 return ERROR_NT(status);
3780 unix_convert(fname,conn,0,&bad_path,&sbuf);
3782 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3786 * For CIFS UNIX extensions the target name may not exist.
3789 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3790 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3791 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3794 if(!check_name(fname, conn)) {
3795 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3800 if (!CAN_WRITE(conn))
3801 return ERROR_DOS(ERRSRV,ERRaccess);
3803 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3804 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3807 if (VALID_STAT(sbuf))
3808 unixmode = sbuf.st_mode;
3810 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3811 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3813 /* Realloc the parameter size */
3814 *pparams = SMB_REALLOC(*pparams,2);
3815 if (*pparams == NULL) {
3816 return ERROR_NT(NT_STATUS_NO_MEMORY);
3822 if (fsp && fsp->pending_modtime) {
3823 /* the pending modtime overrides the current modtime */
3824 sbuf.st_mtime = fsp->pending_modtime;
3827 size = get_file_size(sbuf);
3828 tvs.modtime = sbuf.st_mtime;
3829 tvs.actime = sbuf.st_atime;
3830 dosmode = dos_mode(conn,fname,&sbuf);
3831 unixmode = sbuf.st_mode;
3833 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3834 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3836 switch (info_level) {
3837 case SMB_INFO_STANDARD:
3839 if (total_data < 12) {
3840 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3844 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3846 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3850 case SMB_INFO_SET_EA:
3852 struct ea_list *ea_list = NULL;
3853 TALLOC_CTX *ctx = NULL;
3855 if (total_data < 10) {
3857 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3858 length. They seem to have no effect. Bug #3212. JRA */
3860 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3861 /* We're done. We only get EA info in this call. */
3863 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3867 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3870 if (IVAL(pdata,0) > total_data) {
3871 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3872 IVAL(pdata,0), (unsigned int)total_data));
3873 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3876 ctx = talloc_init("SMB_INFO_SET_EA");
3878 return ERROR_NT(NT_STATUS_NO_MEMORY);
3880 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3882 talloc_destroy(ctx);
3883 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3885 status = set_ea(conn, fsp, fname, ea_list);
3886 talloc_destroy(ctx);
3888 if (!NT_STATUS_IS_OK(status)) {
3889 return ERROR_NT(status);
3892 /* We're done. We only get EA info in this call. */
3894 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3899 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3900 /* XXXX um, i don't think this is right.
3901 it's also not in the cifs6.txt spec.
3903 case SMB_INFO_QUERY_EAS_FROM_LIST:
3904 if (total_data < 28)
3905 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3907 tvs.actime = make_unix_date2(pdata+8);
3908 tvs.modtime = make_unix_date2(pdata+12);
3909 size = IVAL(pdata,16);
3910 dosmode = IVAL(pdata,24);
3913 /* XXXX nor this. not in cifs6.txt, either. */
3914 case SMB_INFO_QUERY_ALL_EAS:
3915 if (total_data < 28)
3916 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3918 tvs.actime = make_unix_date2(pdata+8);
3919 tvs.modtime = make_unix_date2(pdata+12);
3920 size = IVAL(pdata,16);
3921 dosmode = IVAL(pdata,24);
3925 case SMB_SET_FILE_BASIC_INFO:
3926 case SMB_FILE_BASIC_INFORMATION:
3928 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3930 time_t changed_time;
3932 if (total_data < 36) {
3933 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3936 /* Ignore create time at offset pdata. */
3939 tvs.actime = interpret_long_date(pdata+8);
3941 write_time = interpret_long_date(pdata+16);
3942 changed_time = interpret_long_date(pdata+24);
3944 tvs.modtime = MIN(write_time, changed_time);
3946 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3947 tvs.modtime = write_time;
3949 /* Prefer a defined time to an undefined one. */
3950 if (null_mtime(tvs.modtime)) {
3951 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3955 dosmode = IVAL(pdata,32);
3959 case SMB_FILE_ALLOCATION_INFORMATION:
3960 case SMB_SET_FILE_ALLOCATION_INFO:
3963 SMB_BIG_UINT allocation_size;
3965 if (total_data < 8) {
3966 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3969 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3970 #ifdef LARGE_SMB_OFF_T
3971 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3972 #else /* LARGE_SMB_OFF_T */
3973 if (IVAL(pdata,4) != 0) {
3974 /* more than 32 bits? */
3975 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3977 #endif /* LARGE_SMB_OFF_T */
3978 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3979 fname, (double)allocation_size ));
3981 if (allocation_size) {
3982 allocation_size = smb_roundup(conn, allocation_size);
3985 if(allocation_size != get_file_size(sbuf)) {
3986 SMB_STRUCT_STAT new_sbuf;
3988 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3989 fname, (double)allocation_size ));
3992 files_struct *new_fsp = NULL;
3994 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3996 FILE_SHARE_READ|FILE_SHARE_WRITE,
3999 FILE_ATTRIBUTE_NORMAL,
4003 if (new_fsp == NULL) {
4004 return(UNIXERROR(ERRDOS,ERRbadpath));
4006 ret = vfs_allocate_file_space(new_fsp, allocation_size);
4007 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4008 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4009 new_fsp->fnum, strerror(errno)));
4012 close_file(new_fsp,NORMAL_CLOSE);
4014 ret = vfs_allocate_file_space(fsp, allocation_size);
4015 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4016 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4017 fsp->fnum, strerror(errno)));
4022 return ERROR_NT(NT_STATUS_DISK_FULL);
4024 /* Allocate can truncate size... */
4025 size = get_file_size(new_sbuf);
4031 case SMB_FILE_END_OF_FILE_INFORMATION:
4032 case SMB_SET_FILE_END_OF_FILE_INFO:
4034 if (total_data < 8) {
4035 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4038 size = IVAL(pdata,0);
4039 #ifdef LARGE_SMB_OFF_T
4040 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4041 #else /* LARGE_SMB_OFF_T */
4042 if (IVAL(pdata,4) != 0) {
4043 /* more than 32 bits? */
4044 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4046 #endif /* LARGE_SMB_OFF_T */
4047 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4051 case SMB_FILE_DISPOSITION_INFORMATION:
4052 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4054 BOOL delete_on_close;
4056 if (total_data < 1) {
4057 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4060 delete_on_close = (CVAL(pdata,0) ? True : False);
4062 /* Just ignore this set on a path. */
4063 if (tran_call != TRANSACT2_SETFILEINFO)
4067 return(UNIXERROR(ERRDOS,ERRbadfid));
4069 status = can_set_delete_on_close(fsp, delete_on_close,
4072 if (!NT_STATUS_IS_OK(status)) {
4073 return ERROR_NT(status);
4076 /* The set is across all open files on this dev/inode pair. */
4077 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4078 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4082 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4086 case SMB_FILE_POSITION_INFORMATION:
4088 SMB_BIG_UINT position_information;
4090 if (total_data < 8) {
4091 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4094 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4095 #ifdef LARGE_SMB_OFF_T
4096 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4097 #else /* LARGE_SMB_OFF_T */
4098 if (IVAL(pdata,4) != 0) {
4099 /* more than 32 bits? */
4100 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4102 #endif /* LARGE_SMB_OFF_T */
4103 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4104 fname, (double)position_information ));
4106 fsp->fh->position_information = position_information;
4109 /* We're done. We only get position info in this call. */
4111 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4115 /* From tridge Samba4 :
4116 * MODE_INFORMATION in setfileinfo (I have no
4117 * idea what "mode information" on a file is - it takes a value of 0,
4118 * 2, 4 or 6. What could it be?).
4121 case SMB_FILE_MODE_INFORMATION:
4125 if (total_data < 4) {
4126 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4128 mode = IVAL(pdata,0);
4129 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4130 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4133 /* We're done. We only get mode info in this call. */
4135 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4140 * CIFS UNIX extensions.
4143 case SMB_SET_FILE_UNIX_BASIC:
4145 uint32 raw_unixmode;
4147 if (total_data < 100) {
4148 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4151 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4152 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4153 size=IVAL(pdata,0); /* first 8 Bytes are size */
4154 #ifdef LARGE_SMB_OFF_T
4155 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4156 #else /* LARGE_SMB_OFF_T */
4157 if (IVAL(pdata,4) != 0) {
4158 /* more than 32 bits? */
4159 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4161 #endif /* LARGE_SMB_OFF_T */
4163 pdata+=24; /* ctime & st_blocks are not changed */
4164 tvs.actime = interpret_long_date(pdata); /* access_time */
4165 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4167 set_owner = (uid_t)IVAL(pdata,0);
4169 set_grp = (gid_t)IVAL(pdata,0);
4171 raw_unixmode = IVAL(pdata,28);
4172 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4173 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4175 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4176 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4177 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4179 if (!VALID_STAT(sbuf)) {
4182 * The only valid use of this is to create character and block
4183 * devices, and named pipes. This is deprecated (IMHO) and
4184 * a new info level should be used for mknod. JRA.
4187 uint32 file_type = IVAL(pdata,0);
4188 #if defined(HAVE_MAKEDEV)
4189 uint32 dev_major = IVAL(pdata,4);
4190 uint32 dev_minor = IVAL(pdata,12);
4193 uid_t myuid = geteuid();
4194 gid_t mygid = getegid();
4195 SMB_DEV_T dev = (SMB_DEV_T)0;
4197 if (tran_call == TRANSACT2_SETFILEINFO)
4198 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4200 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4201 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4204 #if defined(HAVE_MAKEDEV)
4205 dev = makedev(dev_major, dev_minor);
4208 /* We can only create as the owner/group we are. */
4210 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4211 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4212 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4213 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4215 switch (file_type) {
4216 #if defined(S_IFIFO)
4217 case UNIX_TYPE_FIFO:
4218 unixmode |= S_IFIFO;
4221 #if defined(S_IFSOCK)
4222 case UNIX_TYPE_SOCKET:
4223 unixmode |= S_IFSOCK;
4226 #if defined(S_IFCHR)
4227 case UNIX_TYPE_CHARDEV:
4228 unixmode |= S_IFCHR;
4231 #if defined(S_IFBLK)
4232 case UNIX_TYPE_BLKDEV:
4233 unixmode |= S_IFBLK;
4237 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4240 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4241 0%o for file %s\n", (double)dev, unixmode, fname ));
4243 /* Ok - do the mknod. */
4244 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4245 return(UNIXERROR(ERRDOS,ERRnoaccess));
4247 inherit_access_acl(conn, fname, unixmode);
4250 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4255 * Deal with the UNIX specific mode set.
4258 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4259 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4260 (unsigned int)unixmode, fname ));
4261 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4262 return(UNIXERROR(ERRDOS,ERRnoaccess));
4266 * Deal with the UNIX specific uid set.
4269 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4270 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4271 (unsigned int)set_owner, fname ));
4272 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4273 return(UNIXERROR(ERRDOS,ERRnoaccess));
4277 * Deal with the UNIX specific gid set.
4280 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4281 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4282 (unsigned int)set_owner, fname ));
4283 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4284 return(UNIXERROR(ERRDOS,ERRnoaccess));
4289 case SMB_SET_FILE_UNIX_LINK:
4291 pstring link_target;
4292 char *newname = fname;
4294 /* Set a symbolic link. */
4295 /* Don't allow this if follow links is false. */
4297 if (!lp_symlinks(SNUM(conn)))
4298 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4300 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4302 /* !widelinks forces the target path to be within the share. */
4303 /* This means we can interpret the target as a pathname. */
4304 if (!lp_widelinks(SNUM(conn))) {
4306 char *last_dirp = NULL;
4308 unix_format(link_target);
4309 if (*link_target == '/') {
4310 /* No absolute paths allowed. */
4311 return(UNIXERROR(ERRDOS,ERRnoaccess));
4313 pstrcpy(rel_name, newname);
4314 last_dirp = strrchr_m(rel_name, '/');
4316 last_dirp[1] = '\0';
4318 pstrcpy(rel_name, "./");
4320 pstrcat(rel_name, link_target);
4322 if (!check_name(rel_name, conn)) {
4323 return(UNIXERROR(ERRDOS,ERRnoaccess));
4327 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4328 fname, link_target ));
4330 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4331 return(UNIXERROR(ERRDOS,ERRnoaccess));
4333 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4337 case SMB_SET_FILE_UNIX_HLINK:
4340 char *newname = fname;
4342 /* Set a hard link. */
4343 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4344 if (!NT_STATUS_IS_OK(status)) {
4345 return ERROR_NT(status);
4348 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4351 status = hardlink_internals(conn, oldname, newname);
4352 if (!NT_STATUS_IS_OK(status)) {
4353 return ERROR_NT(status);
4357 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4361 case SMB_FILE_RENAME_INFORMATION:
4370 if (total_data < 12) {
4371 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4374 overwrite = (CVAL(pdata,0) ? True : False);
4375 root_fid = IVAL(pdata,4);
4376 len = IVAL(pdata,8);
4377 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4378 if (!NT_STATUS_IS_OK(status)) {
4379 return ERROR_NT(status);
4382 /* Check the new name has no '/' characters. */
4383 if (strchr_m(newname, '/'))
4384 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4386 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4388 /* Create the base directory. */
4389 pstrcpy(base_name, fname);
4390 p = strrchr_m(base_name, '/');
4393 /* Append the new name. */
4394 pstrcat(base_name, "/");
4395 pstrcat(base_name, newname);
4398 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4399 fsp->fnum, fsp->fsp_name, base_name ));
4400 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4402 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4404 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4406 if (!NT_STATUS_IS_OK(status)) {
4407 return ERROR_NT(status);
4409 process_pending_change_notify_queue((time_t)0);
4411 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4415 #if defined(HAVE_POSIX_ACLS)
4416 case SMB_SET_POSIX_ACL:
4418 uint16 posix_acl_version;
4419 uint16 num_file_acls;
4420 uint16 num_def_acls;
4421 BOOL valid_file_acls = True;
4422 BOOL valid_def_acls = True;
4424 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4425 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4427 posix_acl_version = SVAL(pdata,0);
4428 num_file_acls = SVAL(pdata,2);
4429 num_def_acls = SVAL(pdata,4);
4431 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4432 valid_file_acls = False;
4436 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4437 valid_def_acls = False;
4441 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4442 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4445 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4446 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4447 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4450 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4451 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4452 return(UNIXERROR(ERRDOS,ERRnoaccess));
4455 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4456 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4457 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4458 return(UNIXERROR(ERRDOS,ERRnoaccess));
4462 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4467 #if defined(DEVELOPER)
4468 case SMB_SET_POSIX_LOCK:
4471 SMB_BIG_UINT offset;
4474 enum brl_type lock_type;
4477 if (fsp == NULL || fsp->fh->fd == -1) {
4478 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4481 if (total_data != POSIX_LOCK_DATA_SIZE) {
4482 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4485 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4486 case POSIX_LOCK_TYPE_READ:
4487 lock_type = READ_LOCK;
4489 case POSIX_LOCK_TYPE_WRITE:
4490 /* Return the right POSIX-mappable error code for files opened read-only. */
4491 if (!fsp->can_write) {
4492 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4494 lock_type = WRITE_LOCK;
4496 case POSIX_LOCK_TYPE_UNLOCK:
4497 lock_type = UNLOCK_LOCK;
4500 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4503 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4504 lock_blocking = False;
4505 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4506 lock_blocking = True;
4508 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4511 lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4512 #if defined(HAVE_LONGLONG)
4513 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4514 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4515 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4516 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4517 #else /* HAVE_LONGLONG */
4518 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4519 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4520 #endif /* HAVE_LONGLONG */
4522 if (lock_type == UNLOCK_LOCK) {
4523 status = do_unlock(fsp,
4529 status = do_lock(fsp,
4537 /* TODO: Deal with rescheduling blocking lock fail here... */
4538 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4540 * A blocking lock was requested. Package up
4541 * this smb into a queued request and push it
4542 * onto the blocking lock queue.
4544 if(push_blocking_lock_request(inbuf, length,
4546 -1, /* infinite timeout. */
4558 if (!NT_STATUS_IS_OK(status)) {
4559 return ERROR_NT(status);
4563 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4569 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4572 /* get some defaults (no modifications) if any info is zero or -1. */
4573 if (null_mtime(tvs.actime)) {
4574 tvs.actime = sbuf.st_atime;
4577 if (null_mtime(tvs.modtime)) {
4578 tvs.modtime = sbuf.st_mtime;
4581 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4582 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4583 DEBUG(6,("size: %.0f ", (double)size));
4586 if (S_ISDIR(sbuf.st_mode))
4592 DEBUG(6,("dosmode: %x\n" , dosmode));
4594 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4595 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4596 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4597 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4600 * Only do this test if we are not explicitly
4601 * changing the size of a file.
4604 size = get_file_size(sbuf);
4608 * Try and set the times, size and mode of this file -
4609 * if they are different from the current values
4612 /* check the mode isn't different, before changing it */
4613 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4615 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4617 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4618 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4619 return(UNIXERROR(ERRDOS,ERRnoaccess));
4624 if (size != get_file_size(sbuf)) {
4628 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4629 fname, (double)size ));
4632 files_struct *new_fsp = NULL;
4634 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4636 FILE_SHARE_READ|FILE_SHARE_WRITE,
4639 FILE_ATTRIBUTE_NORMAL,
4643 if (new_fsp == NULL) {
4644 return(UNIXERROR(ERRDOS,ERRbadpath));
4646 ret = vfs_set_filelen(new_fsp, size);
4647 close_file(new_fsp,NORMAL_CLOSE);
4649 ret = vfs_set_filelen(fsp, size);
4653 return (UNIXERROR(ERRHRD,ERRdiskfull));
4658 * Finally the times.
4660 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4663 * This was a setfileinfo on an open file.
4664 * NT does this a lot. We also need to
4665 * set the time here, as it can be read by
4666 * FindFirst/FindNext and with the patch for bug #2045
4667 * in smbd/fileio.c it ensures that this timestamp is
4668 * kept sticky even after a write. We save the request
4669 * away and will set it on file close and after a write. JRA.
4672 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4673 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4674 fsp_set_pending_modtime(fsp, tvs.modtime);
4678 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4680 if(file_utime(conn, fname, &tvs)!=0) {
4681 return(UNIXERROR(ERRDOS,ERRnoaccess));
4686 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4691 /****************************************************************************
4692 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4693 ****************************************************************************/
4695 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4696 char **pparams, int total_params, char **ppdata, int total_data,
4697 unsigned int max_data_bytes)
4699 char *params = *pparams;
4700 char *pdata = *ppdata;
4703 SMB_STRUCT_STAT sbuf;
4704 BOOL bad_path = False;
4705 NTSTATUS status = NT_STATUS_OK;
4706 TALLOC_CTX *ctx = NULL;
4707 struct ea_list *ea_list = NULL;
4709 if (!CAN_WRITE(conn))
4710 return ERROR_DOS(ERRSRV,ERRaccess);
4712 if (total_params < 4) {
4713 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4716 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
4717 if (!NT_STATUS_IS_OK(status)) {
4718 return ERROR_NT(status);
4721 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4723 unix_convert(directory,conn,0,&bad_path,&sbuf);
4725 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4728 /* Any data in this call is an EA list. */
4729 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4730 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4734 * OS/2 workplace shell seems to send SET_EA requests of "null"
4735 * length (4 bytes containing IVAL 4).
4736 * They seem to have no effect. Bug #3212. JRA.
4739 if (total_data != 4) {
4740 if (total_data < 10) {
4741 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4744 if (IVAL(pdata,0) > total_data) {
4745 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4746 IVAL(pdata,0), (unsigned int)total_data));
4747 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4750 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4752 return ERROR_NT(NT_STATUS_NO_MEMORY);
4754 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4756 talloc_destroy(ctx);
4757 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4759 } else if (IVAL(pdata,0) != 4) {
4760 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4763 if (check_name(directory,conn)) {
4764 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4768 talloc_destroy(ctx);
4769 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4770 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4773 /* Try and set any given EA. */
4775 status = set_ea(conn, NULL, directory, ea_list);
4776 talloc_destroy(ctx);
4777 if (!NT_STATUS_IS_OK(status)) {
4778 return ERROR_NT(status);
4782 /* Realloc the parameter and data sizes */
4783 *pparams = SMB_REALLOC(*pparams,2);
4784 if(*pparams == NULL) {
4785 return ERROR_NT(NT_STATUS_NO_MEMORY);
4791 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4796 /****************************************************************************
4797 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4798 We don't actually do this - we just send a null response.
4799 ****************************************************************************/
4801 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4802 char **pparams, int total_params, char **ppdata, int total_data,
4803 unsigned int max_data_bytes)
4805 static uint16 fnf_handle = 257;
4806 char *params = *pparams;
4809 if (total_params < 6) {
4810 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4813 info_level = SVAL(params,4);
4814 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4816 switch (info_level) {
4821 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4824 /* Realloc the parameter and data sizes */
4825 *pparams = SMB_REALLOC(*pparams,6);
4826 if (*pparams == NULL) {
4827 return ERROR_NT(NT_STATUS_NO_MEMORY);
4831 SSVAL(params,0,fnf_handle);
4832 SSVAL(params,2,0); /* No changes */
4833 SSVAL(params,4,0); /* No EA errors */
4840 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4845 /****************************************************************************
4846 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4847 changes). Currently this does nothing.
4848 ****************************************************************************/
4850 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4851 char **pparams, int total_params, char **ppdata, int total_data,
4852 unsigned int max_data_bytes)
4854 char *params = *pparams;
4856 DEBUG(3,("call_trans2findnotifynext\n"));
4858 /* Realloc the parameter and data sizes */
4859 *pparams = SMB_REALLOC(*pparams,4);
4860 if (*pparams == NULL) {
4861 return ERROR_NT(NT_STATUS_NO_MEMORY);
4865 SSVAL(params,0,0); /* No changes */
4866 SSVAL(params,2,0); /* No EA errors */
4868 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4873 /****************************************************************************
4874 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4875 ****************************************************************************/
4877 static int call_trans2getdfsreferral(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;
4884 int max_referral_level;
4886 DEBUG(10,("call_trans2getdfsreferral\n"));
4888 if (total_params < 2) {
4889 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4892 max_referral_level = SVAL(params,0);
4894 if(!lp_host_msdfs())
4895 return ERROR_DOS(ERRDOS,ERRbadfunc);
4897 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4898 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4899 return UNIXERROR(ERRDOS,ERRbadfile);
4901 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4902 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4907 #define LMCAT_SPL 0x53
4908 #define LMFUNC_GETJOBID 0x60
4910 /****************************************************************************
4911 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4912 ****************************************************************************/
4914 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4915 char **pparams, int total_params, char **ppdata, int total_data,
4916 unsigned int max_data_bytes)
4918 char *pdata = *ppdata;
4919 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4921 /* check for an invalid fid before proceeding */
4924 return(ERROR_DOS(ERRDOS,ERRbadfid));
4926 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4927 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4928 *ppdata = SMB_REALLOC(*ppdata, 32);
4929 if (*ppdata == NULL) {
4930 return ERROR_NT(NT_STATUS_NO_MEMORY);
4934 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4935 CAN ACCEPT THIS IN UNICODE. JRA. */
4937 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4938 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4939 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4940 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4943 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4944 return ERROR_DOS(ERRSRV,ERRerror);
4948 /****************************************************************************
4949 Reply to a SMBfindclose (stop trans2 directory search).
4950 ****************************************************************************/
4952 int reply_findclose(connection_struct *conn,
4953 char *inbuf,char *outbuf,int length,int bufsize)
4956 int dptr_num=SVALS(inbuf,smb_vwv0);
4957 START_PROFILE(SMBfindclose);
4959 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4961 dptr_close(&dptr_num);
4963 outsize = set_message(outbuf,0,0,True);
4965 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4967 END_PROFILE(SMBfindclose);
4971 /****************************************************************************
4972 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4973 ****************************************************************************/
4975 int reply_findnclose(connection_struct *conn,
4976 char *inbuf,char *outbuf,int length,int bufsize)
4980 START_PROFILE(SMBfindnclose);
4982 dptr_num = SVAL(inbuf,smb_vwv0);
4984 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4986 /* We never give out valid handles for a
4987 findnotifyfirst - so any dptr_num is ok here.
4990 outsize = set_message(outbuf,0,0,True);
4992 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4994 END_PROFILE(SMBfindnclose);
4998 int handle_trans2(connection_struct *conn,
4999 struct trans_state *state,
5000 char *inbuf, char *outbuf, int size, int bufsize)
5004 if (Protocol >= PROTOCOL_NT1) {
5005 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5008 /* Now we must call the relevant TRANS2 function */
5009 switch(state->call) {
5010 case TRANSACT2_OPEN:
5011 START_PROFILE_NESTED(Trans2_open);
5012 outsize = call_trans2open(
5013 conn, inbuf, outbuf, bufsize,
5014 &state->param, state->total_param,
5015 &state->data, state->total_data,
5016 state->max_data_return);
5017 END_PROFILE_NESTED(Trans2_open);
5020 case TRANSACT2_FINDFIRST:
5021 START_PROFILE_NESTED(Trans2_findfirst);
5022 outsize = call_trans2findfirst(
5023 conn, inbuf, outbuf, bufsize,
5024 &state->param, state->total_param,
5025 &state->data, state->total_data,
5026 state->max_data_return);
5027 END_PROFILE_NESTED(Trans2_findfirst);
5030 case TRANSACT2_FINDNEXT:
5031 START_PROFILE_NESTED(Trans2_findnext);
5032 outsize = call_trans2findnext(
5033 conn, inbuf, outbuf, size, bufsize,
5034 &state->param, state->total_param,
5035 &state->data, state->total_data,
5036 state->max_data_return);
5037 END_PROFILE_NESTED(Trans2_findnext);
5040 case TRANSACT2_QFSINFO:
5041 START_PROFILE_NESTED(Trans2_qfsinfo);
5042 outsize = call_trans2qfsinfo(
5043 conn, inbuf, outbuf, size, bufsize,
5044 &state->param, state->total_param,
5045 &state->data, state->total_data,
5046 state->max_data_return);
5047 END_PROFILE_NESTED(Trans2_qfsinfo);
5050 case TRANSACT2_SETFSINFO:
5051 START_PROFILE_NESTED(Trans2_setfsinfo);
5052 outsize = call_trans2setfsinfo(
5053 conn, inbuf, outbuf, size, bufsize,
5054 &state->param, state->total_param,
5055 &state->data, state->total_data,
5056 state->max_data_return);
5057 END_PROFILE_NESTED(Trans2_setfsinfo);
5060 case TRANSACT2_QPATHINFO:
5061 case TRANSACT2_QFILEINFO:
5062 START_PROFILE_NESTED(Trans2_qpathinfo);
5063 outsize = call_trans2qfilepathinfo(
5064 conn, inbuf, outbuf, size, bufsize, state->call,
5065 &state->param, state->total_param,
5066 &state->data, state->total_data,
5067 state->max_data_return);
5068 END_PROFILE_NESTED(Trans2_qpathinfo);
5070 case TRANSACT2_SETPATHINFO:
5071 case TRANSACT2_SETFILEINFO:
5072 START_PROFILE_NESTED(Trans2_setpathinfo);
5073 outsize = call_trans2setfilepathinfo(
5074 conn, inbuf, outbuf, size, bufsize, state->call,
5075 &state->param, state->total_param,
5076 &state->data, state->total_data,
5077 state->max_data_return);
5078 END_PROFILE_NESTED(Trans2_setpathinfo);
5081 case TRANSACT2_FINDNOTIFYFIRST:
5082 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5083 outsize = call_trans2findnotifyfirst(
5084 conn, inbuf, outbuf, size, bufsize,
5085 &state->param, state->total_param,
5086 &state->data, state->total_data,
5087 state->max_data_return);
5088 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5091 case TRANSACT2_FINDNOTIFYNEXT:
5092 START_PROFILE_NESTED(Trans2_findnotifynext);
5093 outsize = call_trans2findnotifynext(
5094 conn, inbuf, outbuf, size, bufsize,
5095 &state->param, state->total_param,
5096 &state->data, state->total_data,
5097 state->max_data_return);
5098 END_PROFILE_NESTED(Trans2_findnotifynext);
5100 case TRANSACT2_MKDIR:
5101 START_PROFILE_NESTED(Trans2_mkdir);
5102 outsize = call_trans2mkdir(
5103 conn, inbuf, outbuf, size, bufsize,
5104 &state->param, state->total_param,
5105 &state->data, state->total_data,
5106 state->max_data_return);
5107 END_PROFILE_NESTED(Trans2_mkdir);
5110 case TRANSACT2_GET_DFS_REFERRAL:
5111 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5112 outsize = call_trans2getdfsreferral(
5113 conn, inbuf, outbuf, size, bufsize,
5114 &state->param, state->total_param,
5115 &state->data, state->total_data,
5116 state->max_data_return);
5117 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5119 case TRANSACT2_IOCTL:
5120 START_PROFILE_NESTED(Trans2_ioctl);
5121 outsize = call_trans2ioctl(
5122 conn, inbuf, outbuf, size, bufsize,
5123 &state->param, state->total_param,
5124 &state->data, state->total_data,
5125 state->max_data_return);
5126 END_PROFILE_NESTED(Trans2_ioctl);
5129 /* Error in request */
5130 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5131 outsize = ERROR_DOS(ERRSRV,ERRerror);
5136 /****************************************************************************
5137 Reply to a SMBtrans2.
5138 ****************************************************************************/
5140 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5141 int size, int bufsize)
5144 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5145 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5146 unsigned int psoff = SVAL(inbuf, smb_psoff);
5147 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5148 unsigned int tran_call = SVAL(inbuf, smb_setup0);
5149 struct trans_state *state;
5152 START_PROFILE(SMBtrans2);
5154 if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
5155 SVAL(inbuf, smb_mid)))) {
5156 DEBUG(2, ("Got invalid trans2 request: %s\n",
5157 nt_errstr(result)));
5158 END_PROFILE(SMBtrans2);
5159 return ERROR_NT(result);
5162 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5163 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5164 END_PROFILE(SMBtrans2);
5165 return ERROR_DOS(ERRSRV,ERRaccess);
5168 if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
5169 DEBUG(0, ("talloc failed\n"));
5170 END_PROFILE(SMBtrans2);
5171 return ERROR_NT(NT_STATUS_NO_MEMORY);
5174 state->cmd = SMBtrans2;
5176 state->mid = SVAL(inbuf, smb_mid);
5177 state->vuid = SVAL(inbuf, smb_uid);
5178 state->setup_count = SVAL(inbuf, smb_suwcnt);
5179 state->total_param = SVAL(inbuf, smb_tpscnt);
5180 state->param = NULL;
5181 state->total_data = SVAL(inbuf, smb_tdscnt);
5183 state->max_param_return = SVAL(inbuf, smb_mprcnt);
5184 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
5185 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5186 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5187 state->one_way = BITSETW(inbuf+smb_vwv5,1);
5189 state->call = tran_call;
5191 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5192 is so as a sanity check */
5193 if (state->setup_count != 1) {
5195 * Need to have rc=0 for ioctl to get job id for OS/2.
5196 * Network printing will fail if function is not successful.
5197 * Similar function in reply.c will be used if protocol
5198 * is LANMAN1.0 instead of LM1.2X002.
5199 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5200 * outbuf doesn't have to be set(only job id is used).
5202 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5203 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5204 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5205 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5207 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5208 DEBUG(2,("Transaction is %d\n",tran_call));
5209 END_PROFILE(SMBtrans2);
5210 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5214 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5217 if (state->total_data) {
5218 /* Can't use talloc here, the core routines do realloc on the
5219 * params and data. */
5220 state->data = SMB_MALLOC(state->total_data);
5221 if (state->data == NULL) {
5222 DEBUG(0,("reply_trans2: data malloc fail for %u "
5223 "bytes !\n", state->total_data));
5225 END_PROFILE(SMBtrans2);
5226 return(ERROR_DOS(ERRDOS,ERRnomem));
5228 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5230 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5231 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5234 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5237 if (state->total_param) {
5238 /* Can't use talloc here, the core routines do realloc on the
5239 * params and data. */
5240 state->param = SMB_MALLOC(state->total_param);
5241 if (state->param == NULL) {
5242 DEBUG(0,("reply_trans: param malloc fail for %u "
5243 "bytes !\n", state->total_param));
5244 SAFE_FREE(state->data);
5246 END_PROFILE(SMBtrans);
5247 return(ERROR_DOS(ERRDOS,ERRnomem));
5249 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5251 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5252 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5255 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5258 state->received_data = dscnt;
5259 state->received_param = pscnt;
5261 if ((state->received_param == state->total_param) &&
5262 (state->received_data == state->total_data)) {
5264 outsize = handle_trans2(conn, state, inbuf, outbuf,
5266 SAFE_FREE(state->data);
5267 SAFE_FREE(state->param);
5269 END_PROFILE(SMBtrans);
5273 DLIST_ADD(conn->pending_trans, state);
5275 /* We need to send an interim response then receive the rest
5276 of the parameter/data bytes */
5277 outsize = set_message(outbuf,0,0,True);
5279 END_PROFILE(SMBtrans2);
5284 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5285 SAFE_FREE(state->data);
5286 SAFE_FREE(state->param);
5288 END_PROFILE(SMBtrans2);
5289 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5293 /****************************************************************************
5294 Reply to a SMBtranss2
5295 ****************************************************************************/
5297 int reply_transs2(connection_struct *conn,
5298 char *inbuf,char *outbuf,int size,int bufsize)
5301 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5302 struct trans_state *state;
5304 START_PROFILE(SMBtranss2);
5308 for (state = conn->pending_trans; state != NULL;
5309 state = state->next) {
5310 if (state->mid == SVAL(inbuf,smb_mid)) {
5315 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5316 END_PROFILE(SMBtranss2);
5317 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5320 /* Revise state->total_param and state->total_data in case they have
5321 changed downwards */
5323 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5324 state->total_param = SVAL(inbuf, smb_tpscnt);
5325 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5326 state->total_data = SVAL(inbuf, smb_tdscnt);
5328 pcnt = SVAL(inbuf, smb_spscnt);
5329 poff = SVAL(inbuf, smb_spsoff);
5330 pdisp = SVAL(inbuf, smb_spsdisp);
5332 dcnt = SVAL(inbuf, smb_sdscnt);
5333 doff = SVAL(inbuf, smb_sdsoff);
5334 ddisp = SVAL(inbuf, smb_sdsdisp);
5336 state->received_param += pcnt;
5337 state->received_data += dcnt;
5339 if ((state->received_data > state->total_data) ||
5340 (state->received_param > state->total_param))
5344 if (pdisp+pcnt > state->total_param)
5346 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5348 if (pdisp > state->total_param)
5350 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5351 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5353 if (state->param + pdisp < state->param)
5356 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5361 if (ddisp+dcnt > state->total_data)
5363 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5365 if (ddisp > state->total_data)
5367 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5368 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5370 if (state->data + ddisp < state->data)
5373 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5377 if ((state->received_param < state->total_param) ||
5378 (state->received_data < state->total_data)) {
5379 END_PROFILE(SMBtranss);
5383 /* construct_reply_common has done us the favor to pre-fill the
5384 * command field with SMBtranss2 which is wrong :-)
5386 SCVAL(outbuf,smb_com,SMBtrans2);
5388 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5390 DLIST_REMOVE(conn->pending_trans, state);
5391 SAFE_FREE(state->data);
5392 SAFE_FREE(state->param);
5396 END_PROFILE(SMBtranss);
5397 return(ERROR_DOS(ERRSRV,ERRnosupport));
5400 END_PROFILE(SMBtranss2);
5405 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5406 DLIST_REMOVE(conn->pending_trans, state);
5407 SAFE_FREE(state->data);
5408 SAFE_FREE(state->param);
5410 END_PROFILE(SMBtranss2);
5411 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);