2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern enum protocol_types Protocol;
27 extern int smb_read_error;
28 extern int global_oplock_break;
29 extern uint32 global_client_caps;
30 extern struct current_user current_user;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 /********************************************************************
36 Roundup a value to the nearest allocation roundup size boundary.
37 Only do this for Windows clients.
38 ********************************************************************/
40 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
42 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
44 /* Only roundup for Windows clients. */
45 enum remote_arch_types ra_type = get_remote_arch();
46 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
47 val = SMB_ROUNDUP(val,rval);
52 /********************************************************************
53 Given a stat buffer return the allocated size on disk, taking into
55 ********************************************************************/
57 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
61 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
62 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
64 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
67 if (!ret && fsp && fsp->initial_allocation_size)
68 ret = fsp->initial_allocation_size;
70 return smb_roundup(conn, ret);
73 /****************************************************************************
74 Utility functions for dealing with extended attributes.
75 ****************************************************************************/
77 static const char *prohibited_ea_names[] = {
78 SAMBA_POSIX_INHERITANCE_EA_NAME,
79 SAMBA_XATTR_DOS_ATTRIB,
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static BOOL samba_private_attr_name(const char *unix_ea_name)
91 for (i = 0; prohibited_ea_names[i]; i++) {
92 if (strequal( prohibited_ea_names[i], unix_ea_name))
98 /****************************************************************************
99 Get one EA value. Fill in a struct ea_struct.
100 ****************************************************************************/
102 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
103 const char *fname, char *ea_name, struct ea_struct *pea)
105 /* Get the value of this xattr. Max size is 64k. */
106 size_t attr_size = 256;
112 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
117 if (fsp && fsp->fd != -1) {
118 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
120 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
123 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
132 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
133 dump_data(10, val, sizeret);
136 if (strnequal(ea_name, "user.", 5)) {
137 pea->name = &ea_name[5];
141 pea->value.data = (unsigned char *)val;
142 pea->value.length = (size_t)sizeret;
146 /****************************************************************************
147 Return a linked list of the total EA's. Plus the total size
148 ****************************************************************************/
150 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
151 const char *fname, size_t *pea_total_len)
153 /* Get a list of all xattrs. Max namesize is 64k. */
154 size_t ea_namelist_size = 1024;
159 struct ea_list *ea_list_head = NULL;
163 if (!lp_ea_support(SNUM(conn))) {
167 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
168 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
169 if (fsp && fsp->fd != -1) {
170 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
172 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
175 if (sizeret == -1 && errno == ERANGE) {
176 ea_namelist_size *= 2;
185 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %d\n", sizeret ));
188 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
189 struct ea_list *listp, *tmp;
191 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
194 listp = TALLOC_P(mem_ctx, struct ea_list);
198 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
204 push_ascii_fstring(dos_ea_name, listp->ea.name);
205 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
206 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
207 *pea_total_len, dos_ea_name,
208 (unsigned int)listp->ea.value.length ));
210 DLIST_ADD_END(ea_list_head, listp, tmp);
212 /* Add on 4 for total length. */
213 if (*pea_total_len) {
218 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", *pea_total_len));
222 /****************************************************************************
223 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
225 ****************************************************************************/
227 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
228 connection_struct *conn, struct ea_list *ea_list)
230 unsigned int ret_data_size = 4;
233 SMB_ASSERT(total_data_size >= 4);
235 if (!lp_ea_support(SNUM(conn))) {
240 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
243 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
244 dos_namelen = strlen(dos_ea_name);
245 if (dos_namelen > 255 || dos_namelen == 0) {
248 if (ea_list->ea.value.length > 65535) {
251 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
255 /* We know we have room. */
256 SCVAL(p,0,ea_list->ea.flags);
257 SCVAL(p,1,dos_namelen);
258 SSVAL(p,2,ea_list->ea.value.length);
259 fstrcpy(p+4, dos_ea_name);
260 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
262 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
263 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
266 ret_data_size = PTR_DIFF(p, pdata);
267 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
268 SIVAL(pdata,0,ret_data_size);
269 return ret_data_size;
272 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
274 size_t total_ea_len = 0;
275 TALLOC_CTX *mem_ctx = NULL;
277 if (!lp_ea_support(SNUM(conn))) {
280 mem_ctx = talloc_init("estimate_ea_size");
281 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
282 talloc_destroy(mem_ctx);
286 /****************************************************************************
287 Ensure the EA name is case insensitive by matching any existing EA name.
288 ****************************************************************************/
290 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
293 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
294 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
296 for (; ea_list; ea_list = ea_list->next) {
297 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
298 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
299 &unix_ea_name[5], ea_list->ea.name));
300 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
304 talloc_destroy(mem_ctx);
307 /****************************************************************************
308 Set or delete an extended attribute.
309 ****************************************************************************/
311 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
313 if (!lp_ea_support(SNUM(conn))) {
314 return NT_STATUS_EAS_NOT_SUPPORTED;
317 for (;ea_list; ea_list = ea_list->next) {
319 fstring unix_ea_name;
321 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
322 fstrcat(unix_ea_name, ea_list->ea.name);
324 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
326 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ea_list->ea.value.length));
328 if (samba_private_attr_name(unix_ea_name)) {
329 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
330 return NT_STATUS_ACCESS_DENIED;
333 if (ea_list->ea.value.length == 0) {
334 /* Remove the attribute. */
335 if (fsp && (fsp->fd != -1)) {
336 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
337 unix_ea_name, fsp->fsp_name));
338 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
340 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
341 unix_ea_name, fname));
342 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
345 /* Removing a non existent attribute always succeeds. */
346 if (ret == -1 && errno == ENOATTR) {
347 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
353 if (fsp && (fsp->fd != -1)) {
354 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
355 unix_ea_name, fsp->fsp_name));
356 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name,
357 ea_list->ea.value.data, ea_list->ea.value.length, 0);
359 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
360 unix_ea_name, fname));
361 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
362 ea_list->ea.value.data, ea_list->ea.value.length, 0);
368 if (errno == ENOTSUP) {
369 return NT_STATUS_EAS_NOT_SUPPORTED;
372 return map_nt_error_from_unix(errno);
378 /****************************************************************************
379 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
380 ****************************************************************************/
382 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
384 struct ea_list *ea_list_head = NULL;
387 while (offset + 2 < data_size) {
389 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
390 unsigned int namelen = CVAL(pdata,offset);
392 offset++; /* Go past the namelen byte. */
394 /* integer wrap paranioa. */
395 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
396 (offset > data_size) || (namelen > data_size) ||
397 (offset + namelen >= data_size)) {
400 /* Ensure the name is null terminated. */
401 if (pdata[offset + namelen] != '\0') {
404 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
409 offset += (namelen + 1); /* Go past the name + terminating zero. */
410 DLIST_ADD_END(ea_list_head, eal, tmp);
411 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
417 /****************************************************************************
418 Read one EA list entry from the buffer.
419 ****************************************************************************/
421 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
423 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
425 unsigned int namelen;
435 eal->ea.flags = CVAL(pdata,0);
436 namelen = CVAL(pdata,1);
437 val_len = SVAL(pdata,2);
439 if (4 + namelen + 1 + val_len > data_size) {
443 /* Ensure the name is null terminated. */
444 if (pdata[namelen + 4] != '\0') {
447 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
452 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
453 if (!eal->ea.value.data) {
457 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
459 /* Ensure we're null terminated just in case we print the value. */
460 eal->ea.value.data[val_len] = '\0';
461 /* But don't count the null. */
462 eal->ea.value.length--;
465 *pbytes_used = 4 + namelen + 1 + val_len;
468 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
469 dump_data(10, eal->ea.value.data, eal->ea.value.length);
474 /****************************************************************************
475 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
476 ****************************************************************************/
478 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
480 struct ea_list *ea_list_head = NULL;
482 size_t bytes_used = 0;
484 while (offset < data_size) {
486 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
492 DLIST_ADD_END(ea_list_head, eal, tmp);
493 offset += bytes_used;
499 /****************************************************************************
500 Count the total EA size needed.
501 ****************************************************************************/
503 static size_t ea_list_size(struct ea_list *ealist)
506 struct ea_list *listp;
509 for (listp = ealist; listp; listp = listp->next) {
510 push_ascii_fstring(dos_ea_name, listp->ea.name);
511 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
513 /* Add on 4 for total length. */
521 /****************************************************************************
522 Return a union of EA's from a file list and a list of names.
523 The TALLOC context for the two lists *MUST* be identical as we steal
524 memory from one list to add to another. JRA.
525 ****************************************************************************/
527 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
529 struct ea_list *nlistp, *flistp;
531 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
532 for (flistp = file_list; flistp; flistp = flistp->next) {
533 if (strequal(nlistp->ea.name, flistp->ea.name)) {
539 /* Copy the data from this entry. */
540 nlistp->ea.flags = flistp->ea.flags;
541 nlistp->ea.value = flistp->ea.value;
544 nlistp->ea.flags = 0;
545 ZERO_STRUCT(nlistp->ea.value);
549 *total_ea_len = ea_list_size(name_list);
553 /****************************************************************************
554 Send the required number of replies back.
555 We assume all fields other than the data fields are
556 set correctly for the type of call.
557 HACK ! Always assumes smb_setup field is zero.
558 ****************************************************************************/
560 static int send_trans2_replies(char *outbuf,
567 /* As we are using a protocol > LANMAN1 then the max_send
568 variable must have been set in the sessetupX call.
569 This takes precedence over the max_xmit field in the
570 global struct. These different max_xmit variables should
571 be merged as this is now too confusing */
574 int data_to_send = datasize;
575 int params_to_send = paramsize;
579 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
580 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
581 int data_alignment_offset = 0;
583 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
585 set_message(outbuf,10,0,True);
587 /* If there genuinely are no parameters or data to send just send the empty packet */
589 if(params_to_send == 0 && data_to_send == 0) {
590 if (!send_smb(smbd_server_fd(),outbuf))
591 exit_server("send_trans2_replies: send_smb failed.");
595 /* When sending params and data ensure that both are nicely aligned */
596 /* Only do this alignment when there is also data to send - else
597 can cause NT redirector problems. */
599 if (((params_to_send % 4) != 0) && (data_to_send != 0))
600 data_alignment_offset = 4 - (params_to_send % 4);
602 /* Space is bufsize minus Netbios over TCP header minus SMB header */
603 /* The alignment_offset is to align the param bytes on an even byte
604 boundary. NT 4.0 Beta needs this to work correctly. */
606 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
608 /* useable_space can never be more than max_send minus the alignment offset. */
610 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
612 while (params_to_send || data_to_send) {
613 /* Calculate whether we will totally or partially fill this packet */
615 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
617 /* We can never send more than useable_space */
619 * Note that 'useable_space' does not include the alignment offsets,
620 * but we must include the alignment offsets in the calculation of
621 * the length of the data we send over the wire, as the alignment offsets
622 * are sent here. Fix from Marc_Jacobsen@hp.com.
625 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
627 set_message(outbuf, 10, total_sent_thistime, True);
629 /* Set total params and data to be sent */
630 SSVAL(outbuf,smb_tprcnt,paramsize);
631 SSVAL(outbuf,smb_tdrcnt,datasize);
633 /* Calculate how many parameters and data we can fit into
634 * this packet. Parameters get precedence
637 params_sent_thistime = MIN(params_to_send,useable_space);
638 data_sent_thistime = useable_space - params_sent_thistime;
639 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
641 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
643 /* smb_proff is the offset from the start of the SMB header to the
644 parameter bytes, however the first 4 bytes of outbuf are
645 the Netbios over TCP header. Thus use smb_base() to subtract
646 them from the calculation */
648 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
650 if(params_sent_thistime == 0)
651 SSVAL(outbuf,smb_prdisp,0);
653 /* Absolute displacement of param bytes sent in this packet */
654 SSVAL(outbuf,smb_prdisp,pp - params);
656 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
657 if(data_sent_thistime == 0) {
658 SSVAL(outbuf,smb_droff,0);
659 SSVAL(outbuf,smb_drdisp, 0);
661 /* The offset of the data bytes is the offset of the
662 parameter bytes plus the number of parameters being sent this time */
663 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
664 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
665 SSVAL(outbuf,smb_drdisp, pd - pdata);
668 /* Copy the param bytes into the packet */
670 if(params_sent_thistime)
671 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
673 /* Copy in the data bytes */
674 if(data_sent_thistime)
675 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
676 data_alignment_offset,pd,data_sent_thistime);
678 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
679 params_sent_thistime, data_sent_thistime, useable_space));
680 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
681 params_to_send, data_to_send, paramsize, datasize));
683 /* Send the packet */
684 if (!send_smb(smbd_server_fd(),outbuf))
685 exit_server("send_trans2_replies: send_smb failed.");
687 pp += params_sent_thistime;
688 pd += data_sent_thistime;
690 params_to_send -= params_sent_thistime;
691 data_to_send -= data_sent_thistime;
694 if(params_to_send < 0 || data_to_send < 0) {
695 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
696 params_to_send, data_to_send));
704 /****************************************************************************
705 Reply to a TRANSACT2_OPEN.
706 ****************************************************************************/
708 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
709 char **pparams, int total_params, char **ppdata, int total_data,
710 unsigned int max_data_bytes)
712 char *params = *pparams;
713 char *pdata = *ppdata;
718 BOOL return_additional_info;
727 int fmode=0,mtime=0,rmode;
729 SMB_STRUCT_STAT sbuf;
731 BOOL bad_path = False;
733 TALLOC_CTX *ctx = NULL;
734 struct ea_list *ea_list = NULL;
738 * Ensure we have enough parameters to perform the operation.
741 if (total_params < 29) {
742 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
745 open_mode = SVAL(params, 2);
746 open_attr = SVAL(params,6);
747 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
749 return_additional_info = BITSETW(params,0);
750 open_sattr = SVAL(params, 4);
751 open_time = make_unix_date3(params+8);
753 open_ofun = SVAL(params,12);
754 open_size = IVAL(params,14);
758 return(ERROR_DOS(ERRSRV,ERRaccess));
760 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
761 if (!NT_STATUS_IS_OK(status)) {
762 return ERROR_NT(status);
765 DEBUG(3,("call_trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
766 fname,open_mode, open_attr, open_ofun, open_size));
768 /* XXXX we need to handle passed times, sattr and flags */
770 unix_convert(fname,conn,0,&bad_path,&sbuf);
772 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
775 if (!check_name(fname,conn)) {
776 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
779 /* Any data in this call is an EA list. */
780 if (total_data && !lp_ea_support(SNUM(conn))) {
781 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
785 if (total_data < 10) {
786 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
789 if (IVAL(pdata,0) > total_data) {
790 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
791 IVAL(pdata,0), (unsigned int)total_data));
792 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
795 ctx = talloc_init("TRANS2_OPEN_SET_EA");
797 return ERROR_NT(NT_STATUS_NO_MEMORY);
799 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
802 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
806 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
807 oplock_request, &rmode,&smb_action);
811 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
812 /* We have re-scheduled this call. */
813 clear_cached_errors();
816 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
819 size = get_file_size(sbuf);
820 fmode = dos_mode(conn,fname,&sbuf);
821 mtime = sbuf.st_mtime;
825 close_file(fsp,False);
826 return(ERROR_DOS(ERRDOS,ERRnoaccess));
829 if (total_data && smb_action == FILE_WAS_CREATED) {
830 status = set_ea(conn, fsp, fname, ea_list);
832 if (!NT_STATUS_IS_OK(status)) {
833 close_file(fsp,False);
834 return ERROR_NT(status);
838 /* Realloc the size of parameters and data we will return */
839 params = SMB_REALLOC(*pparams, 28);
840 if( params == NULL ) {
841 return ERROR_NT(NT_STATUS_NO_MEMORY);
845 memset((char *)params,'\0',28);
846 SSVAL(params,0,fsp->fnum);
847 SSVAL(params,2,fmode);
848 put_dos_date2(params,4, mtime);
849 SIVAL(params,8, (uint32)size);
850 SSVAL(params,12,rmode);
852 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
853 smb_action |= EXTENDED_OPLOCK_GRANTED;
855 SSVAL(params,18,smb_action);
858 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
860 SIVAL(params,20,inode);
862 /* Send the required number of replies */
863 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
868 /*********************************************************
869 Routine to check if a given string matches exactly.
870 as a special case a mask of "." does NOT match. That
871 is required for correct wildcard semantics
872 Case can be significant or not.
873 **********************************************************/
875 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
877 if (mask[0] == '.' && mask[1] == 0)
880 return strcmp(str,mask)==0;
881 if (StrCaseCmp(str,mask) != 0) {
884 if (ms_has_wild(str)) {
890 /****************************************************************************
891 Return the filetype for UNIX extensions.
892 ****************************************************************************/
894 static uint32 unix_filetype(mode_t mode)
897 return UNIX_TYPE_FILE;
898 else if(S_ISDIR(mode))
899 return UNIX_TYPE_DIR;
901 else if(S_ISLNK(mode))
902 return UNIX_TYPE_SYMLINK;
905 else if(S_ISCHR(mode))
906 return UNIX_TYPE_CHARDEV;
909 else if(S_ISBLK(mode))
910 return UNIX_TYPE_BLKDEV;
913 else if(S_ISFIFO(mode))
914 return UNIX_TYPE_FIFO;
917 else if(S_ISSOCK(mode))
918 return UNIX_TYPE_SOCKET;
921 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
922 return UNIX_TYPE_UNKNOWN;
925 /****************************************************************************
926 Map wire perms onto standard UNIX permissions. Obey share restrictions.
927 ****************************************************************************/
929 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
933 if (perms == SMB_MODE_NO_CHANGE)
936 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
937 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
938 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
939 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
940 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
941 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
942 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
943 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
944 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
946 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
949 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
952 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
955 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
956 ret &= lp_dir_mask(SNUM(conn));
957 /* Add in force bits */
958 ret |= lp_force_dir_mode(SNUM(conn));
960 /* Apply mode mask */
961 ret &= lp_create_mask(SNUM(conn));
962 /* Add in force bits */
963 ret |= lp_force_create_mode(SNUM(conn));
969 /****************************************************************************
970 Get a level dependent lanman2 dir entry.
971 ****************************************************************************/
973 static BOOL get_lanman2_dir_entry(connection_struct *conn,
974 void *inbuf, void *outbuf,
975 char *path_mask,int dirtype,int info_level,
976 int requires_resume_key,
977 BOOL dont_descend,char **ppdata,
978 char *base_data, int space_remaining,
979 BOOL *out_of_space, BOOL *got_exact_match,
980 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
984 SMB_STRUCT_STAT sbuf;
988 char *p, *q, *pdata = *ppdata;
992 SMB_OFF_T file_size = 0;
993 SMB_BIG_UINT allocation_size = 0;
995 time_t mdate=0, adate=0, cdate=0;
997 char *last_entry_ptr;
999 int nt_extmode; /* Used for NT connections instead of mode */
1000 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1003 *out_of_space = False;
1004 *got_exact_match = False;
1009 p = strrchr_m(path_mask,'/');
1012 pstrcpy(mask,"*.*");
1016 pstrcpy(mask, path_mask);
1021 /* Needed if we run out of space */
1022 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1023 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1026 * Due to bugs in NT client redirectors we are not using
1027 * resume keys any more - set them to zero.
1028 * Check out the related comments in findfirst/findnext.
1034 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1035 (long)conn->dirptr,curr_dirpos));
1040 pstrcpy(fname,dname);
1042 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1043 got_match = mask_match(fname, mask, conn->case_sensitive);
1045 if(!got_match && !mangle_is_8_3(fname, False)) {
1048 * It turns out that NT matches wildcards against
1049 * both long *and* short names. This may explain some
1050 * of the wildcard wierdness from old DOS clients
1051 * that some people have been seeing.... JRA.
1055 pstrcpy( newname, fname);
1056 mangle_map( newname, True, False, SNUM(conn));
1057 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1058 got_match = mask_match(newname, mask, conn->case_sensitive);
1062 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1063 if (dont_descend && !isdots)
1066 pstrcpy(pathreal,conn->dirpath);
1068 pstrcat(pathreal,"/");
1069 pstrcat(pathreal,dname);
1071 if (INFO_LEVEL_IS_UNIX(info_level)) {
1072 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1073 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1074 pathreal,strerror(errno)));
1077 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1079 /* Needed to show the msdfs symlinks as
1082 if(lp_host_msdfs() &&
1083 lp_msdfs_root(SNUM(conn)) &&
1084 is_msdfs_link(conn, pathreal, NULL, NULL,
1087 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1088 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1092 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1093 pathreal,strerror(errno)));
1098 mode = dos_mode(conn,pathreal,&sbuf);
1100 if (!dir_check_ftype(conn,mode,dirtype)) {
1101 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1105 file_size = get_file_size(sbuf);
1106 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1107 mdate = sbuf.st_mtime;
1108 adate = sbuf.st_atime;
1109 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1111 if (lp_dos_filetime_resolution(SNUM(conn))) {
1118 /* This is necessary, as otherwise the
1119 * desktop.ini file in this folder is
1121 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1125 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1131 mangle_map(fname,False,True,SNUM(conn));
1136 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1138 switch (info_level) {
1139 case SMB_FIND_INFO_STANDARD:
1140 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1141 if(requires_resume_key) {
1145 put_dos_date2(p,l1_fdateCreation,cdate);
1146 put_dos_date2(p,l1_fdateLastAccess,adate);
1147 put_dos_date2(p,l1_fdateLastWrite,mdate);
1148 SIVAL(p,l1_cbFile,(uint32)file_size);
1149 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1150 SSVAL(p,l1_attrFile,mode);
1153 p += align_string(outbuf, p, 0);
1154 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1155 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1157 SCVAL(nameptr, -1, len - 2);
1159 SCVAL(nameptr, -1, 0);
1163 SCVAL(nameptr, -1, len - 1);
1165 SCVAL(nameptr, -1, 0);
1171 case SMB_FIND_EA_SIZE:
1172 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1173 if(requires_resume_key) {
1177 put_dos_date2(p,l2_fdateCreation,cdate);
1178 put_dos_date2(p,l2_fdateLastAccess,adate);
1179 put_dos_date2(p,l2_fdateLastWrite,mdate);
1180 SIVAL(p,l2_cbFile,(uint32)file_size);
1181 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1182 SSVAL(p,l2_attrFile,mode);
1184 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1185 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1189 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1190 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1203 SCVAL(nameptr,0,len);
1205 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1208 case SMB_FIND_EA_LIST:
1210 struct ea_list *file_list = NULL;
1213 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1217 if(requires_resume_key) {
1221 put_dos_date2(p,l2_fdateCreation,cdate);
1222 put_dos_date2(p,l2_fdateLastAccess,adate);
1223 put_dos_date2(p,l2_fdateLastWrite,mdate);
1224 SIVAL(p,l2_cbFile,(uint32)file_size);
1225 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1226 SSVAL(p,l2_attrFile,mode);
1227 p += l2_cbList; /* p now points to the EA area. */
1229 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1230 name_list = ea_list_union(name_list, file_list, &ea_len);
1232 /* We need to determine if this entry will fit in the space available. */
1233 /* Max string size is 255 bytes. */
1234 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1235 /* Move the dirptr back to prev_dirpos */
1236 dptr_SeekDir(conn->dirptr, prev_dirpos);
1237 *out_of_space = True;
1238 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1239 return False; /* Not finished - just out of space */
1242 /* Push the ea_data followed by the name. */
1243 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1245 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1246 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1259 SCVAL(nameptr,0,len);
1261 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1265 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1266 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1267 was_8_3 = mangle_is_8_3(fname, True);
1269 SIVAL(p,0,reskey); p += 4;
1270 put_long_date(p,cdate); p += 8;
1271 put_long_date(p,adate); p += 8;
1272 put_long_date(p,mdate); p += 8;
1273 put_long_date(p,mdate); p += 8;
1274 SOFF_T(p,0,file_size); p += 8;
1275 SOFF_T(p,0,allocation_size); p += 8;
1276 SIVAL(p,0,nt_extmode); p += 4;
1277 q = p; p += 4; /* q is placeholder for name length. */
1279 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1280 SIVAL(p,0,ea_size); /* Extended attributes */
1283 /* Clear the short name buffer. This is
1284 * IMPORTANT as not doing so will trigger
1285 * a Win2k client bug. JRA.
1288 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1289 pstring mangled_name;
1290 pstrcpy(mangled_name, fname);
1291 mangle_map(mangled_name,True,True,SNUM(conn));
1292 mangled_name[12] = 0;
1293 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1300 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1303 len = PTR_DIFF(p, pdata);
1304 len = (len + 3) & ~3;
1309 case SMB_FIND_FILE_DIRECTORY_INFO:
1310 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1312 SIVAL(p,0,reskey); p += 4;
1313 put_long_date(p,cdate); p += 8;
1314 put_long_date(p,adate); p += 8;
1315 put_long_date(p,mdate); p += 8;
1316 put_long_date(p,mdate); p += 8;
1317 SOFF_T(p,0,file_size); p += 8;
1318 SOFF_T(p,0,allocation_size); p += 8;
1319 SIVAL(p,0,nt_extmode); p += 4;
1320 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1323 len = PTR_DIFF(p, pdata);
1324 len = (len + 3) & ~3;
1329 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1330 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1332 SIVAL(p,0,reskey); p += 4;
1333 put_long_date(p,cdate); p += 8;
1334 put_long_date(p,adate); p += 8;
1335 put_long_date(p,mdate); p += 8;
1336 put_long_date(p,mdate); p += 8;
1337 SOFF_T(p,0,file_size); p += 8;
1338 SOFF_T(p,0,allocation_size); p += 8;
1339 SIVAL(p,0,nt_extmode); p += 4;
1340 q = p; p += 4; /* q is placeholder for name length. */
1342 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1343 SIVAL(p,0,ea_size); /* Extended attributes */
1346 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1350 len = PTR_DIFF(p, pdata);
1351 len = (len + 3) & ~3;
1356 case SMB_FIND_FILE_NAMES_INFO:
1357 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1359 SIVAL(p,0,reskey); p += 4;
1361 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1362 acl on a dir (tridge) */
1363 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1366 len = PTR_DIFF(p, pdata);
1367 len = (len + 3) & ~3;
1372 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1373 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_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 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1390 SIVAL(p,0,sbuf.st_dev); p += 4;
1391 SIVAL(p,0,sbuf.st_ino); p += 4;
1392 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1395 len = PTR_DIFF(p, pdata);
1396 len = (len + 3) & ~3;
1401 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1402 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1403 was_8_3 = mangle_is_8_3(fname, True);
1405 SIVAL(p,0,reskey); p += 4;
1406 put_long_date(p,cdate); p += 8;
1407 put_long_date(p,adate); p += 8;
1408 put_long_date(p,mdate); p += 8;
1409 put_long_date(p,mdate); p += 8;
1410 SOFF_T(p,0,file_size); p += 8;
1411 SOFF_T(p,0,allocation_size); p += 8;
1412 SIVAL(p,0,nt_extmode); p += 4;
1413 q = p; p += 4; /* q is placeholder for name length */
1415 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1416 SIVAL(p,0,ea_size); /* Extended attributes */
1419 /* Clear the short name buffer. This is
1420 * IMPORTANT as not doing so will trigger
1421 * a Win2k client bug. JRA.
1424 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1425 pstring mangled_name;
1426 pstrcpy(mangled_name, fname);
1427 mangle_map(mangled_name,True,True,SNUM(conn));
1428 mangled_name[12] = 0;
1429 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1436 SSVAL(p,0,0); p += 2; /* Reserved ? */
1437 SIVAL(p,0,sbuf.st_dev); p += 4;
1438 SIVAL(p,0,sbuf.st_ino); p += 4;
1439 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1442 len = PTR_DIFF(p, pdata);
1443 len = (len + 3) & ~3;
1448 /* CIFS UNIX Extension. */
1450 case SMB_FIND_FILE_UNIX:
1451 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1453 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1455 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1456 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1459 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1462 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1463 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1464 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1467 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1471 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1475 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1478 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1482 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1486 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1489 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1493 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1497 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1500 len = PTR_DIFF(p, pdata);
1501 len = (len + 3) & ~3;
1502 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1504 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1513 if (PTR_DIFF(p,pdata) > space_remaining) {
1514 /* Move the dirptr back to prev_dirpos */
1515 dptr_SeekDir(conn->dirptr, prev_dirpos);
1516 *out_of_space = True;
1517 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1518 return False; /* Not finished - just out of space */
1521 /* Setup the last entry pointer, as an offset from base_data */
1522 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1523 /* Advance the data pointer to the next slot */
1529 /****************************************************************************
1530 Reply to a TRANS2_FINDFIRST.
1531 ****************************************************************************/
1533 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1534 char **pparams, int total_params, char **ppdata, int total_data,
1535 unsigned int max_data_bytes)
1537 /* We must be careful here that we don't return more than the
1538 allowed number of data bytes. If this means returning fewer than
1539 maxentries then so be it. We assume that the redirector has
1540 enough room for the fixed number of parameter bytes it has
1542 char *params = *pparams;
1543 char *pdata = *ppdata;
1544 int dirtype = SVAL(params,0);
1545 int maxentries = SVAL(params,2);
1546 uint16 findfirst_flags = SVAL(params,4);
1547 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1548 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1549 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1550 int info_level = SVAL(params,6);
1554 int last_entry_off=0;
1558 BOOL finished = False;
1559 BOOL dont_descend = False;
1560 BOOL out_of_space = False;
1561 int space_remaining;
1562 BOOL bad_path = False;
1563 SMB_STRUCT_STAT sbuf;
1564 TALLOC_CTX *ea_ctx = NULL;
1565 struct ea_list *ea_list = NULL;
1566 NTSTATUS ntstatus = NT_STATUS_OK;
1568 if (total_params < 12) {
1569 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1572 *directory = *mask = 0;
1574 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1575 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1576 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1577 info_level, max_data_bytes));
1580 /* W2K3 seems to treat zero as 1. */
1584 switch (info_level) {
1585 case SMB_FIND_INFO_STANDARD:
1586 case SMB_FIND_EA_SIZE:
1587 case SMB_FIND_EA_LIST:
1588 case SMB_FIND_FILE_DIRECTORY_INFO:
1589 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1590 case SMB_FIND_FILE_NAMES_INFO:
1591 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1592 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1593 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1595 case SMB_FIND_FILE_UNIX:
1596 if (!lp_unix_extensions())
1597 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1600 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1603 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1604 if (!NT_STATUS_IS_OK(ntstatus)) {
1605 return ERROR_NT(ntstatus);
1608 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1610 unix_convert(directory,conn,0,&bad_path,&sbuf);
1612 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1614 if(!check_name(directory,conn)) {
1615 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1618 p = strrchr_m(directory,'/');
1620 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1621 if((directory[0] == '.') && (directory[1] == '\0'))
1624 pstrcpy(mask,directory);
1625 pstrcpy(directory,"./");
1631 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1633 if (info_level == SMB_FIND_EA_LIST) {
1636 if (total_data < 4) {
1637 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1640 ea_size = IVAL(pdata,0);
1641 if (ea_size != total_data) {
1642 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1643 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1644 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1647 if (!lp_ea_support(SNUM(conn))) {
1648 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1651 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1652 return ERROR_NT(NT_STATUS_NO_MEMORY);
1655 /* Pull out the list of names. */
1656 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1658 talloc_destroy(ea_ctx);
1659 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1663 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1664 if( pdata == NULL ) {
1665 talloc_destroy(ea_ctx);
1666 return ERROR_NT(NT_STATUS_NO_MEMORY);
1670 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1672 /* Realloc the params space */
1673 params = SMB_REALLOC(*pparams, 10);
1674 if (params == NULL) {
1675 talloc_destroy(ea_ctx);
1676 return ERROR_NT(NT_STATUS_NO_MEMORY);
1680 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1682 talloc_destroy(ea_ctx);
1683 return(UNIXERROR(ERRDOS,ERRbadfile));
1686 /* Save the wildcard match and attribs we are using on this directory -
1687 needed as lanman2 assumes these are being saved between calls */
1689 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1690 dptr_close(&dptr_num);
1691 talloc_destroy(ea_ctx);
1692 return ERROR_NT(NT_STATUS_NO_MEMORY);
1695 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1697 /* We don't need to check for VOL here as this is returned by
1698 a different TRANS2 call. */
1700 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1701 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1702 dont_descend = True;
1705 space_remaining = max_data_bytes;
1706 out_of_space = False;
1708 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1709 BOOL got_exact_match = False;
1711 /* this is a heuristic to avoid seeking the dirptr except when
1712 absolutely necessary. It allows for a filename of about 40 chars */
1713 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1714 out_of_space = True;
1717 finished = !get_lanman2_dir_entry(conn,
1719 mask,dirtype,info_level,
1720 requires_resume_key,dont_descend,
1721 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1722 &last_entry_off, ea_list, ea_ctx);
1725 if (finished && out_of_space)
1728 if (!finished && !out_of_space)
1732 * As an optimisation if we know we aren't looking
1733 * for a wildcard name (ie. the name matches the wildcard exactly)
1734 * then we can finish on any (first) match.
1735 * This speeds up large directory searches. JRA.
1741 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1744 talloc_destroy(ea_ctx);
1746 /* Check if we can close the dirptr */
1747 if(close_after_first || (finished && close_if_end)) {
1748 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1749 dptr_close(&dptr_num);
1753 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1754 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1755 * the protocol level is less than NT1. Tested with smbclient. JRA.
1756 * This should fix the OS/2 client bug #2335.
1759 if(numentries == 0) {
1760 dptr_close(&dptr_num);
1761 if (Protocol < PROTOCOL_NT1) {
1762 return ERROR_DOS(ERRDOS,ERRnofiles);
1764 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1768 /* At this point pdata points to numentries directory entries. */
1770 /* Set up the return parameter block */
1771 SSVAL(params,0,dptr_num);
1772 SSVAL(params,2,numentries);
1773 SSVAL(params,4,finished);
1774 SSVAL(params,6,0); /* Never an EA error */
1775 SSVAL(params,8,last_entry_off);
1777 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1779 if ((! *directory) && dptr_path(dptr_num))
1780 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1782 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1783 smb_fn_name(CVAL(inbuf,smb_com)),
1784 mask, directory, dirtype, numentries ) );
1787 * Force a name mangle here to ensure that the
1788 * mask as an 8.3 name is top of the mangled cache.
1789 * The reasons for this are subtle. Don't remove
1790 * this code unless you know what you are doing
1791 * (see PR#13758). JRA.
1794 if(!mangle_is_8_3_wildcards( mask, False))
1795 mangle_map(mask, True, True, SNUM(conn));
1800 /****************************************************************************
1801 Reply to a TRANS2_FINDNEXT.
1802 ****************************************************************************/
1804 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1805 char **pparams, int total_params, char **ppdata, int total_data,
1806 unsigned int max_data_bytes)
1808 /* We must be careful here that we don't return more than the
1809 allowed number of data bytes. If this means returning fewer than
1810 maxentries then so be it. We assume that the redirector has
1811 enough room for the fixed number of parameter bytes it has
1813 char *params = *pparams;
1814 char *pdata = *ppdata;
1815 int dptr_num = SVAL(params,0);
1816 int maxentries = SVAL(params,2);
1817 uint16 info_level = SVAL(params,4);
1818 uint32 resume_key = IVAL(params,6);
1819 uint16 findnext_flags = SVAL(params,10);
1820 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1821 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1822 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1823 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1824 pstring resume_name;
1830 int i, last_entry_off=0;
1831 BOOL finished = False;
1832 BOOL dont_descend = False;
1833 BOOL out_of_space = False;
1834 int space_remaining;
1835 TALLOC_CTX *ea_ctx = NULL;
1836 struct ea_list *ea_list = NULL;
1837 NTSTATUS ntstatus = NT_STATUS_OK;
1839 if (total_params < 12) {
1840 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1843 *mask = *directory = *resume_name = 0;
1845 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1846 if (!NT_STATUS_IS_OK(ntstatus)) {
1847 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1848 complain (it thinks we're asking for the directory above the shared
1849 path or an invalid name). Catch this as the resume name is only compared, never used in
1850 a file access. JRA. */
1851 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1852 pstrcpy(resume_name, "..");
1853 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1854 pstrcpy(resume_name, ".");
1856 return ERROR_NT(ntstatus);
1860 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1861 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1862 resume_key = %d resume name = %s continue=%d level = %d\n",
1863 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1864 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1867 /* W2K3 seems to treat zero as 1. */
1871 switch (info_level) {
1872 case SMB_FIND_INFO_STANDARD:
1873 case SMB_FIND_EA_SIZE:
1874 case SMB_FIND_EA_LIST:
1875 case SMB_FIND_FILE_DIRECTORY_INFO:
1876 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1877 case SMB_FIND_FILE_NAMES_INFO:
1878 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1880 case SMB_FIND_FILE_UNIX:
1881 if (!lp_unix_extensions())
1882 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1885 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1888 if (info_level == SMB_FIND_EA_LIST) {
1891 if (total_data < 4) {
1892 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1895 ea_size = IVAL(pdata,0);
1896 if (ea_size != total_data) {
1897 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1898 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1899 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1902 if (!lp_ea_support(SNUM(conn))) {
1903 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1906 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1907 return ERROR_NT(NT_STATUS_NO_MEMORY);
1910 /* Pull out the list of names. */
1911 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1913 talloc_destroy(ea_ctx);
1914 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1918 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1920 talloc_destroy(ea_ctx);
1921 return ERROR_NT(NT_STATUS_NO_MEMORY);
1925 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1927 /* Realloc the params space */
1928 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1929 if( params == NULL ) {
1930 talloc_destroy(ea_ctx);
1931 return ERROR_NT(NT_STATUS_NO_MEMORY);
1936 /* Check that the dptr is valid */
1937 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1938 talloc_destroy(ea_ctx);
1939 return ERROR_DOS(ERRDOS,ERRnofiles);
1942 string_set(&conn->dirpath,dptr_path(dptr_num));
1944 /* Get the wildcard mask from the dptr */
1945 if((p = dptr_wcard(dptr_num))== NULL) {
1946 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1947 talloc_destroy(ea_ctx);
1948 return ERROR_DOS(ERRDOS,ERRnofiles);
1952 pstrcpy(directory,conn->dirpath);
1954 /* Get the attr mask from the dptr */
1955 dirtype = dptr_attr(dptr_num);
1957 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1958 dptr_num, mask, dirtype,
1960 dptr_TellDir(conn->dirptr)));
1962 /* We don't need to check for VOL here as this is returned by
1963 a different TRANS2 call. */
1965 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1966 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1967 dont_descend = True;
1970 space_remaining = max_data_bytes;
1971 out_of_space = False;
1974 * Seek to the correct position. We no longer use the resume key but
1975 * depend on the last file name instead.
1978 if(*resume_name && !continue_bit) {
1981 long current_pos = 0;
1983 * Remember, mangle_map is called by
1984 * get_lanman2_dir_entry(), so the resume name
1985 * could be mangled. Ensure we check the unmangled name.
1988 if (mangle_is_mangled(resume_name)) {
1989 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1993 * Fix for NT redirector problem triggered by resume key indexes
1994 * changing between directory scans. We now return a resume key of 0
1995 * and instead look for the filename to continue from (also given
1996 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1997 * findfirst/findnext (as is usual) then the directory pointer
1998 * should already be at the correct place.
2001 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2002 } /* end if resume_name && !continue_bit */
2004 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2005 BOOL got_exact_match = False;
2007 /* this is a heuristic to avoid seeking the dirptr except when
2008 absolutely necessary. It allows for a filename of about 40 chars */
2009 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2010 out_of_space = True;
2013 finished = !get_lanman2_dir_entry(conn,
2015 mask,dirtype,info_level,
2016 requires_resume_key,dont_descend,
2017 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2018 &last_entry_off, ea_list, ea_ctx);
2021 if (finished && out_of_space)
2024 if (!finished && !out_of_space)
2028 * As an optimisation if we know we aren't looking
2029 * for a wildcard name (ie. the name matches the wildcard exactly)
2030 * then we can finish on any (first) match.
2031 * This speeds up large directory searches. JRA.
2037 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2040 talloc_destroy(ea_ctx);
2042 /* Check if we can close the dirptr */
2043 if(close_after_request || (finished && close_if_end)) {
2044 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2045 dptr_close(&dptr_num); /* This frees up the saved mask */
2048 /* Set up the return parameter block */
2049 SSVAL(params,0,numentries);
2050 SSVAL(params,2,finished);
2051 SSVAL(params,4,0); /* Never an EA error */
2052 SSVAL(params,6,last_entry_off);
2054 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2056 if ((! *directory) && dptr_path(dptr_num))
2057 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2059 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2060 smb_fn_name(CVAL(inbuf,smb_com)),
2061 mask, directory, dirtype, numentries ) );
2066 /****************************************************************************
2067 Reply to a TRANS2_QFSINFO (query filesystem info).
2068 ****************************************************************************/
2070 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2071 char **pparams, int total_params, char **ppdata, int total_data,
2072 unsigned int max_data_bytes)
2074 char *pdata = *ppdata;
2075 char *params = *pparams;
2076 uint16 info_level = SVAL(params,0);
2079 char *vname = volume_label(SNUM(conn));
2080 int snum = SNUM(conn);
2081 char *fstype = lp_fstype(SNUM(conn));
2084 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2086 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2087 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2088 return ERROR_DOS(ERRSRV,ERRinvdevice);
2091 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2092 if ( pdata == NULL ) {
2093 return ERROR_NT(NT_STATUS_NO_MEMORY);
2097 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2099 switch (info_level) {
2100 case SMB_INFO_ALLOCATION:
2102 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2104 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2105 return(UNIXERROR(ERRHRD,ERRgeneral));
2108 block_size = lp_block_size(snum);
2109 if (bsize < block_size) {
2110 SMB_BIG_UINT factor = block_size/bsize;
2115 if (bsize > block_size) {
2116 SMB_BIG_UINT factor = bsize/block_size;
2121 bytes_per_sector = 512;
2122 sectors_per_unit = bsize/bytes_per_sector;
2124 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2125 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2126 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2128 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2129 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2130 SIVAL(pdata,l1_cUnit,dsize);
2131 SIVAL(pdata,l1_cUnitAvail,dfree);
2132 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2136 case SMB_INFO_VOLUME:
2137 /* Return volume name */
2139 * Add volume serial number - hash of a combination of
2140 * the called hostname and the service name.
2142 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2144 * Win2k3 and previous mess this up by sending a name length
2145 * one byte short. I believe only older clients (OS/2 Win9x) use
2146 * this call so try fixing this by adding a terminating null to
2147 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2149 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2150 SCVAL(pdata,l2_vol_cch,len);
2151 data_len = l2_vol_szVolLabel + len;
2152 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2153 (unsigned)st.st_ctime, len, vname));
2156 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2157 case SMB_FS_ATTRIBUTE_INFORMATION:
2160 #if defined(HAVE_SYS_QUOTAS)
2161 quota_flag = FILE_VOLUME_QUOTAS;
2164 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2165 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2166 quota_flag); /* FS ATTRIBUTES */
2168 SIVAL(pdata,4,255); /* Max filename component length */
2169 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2170 and will think we can't do long filenames */
2171 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2173 data_len = 12 + len;
2176 case SMB_QUERY_FS_LABEL_INFO:
2177 case SMB_FS_LABEL_INFORMATION:
2178 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2183 case SMB_QUERY_FS_VOLUME_INFO:
2184 case SMB_FS_VOLUME_INFORMATION:
2187 * Add volume serial number - hash of a combination of
2188 * the called hostname and the service name.
2190 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2191 (str_checksum(get_local_machine_name())<<16));
2193 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2194 SIVAL(pdata,12,len);
2196 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2197 (int)strlen(vname),vname, lp_servicename(snum)));
2200 case SMB_QUERY_FS_SIZE_INFO:
2201 case SMB_FS_SIZE_INFORMATION:
2203 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2205 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2206 return(UNIXERROR(ERRHRD,ERRgeneral));
2208 block_size = lp_block_size(snum);
2209 if (bsize < block_size) {
2210 SMB_BIG_UINT factor = block_size/bsize;
2215 if (bsize > block_size) {
2216 SMB_BIG_UINT factor = bsize/block_size;
2221 bytes_per_sector = 512;
2222 sectors_per_unit = bsize/bytes_per_sector;
2223 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2224 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2225 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2226 SBIG_UINT(pdata,0,dsize);
2227 SBIG_UINT(pdata,8,dfree);
2228 SIVAL(pdata,16,sectors_per_unit);
2229 SIVAL(pdata,20,bytes_per_sector);
2233 case SMB_FS_FULL_SIZE_INFORMATION:
2235 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2237 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2238 return(UNIXERROR(ERRHRD,ERRgeneral));
2240 block_size = lp_block_size(snum);
2241 if (bsize < block_size) {
2242 SMB_BIG_UINT factor = block_size/bsize;
2247 if (bsize > block_size) {
2248 SMB_BIG_UINT factor = bsize/block_size;
2253 bytes_per_sector = 512;
2254 sectors_per_unit = bsize/bytes_per_sector;
2255 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2256 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2257 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2258 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2259 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2260 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2261 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2262 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2266 case SMB_QUERY_FS_DEVICE_INFO:
2267 case SMB_FS_DEVICE_INFORMATION:
2269 SIVAL(pdata,0,0); /* dev type */
2270 SIVAL(pdata,4,0); /* characteristics */
2273 #ifdef HAVE_SYS_QUOTAS
2274 case SMB_FS_QUOTA_INFORMATION:
2276 * what we have to send --metze:
2278 * Unknown1: 24 NULL bytes
2279 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2280 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2281 * Quota Flags: 2 byte :
2282 * Unknown3: 6 NULL bytes
2286 * details for Quota Flags:
2288 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2289 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2290 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2291 * 0x0001 Enable Quotas: enable quota for this fs
2295 /* we need to fake up a fsp here,
2296 * because its not send in this call
2299 SMB_NTQUOTA_STRUCT quotas;
2302 ZERO_STRUCT(quotas);
2309 if (current_user.uid != 0) {
2310 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2311 lp_servicename(SNUM(conn)),conn->user));
2312 return ERROR_DOS(ERRDOS,ERRnoaccess);
2315 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2316 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2317 return ERROR_DOS(ERRSRV,ERRerror);
2322 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2324 /* Unknown1 24 NULL bytes*/
2325 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2326 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2327 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2329 /* Default Soft Quota 8 bytes */
2330 SBIG_UINT(pdata,24,quotas.softlim);
2332 /* Default Hard Quota 8 bytes */
2333 SBIG_UINT(pdata,32,quotas.hardlim);
2335 /* Quota flag 2 bytes */
2336 SSVAL(pdata,40,quotas.qflags);
2338 /* Unknown3 6 NULL bytes */
2344 #endif /* HAVE_SYS_QUOTAS */
2345 case SMB_FS_OBJECTID_INFORMATION:
2350 * Query the version and capabilities of the CIFS UNIX extensions
2354 case SMB_QUERY_CIFS_UNIX_INFO:
2355 if (!lp_unix_extensions())
2356 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2358 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2359 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2360 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2363 case SMB_MAC_QUERY_FS_INFO:
2365 * Thursby MAC extension... ONLY on NTFS filesystems
2366 * once we do streams then we don't need this
2368 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2370 SIVAL(pdata,84,0x100); /* Don't support mac... */
2375 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2379 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2381 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2386 #ifdef HAVE_SYS_QUOTAS
2387 /****************************************************************************
2388 Reply to a TRANS2_SETFSINFO (set filesystem info).
2389 ****************************************************************************/
2391 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2392 char **pparams, int total_params, char **ppdata, int total_data,
2393 unsigned int max_data_bytes)
2395 char *pdata = *ppdata;
2396 char *params = *pparams;
2397 files_struct *fsp = NULL;
2400 SMB_NTQUOTA_STRUCT quotas;
2402 ZERO_STRUCT(quotas);
2404 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2407 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2408 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2409 lp_servicename(SNUM(conn)),conn->user));
2410 return ERROR_DOS(ERRSRV,ERRaccess);
2414 if (total_params < 4) {
2415 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2417 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2420 fsp = file_fsp(params,0);
2422 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2423 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2424 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2427 info_level = SVAL(params,2);
2429 switch(info_level) {
2430 case SMB_FS_QUOTA_INFORMATION:
2431 /* note: normaly there're 48 bytes,
2432 * but we didn't use the last 6 bytes for now
2435 if (total_data < 42) {
2436 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2438 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2441 /* unknown_1 24 NULL bytes in pdata*/
2443 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2444 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2445 #ifdef LARGE_SMB_OFF_T
2446 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2447 #else /* LARGE_SMB_OFF_T */
2448 if ((IVAL(pdata,28) != 0)&&
2449 ((quotas.softlim != 0xFFFFFFFF)||
2450 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2451 /* more than 32 bits? */
2452 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2454 #endif /* LARGE_SMB_OFF_T */
2456 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2457 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2458 #ifdef LARGE_SMB_OFF_T
2459 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2460 #else /* LARGE_SMB_OFF_T */
2461 if ((IVAL(pdata,36) != 0)&&
2462 ((quotas.hardlim != 0xFFFFFFFF)||
2463 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2464 /* more than 32 bits? */
2465 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2467 #endif /* LARGE_SMB_OFF_T */
2469 /* quota_flags 2 bytes **/
2470 quotas.qflags = SVAL(pdata,40);
2472 /* unknown_2 6 NULL bytes follow*/
2474 /* now set the quotas */
2475 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2476 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2477 return ERROR_DOS(ERRSRV,ERRerror);
2482 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2484 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2489 * sending this reply works fine,
2490 * but I'm not sure it's the same
2491 * like windows do...
2494 outsize = set_message(outbuf,10,0,True);
2498 #endif /* HAVE_SYS_QUOTAS */
2500 /****************************************************************************
2501 Utility function to set bad path error.
2502 ****************************************************************************/
2504 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2506 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2507 err, (int)bad_path ));
2511 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2513 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2516 return UNIXERROR(def_class,def_code);
2519 #if defined(HAVE_POSIX_ACLS)
2520 /****************************************************************************
2521 Utility function to count the number of entries in a POSIX acl.
2522 ****************************************************************************/
2524 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2526 unsigned int ace_count = 0;
2527 int entry_id = SMB_ACL_FIRST_ENTRY;
2528 SMB_ACL_ENTRY_T entry;
2530 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2532 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2533 entry_id = SMB_ACL_NEXT_ENTRY;
2540 /****************************************************************************
2541 Utility function to marshall a POSIX acl into wire format.
2542 ****************************************************************************/
2544 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2546 int entry_id = SMB_ACL_FIRST_ENTRY;
2547 SMB_ACL_ENTRY_T entry;
2549 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2550 SMB_ACL_TAG_T tagtype;
2551 SMB_ACL_PERMSET_T permset;
2552 unsigned char perms = 0;
2553 unsigned int own_grp;
2556 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2557 entry_id = SMB_ACL_NEXT_ENTRY;
2560 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2561 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2565 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2566 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2570 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2571 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2572 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2574 SCVAL(pdata,1,perms);
2577 case SMB_ACL_USER_OBJ:
2578 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2579 own_grp = (unsigned int)pst->st_uid;
2580 SIVAL(pdata,2,own_grp);
2585 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2587 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2589 own_grp = (unsigned int)*puid;
2590 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2591 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2592 SIVAL(pdata,2,own_grp);
2596 case SMB_ACL_GROUP_OBJ:
2597 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2598 own_grp = (unsigned int)pst->st_gid;
2599 SIVAL(pdata,2,own_grp);
2604 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2606 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2608 own_grp = (unsigned int)*pgid;
2609 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2610 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2611 SIVAL(pdata,2,own_grp);
2616 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2617 SIVAL(pdata,2,0xFFFFFFFF);
2618 SIVAL(pdata,6,0xFFFFFFFF);
2621 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2622 SIVAL(pdata,2,0xFFFFFFFF);
2623 SIVAL(pdata,6,0xFFFFFFFF);
2626 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2629 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2636 /****************************************************************************
2637 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2638 file name or file id).
2639 ****************************************************************************/
2641 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2642 char **pparams, int total_params, char **ppdata, int total_data,
2643 unsigned int max_data_bytes)
2645 char *params = *pparams;
2646 char *pdata = *ppdata;
2647 uint16 tran_call = SVAL(inbuf, smb_setup0);
2650 SMB_OFF_T file_size=0;
2651 SMB_BIG_UINT allocation_size=0;
2652 unsigned int data_size = 0;
2653 unsigned int param_size = 2;
2654 SMB_STRUCT_STAT sbuf;
2655 pstring fname, dos_fname;
2660 BOOL bad_path = False;
2661 BOOL delete_pending = False;
2664 files_struct *fsp = NULL;
2665 TALLOC_CTX *ea_ctx = NULL;
2666 struct ea_list *ea_list = NULL;
2667 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2670 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2674 if (tran_call == TRANSACT2_QFILEINFO) {
2675 if (total_params < 4) {
2676 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2679 fsp = file_fsp(params,0);
2680 info_level = SVAL(params,2);
2682 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2684 if(fsp && (fsp->fake_file_handle)) {
2686 * This is actually for the QUOTA_FAKE_FILE --metze
2689 pstrcpy(fname, fsp->fsp_name);
2690 /* We know this name is ok, it's already passed the checks. */
2692 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2694 * This is actually a QFILEINFO on a directory
2695 * handle (returned from an NT SMB). NT5.0 seems
2696 * to do this call. JRA.
2698 /* We know this name is ok, it's already passed the checks. */
2699 pstrcpy(fname, fsp->fsp_name);
2701 if (INFO_LEVEL_IS_UNIX(info_level)) {
2702 /* Always do lstat for UNIX calls. */
2703 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2704 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2705 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2707 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2708 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2709 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2712 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2715 * Original code - this is an open file.
2717 CHECK_FSP(fsp,conn);
2719 pstrcpy(fname, fsp->fsp_name);
2720 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2721 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2722 return(UNIXERROR(ERRDOS,ERRbadfid));
2724 pos = fsp->position_information;
2725 delete_pending = fsp->delete_on_close;
2726 desired_access = fsp->desired_access;
2729 NTSTATUS status = NT_STATUS_OK;
2732 if (total_params < 6) {
2733 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2736 info_level = SVAL(params,0);
2738 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2740 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 return ERROR_NT(status);
2745 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2747 unix_convert(fname,conn,0,&bad_path,&sbuf);
2749 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2751 if (!check_name(fname,conn)) {
2752 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2753 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2756 if (INFO_LEVEL_IS_UNIX(info_level)) {
2757 /* Always do lstat for UNIX calls. */
2758 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2759 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2760 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2762 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2763 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2764 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2768 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2769 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2771 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2772 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2774 p = strrchr_m(fname,'/');
2780 mode = dos_mode(conn,fname,&sbuf);
2782 mode = FILE_ATTRIBUTE_NORMAL;
2784 fullpathname = fname;
2785 file_size = get_file_size(sbuf);
2786 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2788 /* This is necessary, as otherwise the desktop.ini file in
2789 * this folder is ignored */
2790 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2794 /* Pull any EA list from the data portion. */
2795 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2798 if (total_data < 4) {
2799 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2801 ea_size = IVAL(pdata,0);
2803 if (total_data > 0 && ea_size != total_data) {
2804 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2805 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2809 if (!lp_ea_support(SNUM(conn))) {
2810 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2813 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2814 return ERROR_NT(NT_STATUS_NO_MEMORY);
2817 /* Pull out the list of names. */
2818 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2820 talloc_destroy(ea_ctx);
2821 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2825 params = SMB_REALLOC(*pparams,2);
2826 if (params == NULL) {
2827 talloc_destroy(ea_ctx);
2828 return ERROR_NT(NT_STATUS_NO_MEMORY);
2831 memset((char *)params,'\0',2);
2832 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2833 pdata = SMB_REALLOC(*ppdata, data_size);
2834 if ( pdata == NULL ) {
2835 talloc_destroy(ea_ctx);
2836 return ERROR_NT(NT_STATUS_NO_MEMORY);
2840 memset((char *)pdata,'\0',data_size);
2842 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2845 if (fsp->pending_modtime) {
2846 /* the pending modtime overrides the current modtime */
2847 sbuf.st_mtime = fsp->pending_modtime;
2850 /* Do we have this path open ? */
2851 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2852 if (fsp1 && fsp1->pending_modtime) {
2853 /* the pending modtime overrides the current modtime */
2854 sbuf.st_mtime = fsp1->pending_modtime;
2858 if (lp_dos_filetime_resolution(SNUM(conn))) {
2860 sbuf.st_atime &= ~1;
2861 sbuf.st_ctime &= ~1;
2862 sbuf.st_mtime &= ~1;
2865 /* NT expects the name to be in an exact form of the *full*
2866 filename. See the trans2 torture test */
2867 if (strequal(base_name,".")) {
2868 pstrcpy(dos_fname, "\\");
2870 pstr_sprintf(dos_fname, "\\%s", fname);
2871 string_replace(dos_fname, '/', '\\');
2874 switch (info_level) {
2875 case SMB_INFO_STANDARD:
2876 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2878 put_dos_date2(pdata,l1_fdateCreation,c_time);
2879 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2880 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2881 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2882 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2883 SSVAL(pdata,l1_attrFile,mode);
2886 case SMB_INFO_QUERY_EA_SIZE:
2888 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2889 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2891 put_dos_date2(pdata,l1_fdateCreation,c_time);
2892 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2893 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2894 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2895 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2896 SSVAL(pdata,l1_attrFile,mode);
2897 SIVAL(pdata,l1_attrFile+2,ea_size);
2901 case SMB_INFO_IS_NAME_VALID:
2902 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2903 if (tran_call == TRANSACT2_QFILEINFO) {
2904 /* os/2 needs this ? really ?*/
2905 return ERROR_DOS(ERRDOS,ERRbadfunc);
2911 case SMB_INFO_QUERY_EAS_FROM_LIST:
2913 size_t total_ea_len = 0;
2914 struct ea_list *ea_file_list = NULL;
2916 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2918 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2919 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2921 if (!ea_list || (total_ea_len > data_size)) {
2922 talloc_destroy(ea_ctx);
2924 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
2928 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2929 talloc_destroy(ea_ctx);
2933 case SMB_INFO_QUERY_ALL_EAS:
2935 /* We have data_size bytes to put EA's into. */
2936 size_t total_ea_len = 0;
2938 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2940 ea_ctx = talloc_init("ea_ctx");
2942 return ERROR_NT(NT_STATUS_NO_MEMORY);
2945 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2946 if (!ea_list || (total_ea_len > data_size)) {
2947 talloc_destroy(ea_ctx);
2949 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
2953 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2954 talloc_destroy(ea_ctx);
2958 case SMB_FILE_BASIC_INFORMATION:
2959 case SMB_QUERY_FILE_BASIC_INFO:
2961 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2962 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2963 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2965 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2969 put_long_date(pdata,c_time);
2970 put_long_date(pdata+8,sbuf.st_atime);
2971 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2972 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2973 SIVAL(pdata,32,mode);
2975 DEBUG(5,("SMB_QFBI - "));
2977 time_t create_time = c_time;
2978 DEBUG(5,("create: %s ", ctime(&create_time)));
2980 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2981 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2982 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2983 DEBUG(5,("mode: %x\n", mode));
2987 case SMB_FILE_STANDARD_INFORMATION:
2988 case SMB_QUERY_FILE_STANDARD_INFO:
2990 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2992 SOFF_T(pdata,0,allocation_size);
2993 SOFF_T(pdata,8,file_size);
2994 if (delete_pending & sbuf.st_nlink)
2995 SIVAL(pdata,16,sbuf.st_nlink - 1);
2997 SIVAL(pdata,16,sbuf.st_nlink);
2999 SCVAL(pdata,21,(mode&aDIR)?1:0);
3002 case SMB_FILE_EA_INFORMATION:
3003 case SMB_QUERY_FILE_EA_INFO:
3005 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3006 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3008 SIVAL(pdata,0,ea_size);
3012 /* Get the 8.3 name - used if NT SMB was negotiated. */
3013 case SMB_QUERY_FILE_ALT_NAME_INFO:
3014 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3018 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3019 pstrcpy(short_name,base_name);
3020 /* Mangle if not already 8.3 */
3021 if(!mangle_is_8_3(short_name, True)) {
3022 mangle_map(short_name,True,True,SNUM(conn));
3024 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3025 data_size = 4 + len;
3030 case SMB_QUERY_FILE_NAME_INFO:
3032 this must be *exactly* right for ACLs on mapped drives to work
3034 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3035 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3036 data_size = 4 + len;
3040 case SMB_FILE_ALLOCATION_INFORMATION:
3041 case SMB_QUERY_FILE_ALLOCATION_INFO:
3042 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3044 SOFF_T(pdata,0,allocation_size);
3047 case SMB_FILE_END_OF_FILE_INFORMATION:
3048 case SMB_QUERY_FILE_END_OF_FILEINFO:
3049 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3051 SOFF_T(pdata,0,file_size);
3054 case SMB_QUERY_FILE_ALL_INFO:
3055 case SMB_FILE_ALL_INFORMATION:
3057 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3058 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3059 put_long_date(pdata,c_time);
3060 put_long_date(pdata+8,sbuf.st_atime);
3061 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3062 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3063 SIVAL(pdata,32,mode);
3065 SOFF_T(pdata,0,allocation_size);
3066 SOFF_T(pdata,8,file_size);
3067 if (delete_pending && sbuf.st_nlink)
3068 SIVAL(pdata,16,sbuf.st_nlink - 1);
3070 SIVAL(pdata,16,sbuf.st_nlink);
3071 SCVAL(pdata,20,delete_pending);
3072 SCVAL(pdata,21,(mode&aDIR)?1:0);
3074 SIVAL(pdata,0,ea_size);
3075 pdata += 4; /* EA info */
3076 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3079 data_size = PTR_DIFF(pdata,(*ppdata));
3082 case SMB_FILE_INTERNAL_INFORMATION:
3083 /* This should be an index number - looks like
3086 I think this causes us to fail the IFSKIT
3087 BasicFileInformationTest. -tpot */
3089 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3090 SIVAL(pdata,0,sbuf.st_dev);
3091 SIVAL(pdata,4,sbuf.st_ino);
3095 case SMB_FILE_ACCESS_INFORMATION:
3096 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3097 SIVAL(pdata,0,desired_access);
3101 case SMB_FILE_NAME_INFORMATION:
3102 /* Pathname with leading '\'. */
3105 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3106 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3107 SIVAL(pdata,0,byte_len);
3108 data_size = 4 + byte_len;
3112 case SMB_FILE_DISPOSITION_INFORMATION:
3113 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3115 SCVAL(pdata,0,delete_pending);
3118 case SMB_FILE_POSITION_INFORMATION:
3119 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3121 SOFF_T(pdata,0,pos);
3124 case SMB_FILE_MODE_INFORMATION:
3125 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3126 SIVAL(pdata,0,mode);
3130 case SMB_FILE_ALIGNMENT_INFORMATION:
3131 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3132 SIVAL(pdata,0,0); /* No alignment needed. */
3138 * NT4 server just returns "invalid query" to this - if we try to answer
3139 * it then NTws gets a BSOD! (tridge).
3140 * W2K seems to want this. JRA.
3142 case SMB_QUERY_FILE_STREAM_INFO:
3144 case SMB_FILE_STREAM_INFORMATION:
3145 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3149 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3150 SIVAL(pdata,0,0); /* ??? */
3151 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3152 SOFF_T(pdata,8,file_size);
3153 SIVAL(pdata,16,allocation_size);
3154 SIVAL(pdata,20,0); /* ??? */
3155 data_size = 24 + byte_len;
3159 case SMB_QUERY_COMPRESSION_INFO:
3160 case SMB_FILE_COMPRESSION_INFORMATION:
3161 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3162 SOFF_T(pdata,0,file_size);
3163 SIVAL(pdata,8,0); /* ??? */
3164 SIVAL(pdata,12,0); /* ??? */
3168 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3169 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3170 put_long_date(pdata,c_time);
3171 put_long_date(pdata+8,sbuf.st_atime);
3172 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3173 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3174 SIVAL(pdata,32,allocation_size);
3175 SOFF_T(pdata,40,file_size);
3176 SIVAL(pdata,48,mode);
3177 SIVAL(pdata,52,0); /* ??? */
3181 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3182 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3183 SIVAL(pdata,0,mode);
3189 * CIFS UNIX Extensions.
3192 case SMB_QUERY_FILE_UNIX_BASIC:
3194 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3195 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3197 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3200 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3203 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3204 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3205 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3208 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3212 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3216 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3219 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3223 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3227 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3230 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3234 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3237 data_size = PTR_DIFF(pdata,(*ppdata));
3241 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3243 for (i=0; i<100; i++)
3244 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3250 case SMB_QUERY_FILE_UNIX_LINK:
3254 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3256 if(!S_ISLNK(sbuf.st_mode))
3257 return(UNIXERROR(ERRSRV,ERRbadlink));
3259 return(UNIXERROR(ERRDOS,ERRbadlink));
3261 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3263 return(UNIXERROR(ERRDOS,ERRnoaccess));
3265 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3267 data_size = PTR_DIFF(pdata,(*ppdata));
3272 #if defined(HAVE_POSIX_ACLS)
3273 case SMB_QUERY_POSIX_ACL:
3275 SMB_ACL_T file_acl = NULL;
3276 SMB_ACL_T def_acl = NULL;
3277 uint16 num_file_acls = 0;
3278 uint16 num_def_acls = 0;
3280 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3281 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3283 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3286 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3287 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3289 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3292 if (S_ISDIR(sbuf.st_mode)) {
3293 if (fsp && fsp->is_directory) {
3294 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3296 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3298 def_acl = free_empty_sys_acl(conn, def_acl);
3301 num_file_acls = count_acl_entries(conn, file_acl);
3302 num_def_acls = count_acl_entries(conn, def_acl);
3304 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3305 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3307 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3308 SMB_POSIX_ACL_HEADER_SIZE) ));
3310 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3313 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3315 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3318 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3319 SSVAL(pdata,2,num_file_acls);
3320 SSVAL(pdata,4,num_def_acls);
3321 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3323 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3326 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3328 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3330 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3332 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3335 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3337 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3341 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3344 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3346 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3352 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3355 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3360 /****************************************************************************
3361 Deal with the internal needs of setting the delete on close flag. Note that
3362 as the tdb locking is recursive, it is safe to call this from within
3363 open_file_shared. JRA.
3364 ****************************************************************************/
3366 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3368 if (delete_on_close) {
3370 * Only allow delete on close for writable files.
3373 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3374 if (dosmode & aRONLY) {
3375 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3377 return NT_STATUS_CANNOT_DELETE;
3382 * Only allow delete on close for writable shares.
3385 if (!CAN_WRITE(fsp->conn)) {
3386 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3388 return NT_STATUS_ACCESS_DENIED;
3392 * Only allow delete on close for files/directories opened with delete intent.
3395 if (!(fsp->desired_access & DELETE_ACCESS)) {
3396 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3398 return NT_STATUS_ACCESS_DENIED;
3402 if(fsp->is_directory) {
3403 fsp->directory_delete_on_close = delete_on_close;
3404 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3405 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3407 fsp->delete_on_close = delete_on_close;
3408 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3409 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3412 return NT_STATUS_OK;
3415 /****************************************************************************
3416 Sets the delete on close flag over all share modes on this file.
3417 Modify the share mode entry for all files open
3418 on this device and inode to tell other smbds we have
3419 changed the delete on close flag. This will be noticed
3420 in the close code, the last closer will delete the file
3422 ****************************************************************************/
3424 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3426 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3427 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3429 if (fsp->is_directory || fsp->is_stat)
3430 return NT_STATUS_OK;
3432 if (lock_share_entry_fsp(fsp) == False)
3433 return NT_STATUS_ACCESS_DENIED;
3435 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3436 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3438 unlock_share_entry_fsp(fsp);
3439 return NT_STATUS_ACCESS_DENIED;
3442 unlock_share_entry_fsp(fsp);
3443 return NT_STATUS_OK;
3446 /****************************************************************************
3447 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3449 ****************************************************************************/
3451 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3453 BOOL bad_path_oldname = False;
3454 BOOL bad_path_newname = False;
3455 SMB_STRUCT_STAT sbuf1, sbuf2;
3456 pstring last_component_oldname;
3457 pstring last_component_newname;
3458 NTSTATUS status = NT_STATUS_OK;
3464 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3465 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3468 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3469 if (bad_path_oldname) {
3470 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3473 /* Quick check for "." and ".." */
3474 if (last_component_oldname[0] == '.') {
3475 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3476 return NT_STATUS_OBJECT_NAME_INVALID;
3480 /* source must already exist. */
3481 if (!VALID_STAT(sbuf1)) {
3482 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3485 if (!check_name(oldname,conn)) {
3486 return NT_STATUS_ACCESS_DENIED;
3489 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3490 if (bad_path_newname) {
3491 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3494 /* Quick check for "." and ".." */
3495 if (last_component_newname[0] == '.') {
3496 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3497 return NT_STATUS_OBJECT_NAME_INVALID;
3501 /* Disallow if newname already exists. */
3502 if (VALID_STAT(sbuf2)) {
3503 return NT_STATUS_OBJECT_NAME_COLLISION;
3506 if (!check_name(newname,conn)) {
3507 return NT_STATUS_ACCESS_DENIED;
3510 /* No links from a directory. */
3511 if (S_ISDIR(sbuf1.st_mode)) {
3512 return NT_STATUS_FILE_IS_A_DIRECTORY;
3515 /* Ensure this is within the share. */
3516 if (!reduce_name(conn, oldname) != 0)
3517 return NT_STATUS_ACCESS_DENIED;
3519 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3521 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3522 status = map_nt_error_from_unix(errno);
3523 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3524 nt_errstr(status), newname, oldname));
3530 /****************************************************************************
3531 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3532 ****************************************************************************/
3534 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3535 char **pparams, int total_params, char **ppdata, int total_data,
3536 unsigned int max_data_bytes)
3538 char *params = *pparams;
3539 char *pdata = *ppdata;
3540 uint16 tran_call = SVAL(inbuf, smb_setup0);
3545 SMB_STRUCT_STAT sbuf;
3548 BOOL bad_path = False;
3549 files_struct *fsp = NULL;
3550 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3551 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3552 mode_t unixmode = 0;
3553 NTSTATUS status = NT_STATUS_OK;
3556 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3560 if (tran_call == TRANSACT2_SETFILEINFO) {
3561 if (total_params < 4) {
3562 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3565 fsp = file_fsp(params,0);
3566 info_level = SVAL(params,2);
3568 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3570 * This is actually a SETFILEINFO on a directory
3571 * handle (returned from an NT SMB). NT5.0 seems
3572 * to do this call. JRA.
3574 pstrcpy(fname, fsp->fsp_name);
3575 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3576 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3577 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3579 } else if (fsp && fsp->print_file) {
3581 * Doing a DELETE_ON_CLOSE should cancel a print job.
3583 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3584 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3586 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3589 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3592 return (UNIXERROR(ERRDOS,ERRbadpath));
3595 * Original code - this is an open file.
3597 CHECK_FSP(fsp,conn);
3599 pstrcpy(fname, fsp->fsp_name);
3602 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3603 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3604 return(UNIXERROR(ERRDOS,ERRbadfid));
3609 if (total_params < 6) {
3610 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3613 info_level = SVAL(params,0);
3614 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3615 if (!NT_STATUS_IS_OK(status)) {
3616 return ERROR_NT(status);
3618 unix_convert(fname,conn,0,&bad_path,&sbuf);
3620 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3624 * For CIFS UNIX extensions the target name may not exist.
3627 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3628 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3629 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3632 if(!check_name(fname, conn)) {
3633 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3638 if (!CAN_WRITE(conn))
3639 return ERROR_DOS(ERRSRV,ERRaccess);
3641 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3642 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3644 if (VALID_STAT(sbuf))
3645 unixmode = sbuf.st_mode;
3647 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3648 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3650 /* Realloc the parameter size */
3651 params = SMB_REALLOC(*pparams,2);
3652 if(params == NULL) {
3653 return ERROR_NT(NT_STATUS_NO_MEMORY);
3659 if (fsp && fsp->pending_modtime) {
3660 /* the pending modtime overrides the current modtime */
3661 sbuf.st_mtime = fsp->pending_modtime;
3664 size = get_file_size(sbuf);
3665 tvs.modtime = sbuf.st_mtime;
3666 tvs.actime = sbuf.st_atime;
3667 dosmode = dos_mode(conn,fname,&sbuf);
3668 unixmode = sbuf.st_mode;
3670 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3671 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3673 switch (info_level) {
3674 case SMB_INFO_STANDARD:
3676 if (total_data < 12) {
3677 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3681 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3683 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3687 case SMB_INFO_SET_EA:
3689 struct ea_list *ea_list = NULL;
3690 TALLOC_CTX *ctx = NULL;
3692 if (total_data < 10) {
3693 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3696 if (IVAL(pdata,0) > total_data) {
3697 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3698 IVAL(pdata,0), (unsigned int)total_data));
3699 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3702 ctx = talloc_init("SMB_INFO_SET_EA");
3704 return ERROR_NT(NT_STATUS_NO_MEMORY);
3706 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3708 talloc_destroy(ctx);
3709 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3711 status = set_ea(conn, fsp, fname, ea_list);
3712 talloc_destroy(ctx);
3714 if (!NT_STATUS_IS_OK(status)) {
3715 return ERROR_NT(status);
3721 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3722 /* XXXX um, i don't think this is right.
3723 it's also not in the cifs6.txt spec.
3725 case SMB_INFO_QUERY_EAS_FROM_LIST:
3726 if (total_data < 28)
3727 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3729 tvs.actime = make_unix_date2(pdata+8);
3730 tvs.modtime = make_unix_date2(pdata+12);
3731 size = IVAL(pdata,16);
3732 dosmode = IVAL(pdata,24);
3735 /* XXXX nor this. not in cifs6.txt, either. */
3736 case SMB_INFO_QUERY_ALL_EAS:
3737 if (total_data < 28)
3738 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3740 tvs.actime = make_unix_date2(pdata+8);
3741 tvs.modtime = make_unix_date2(pdata+12);
3742 size = IVAL(pdata,16);
3743 dosmode = IVAL(pdata,24);
3747 case SMB_SET_FILE_BASIC_INFO:
3748 case SMB_FILE_BASIC_INFORMATION:
3750 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3752 time_t changed_time;
3754 if (total_data < 36) {
3755 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3758 /* Ignore create time at offset pdata. */
3761 tvs.actime = interpret_long_date(pdata+8);
3763 write_time = interpret_long_date(pdata+16);
3764 changed_time = interpret_long_date(pdata+24);
3766 tvs.modtime = MIN(write_time, changed_time);
3768 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3769 tvs.modtime = write_time;
3771 /* Prefer a defined time to an undefined one. */
3772 if (null_mtime(tvs.modtime)) {
3773 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3777 dosmode = IVAL(pdata,32);
3781 case SMB_FILE_ALLOCATION_INFORMATION:
3782 case SMB_SET_FILE_ALLOCATION_INFO:
3785 SMB_BIG_UINT allocation_size;
3787 if (total_data < 8) {
3788 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3791 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3792 #ifdef LARGE_SMB_OFF_T
3793 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3794 #else /* LARGE_SMB_OFF_T */
3795 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3796 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3797 #endif /* LARGE_SMB_OFF_T */
3798 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3799 fname, (double)allocation_size ));
3801 if (allocation_size) {
3802 allocation_size = smb_roundup(conn, allocation_size);
3805 if(allocation_size != get_file_size(sbuf)) {
3806 SMB_STRUCT_STAT new_sbuf;
3808 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3809 fname, (double)allocation_size ));
3812 files_struct *new_fsp = NULL;
3813 int access_mode = 0;
3816 if(global_oplock_break) {
3817 /* Queue this file modify as we are the process of an oplock break. */
3819 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3820 DEBUGADD(2,( "in oplock break state.\n"));
3822 push_oplock_pending_smb_message(inbuf, length);
3826 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3827 SET_OPEN_MODE(DOS_OPEN_RDWR),
3828 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3829 FILE_ATTRIBUTE_NORMAL,
3830 INTERNAL_OPEN_ONLY, &access_mode, &action);
3832 if (new_fsp == NULL)
3833 return(UNIXERROR(ERRDOS,ERRbadpath));
3834 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3835 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3836 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3837 new_fsp->fnum, strerror(errno)));
3840 close_file(new_fsp,True);
3842 ret = vfs_allocate_file_space(fsp, allocation_size);
3843 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3844 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3845 fsp->fnum, strerror(errno)));
3850 return ERROR_NT(NT_STATUS_DISK_FULL);
3852 /* Allocate can truncate size... */
3853 size = get_file_size(new_sbuf);
3859 case SMB_FILE_END_OF_FILE_INFORMATION:
3860 case SMB_SET_FILE_END_OF_FILE_INFO:
3862 if (total_data < 8) {
3863 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3866 size = IVAL(pdata,0);
3867 #ifdef LARGE_SMB_OFF_T
3868 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3869 #else /* LARGE_SMB_OFF_T */
3870 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3871 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3872 #endif /* LARGE_SMB_OFF_T */
3873 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3877 case SMB_FILE_DISPOSITION_INFORMATION:
3878 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3880 BOOL delete_on_close;
3882 if (total_data < 1) {
3883 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3886 delete_on_close = (CVAL(pdata,0) ? True : False);
3888 /* Just ignore this set on a path. */
3889 if (tran_call != TRANSACT2_SETFILEINFO)
3893 return(UNIXERROR(ERRDOS,ERRbadfid));
3895 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3897 if (!NT_STATUS_IS_OK(status)) {
3898 return ERROR_NT(status);
3901 /* The set is across all open files on this dev/inode pair. */
3902 status =set_delete_on_close_over_all(fsp, delete_on_close);
3903 if (!NT_STATUS_IS_OK(status)) {
3904 return ERROR_NT(status);
3910 case SMB_FILE_POSITION_INFORMATION:
3912 SMB_BIG_UINT position_information;
3914 if (total_data < 8) {
3915 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3918 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3919 #ifdef LARGE_SMB_OFF_T
3920 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3921 #else /* LARGE_SMB_OFF_T */
3922 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3923 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3924 #endif /* LARGE_SMB_OFF_T */
3925 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3926 fname, (double)position_information ));
3928 fsp->position_information = position_information;
3932 /* From tridge Samba4 :
3933 * MODE_INFORMATION in setfileinfo (I have no
3934 * idea what "mode information" on a file is - it takes a value of 0,
3935 * 2, 4 or 6. What could it be?).
3938 case SMB_FILE_MODE_INFORMATION:
3942 if (total_data < 4) {
3943 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3945 mode = IVAL(pdata,0);
3946 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3947 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3953 * CIFS UNIX extensions.
3956 case SMB_SET_FILE_UNIX_BASIC:
3958 uint32 raw_unixmode;
3960 if (total_data < 100) {
3961 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3964 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3965 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3966 size=IVAL(pdata,0); /* first 8 Bytes are size */
3967 #ifdef LARGE_SMB_OFF_T
3968 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3969 #else /* LARGE_SMB_OFF_T */
3970 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3971 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3972 #endif /* LARGE_SMB_OFF_T */
3974 pdata+=24; /* ctime & st_blocks are not changed */
3975 tvs.actime = interpret_long_date(pdata); /* access_time */
3976 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3978 set_owner = (uid_t)IVAL(pdata,0);
3980 set_grp = (gid_t)IVAL(pdata,0);
3982 raw_unixmode = IVAL(pdata,28);
3983 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3984 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3986 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3987 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3988 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3990 if (!VALID_STAT(sbuf)) {
3993 * The only valid use of this is to create character and block
3994 * devices, and named pipes. This is deprecated (IMHO) and
3995 * a new info level should be used for mknod. JRA.
3998 uint32 file_type = IVAL(pdata,0);
3999 #if defined(HAVE_MAKEDEV)
4000 uint32 dev_major = IVAL(pdata,4);
4001 uint32 dev_minor = IVAL(pdata,12);
4004 uid_t myuid = geteuid();
4005 gid_t mygid = getegid();
4006 SMB_DEV_T dev = (SMB_DEV_T)0;
4008 if (tran_call == TRANSACT2_SETFILEINFO)
4009 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4011 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4012 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4015 #if defined(HAVE_MAKEDEV)
4016 dev = makedev(dev_major, dev_minor);
4019 /* We can only create as the owner/group we are. */
4021 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4022 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4023 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4024 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4026 switch (file_type) {
4027 #if defined(S_IFIFO)
4028 case UNIX_TYPE_FIFO:
4029 unixmode |= S_IFIFO;
4032 #if defined(S_IFSOCK)
4033 case UNIX_TYPE_SOCKET:
4034 unixmode |= S_IFSOCK;
4037 #if defined(S_IFCHR)
4038 case UNIX_TYPE_CHARDEV:
4039 unixmode |= S_IFCHR;
4042 #if defined(S_IFBLK)
4043 case UNIX_TYPE_BLKDEV:
4044 unixmode |= S_IFBLK;
4048 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4051 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4052 0%o for file %s\n", (double)dev, unixmode, fname ));
4054 /* Ok - do the mknod. */
4055 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4056 return(UNIXERROR(ERRDOS,ERRnoaccess));
4058 inherit_access_acl(conn, fname, unixmode);
4061 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4066 * Deal with the UNIX specific mode set.
4069 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4070 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4071 (unsigned int)unixmode, fname ));
4072 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4073 return(UNIXERROR(ERRDOS,ERRnoaccess));
4077 * Deal with the UNIX specific uid set.
4080 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4081 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4082 (unsigned int)set_owner, fname ));
4083 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4084 return(UNIXERROR(ERRDOS,ERRnoaccess));
4088 * Deal with the UNIX specific gid set.
4091 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4092 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4093 (unsigned int)set_owner, fname ));
4094 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4095 return(UNIXERROR(ERRDOS,ERRnoaccess));
4100 case SMB_SET_FILE_UNIX_LINK:
4102 pstring link_target;
4103 char *newname = fname;
4105 /* Set a symbolic link. */
4106 /* Don't allow this if follow links is false. */
4108 if (!lp_symlinks(SNUM(conn)))
4109 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4111 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4113 /* !widelinks forces the target path to be within the share. */
4114 /* This means we can interpret the target as a pathname. */
4115 if (!lp_widelinks(SNUM(conn))) {
4117 char *last_dirp = NULL;
4119 unix_format(link_target);
4120 if (*link_target == '/') {
4121 /* No absolute paths allowed. */
4122 return(UNIXERROR(ERRDOS,ERRnoaccess));
4124 pstrcpy(rel_name, newname);
4125 last_dirp = strrchr_m(rel_name, '/');
4127 last_dirp[1] = '\0';
4129 pstrcpy(rel_name, "./");
4131 pstrcat(rel_name, link_target);
4133 if (!check_name(rel_name, conn)) {
4134 return(UNIXERROR(ERRDOS,ERRnoaccess));
4138 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4139 fname, link_target ));
4141 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4142 return(UNIXERROR(ERRDOS,ERRnoaccess));
4144 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4148 case SMB_SET_FILE_UNIX_HLINK:
4151 char *newname = fname;
4153 /* Set a hard link. */
4154 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4155 if (!NT_STATUS_IS_OK(status)) {
4156 return ERROR_NT(status);
4159 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4162 status = hardlink_internals(conn, oldname, newname);
4163 if (!NT_STATUS_IS_OK(status)) {
4164 return ERROR_NT(status);
4168 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4172 case SMB_FILE_RENAME_INFORMATION:
4181 if (total_data < 12) {
4182 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4185 overwrite = (CVAL(pdata,0) ? True : False);
4186 root_fid = IVAL(pdata,4);
4187 len = IVAL(pdata,8);
4188 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4189 if (!NT_STATUS_IS_OK(status)) {
4190 return ERROR_NT(status);
4193 /* Check the new name has no '/' characters. */
4194 if (strchr_m(newname, '/'))
4195 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4197 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4199 /* Create the base directory. */
4200 pstrcpy(base_name, fname);
4201 p = strrchr_m(base_name, '/');
4204 /* Append the new name. */
4205 pstrcat(base_name, "/");
4206 pstrcat(base_name, newname);
4209 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4210 fsp->fnum, fsp->fsp_name, base_name ));
4211 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4213 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4215 status = rename_internals(conn, fname, base_name, 0, overwrite);
4217 if (!NT_STATUS_IS_OK(status)) {
4218 return ERROR_NT(status);
4220 process_pending_change_notify_queue((time_t)0);
4222 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4226 #if defined(HAVE_POSIX_ACLS)
4227 case SMB_SET_POSIX_ACL:
4229 uint16 posix_acl_version;
4230 uint16 num_file_acls;
4231 uint16 num_def_acls;
4232 BOOL valid_file_acls = True;
4233 BOOL valid_def_acls = True;
4235 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4236 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4238 posix_acl_version = SVAL(pdata,0);
4239 num_file_acls = SVAL(pdata,2);
4240 num_def_acls = SVAL(pdata,4);
4242 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4243 valid_file_acls = False;
4247 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4248 valid_def_acls = False;
4252 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4253 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4256 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4257 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4258 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4261 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4262 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4263 return(UNIXERROR(ERRDOS,ERRnoaccess));
4266 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4267 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4268 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4269 return(UNIXERROR(ERRDOS,ERRnoaccess));
4273 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4279 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4282 /* get some defaults (no modifications) if any info is zero or -1. */
4283 if (null_mtime(tvs.actime)) {
4284 tvs.actime = sbuf.st_atime;
4287 if (null_mtime(tvs.modtime)) {
4288 tvs.modtime = sbuf.st_mtime;
4291 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4292 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4293 DEBUG(6,("size: %.0f ", (double)size));
4296 if (S_ISDIR(sbuf.st_mode))
4302 DEBUG(6,("dosmode: %x\n" , dosmode));
4304 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4305 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4306 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4307 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4310 * Only do this test if we are not explicitly
4311 * changing the size of a file.
4314 size = get_file_size(sbuf);
4318 * Try and set the times, size and mode of this file -
4319 * if they are different from the current values
4322 /* check the mode isn't different, before changing it */
4323 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4325 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4327 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4328 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4329 return(UNIXERROR(ERRDOS,ERRnoaccess));
4334 if (size != get_file_size(sbuf)) {
4338 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4339 fname, (double)size ));
4342 files_struct *new_fsp = NULL;
4343 int access_mode = 0;
4346 if(global_oplock_break) {
4347 /* Queue this file modify as we are the process of an oplock break. */
4349 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4350 DEBUGADD(2,( "in oplock break state.\n"));
4352 push_oplock_pending_smb_message(inbuf, length);
4356 new_fsp = open_file_shared(conn, fname, &sbuf,
4357 SET_OPEN_MODE(DOS_OPEN_RDWR),
4358 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4359 FILE_ATTRIBUTE_NORMAL,
4360 INTERNAL_OPEN_ONLY, &access_mode, &action);
4362 if (new_fsp == NULL)
4363 return(UNIXERROR(ERRDOS,ERRbadpath));
4364 ret = vfs_set_filelen(new_fsp, size);
4365 close_file(new_fsp,True);
4367 ret = vfs_set_filelen(fsp, size);
4371 return (UNIXERROR(ERRHRD,ERRdiskfull));
4375 * Finally the times.
4377 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4380 * This was a setfileinfo on an open file.
4381 * NT does this a lot. We also need to
4382 * set the time here, as it can be read by
4383 * FindFirst/FindNext and with the patch for bug #2045
4384 * in smbd/fileio.c it ensures that this timestamp is
4385 * kept sticky even after a write. We save the request
4386 * away and will set it on file close and after a write. JRA.
4389 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4390 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4391 fsp_set_pending_modtime(fsp, tvs.modtime);
4395 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4397 if(file_utime(conn, fname, &tvs)!=0) {
4398 return(UNIXERROR(ERRDOS,ERRnoaccess));
4403 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4408 /****************************************************************************
4409 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4410 ****************************************************************************/
4412 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4413 char **pparams, int total_params, char **ppdata, int total_data,
4414 unsigned int max_data_bytes)
4416 char *params = *pparams;
4417 char *pdata = *ppdata;
4420 SMB_STRUCT_STAT sbuf;
4421 BOOL bad_path = False;
4422 NTSTATUS status = NT_STATUS_OK;
4423 TALLOC_CTX *ctx = NULL;
4424 struct ea_list *ea_list = NULL;
4426 if (!CAN_WRITE(conn))
4427 return ERROR_DOS(ERRSRV,ERRaccess);
4429 if (total_params < 4) {
4430 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4433 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4434 if (!NT_STATUS_IS_OK(status)) {
4435 return ERROR_NT(status);
4438 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4440 unix_convert(directory,conn,0,&bad_path,&sbuf);
4442 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4445 /* Any data in this call is an EA list. */
4446 if (total_data && !lp_ea_support(SNUM(conn))) {
4447 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4451 if (total_data < 10) {
4452 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4455 if (IVAL(pdata,0) > total_data) {
4456 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4457 IVAL(pdata,0), (unsigned int)total_data));
4458 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4461 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4463 return ERROR_NT(NT_STATUS_NO_MEMORY);
4465 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4467 talloc_destroy(ctx);
4468 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4472 if (check_name(directory,conn)) {
4473 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4477 talloc_destroy(ctx);
4478 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4479 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4482 /* Try and set any given EA. */
4484 status = set_ea(conn, NULL, directory, ea_list);
4485 talloc_destroy(ctx);
4486 if (!NT_STATUS_IS_OK(status)) {
4487 return ERROR_NT(status);
4491 /* Realloc the parameter and data sizes */
4492 params = SMB_REALLOC(*pparams,2);
4493 if(params == NULL) {
4494 return ERROR_NT(NT_STATUS_NO_MEMORY);
4500 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4505 /****************************************************************************
4506 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4507 We don't actually do this - we just send a null response.
4508 ****************************************************************************/
4510 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4511 char **pparams, int total_params, char **ppdata, int total_data,
4512 unsigned int max_data_bytes)
4514 static uint16 fnf_handle = 257;
4515 char *params = *pparams;
4518 if (total_params < 6) {
4519 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4522 info_level = SVAL(params,4);
4523 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4525 switch (info_level) {
4530 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4533 /* Realloc the parameter and data sizes */
4534 params = SMB_REALLOC(*pparams,6);
4535 if(params == NULL) {
4536 return ERROR_NT(NT_STATUS_NO_MEMORY);
4540 SSVAL(params,0,fnf_handle);
4541 SSVAL(params,2,0); /* No changes */
4542 SSVAL(params,4,0); /* No EA errors */
4549 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4554 /****************************************************************************
4555 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4556 changes). Currently this does nothing.
4557 ****************************************************************************/
4559 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4560 char **pparams, int total_params, char **ppdata, int total_data,
4561 unsigned int max_data_bytes)
4563 char *params = *pparams;
4565 DEBUG(3,("call_trans2findnotifynext\n"));
4567 /* Realloc the parameter and data sizes */
4568 params = SMB_REALLOC(*pparams,4);
4569 if(params == NULL) {
4570 return ERROR_NT(NT_STATUS_NO_MEMORY);
4574 SSVAL(params,0,0); /* No changes */
4575 SSVAL(params,2,0); /* No EA errors */
4577 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4582 /****************************************************************************
4583 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4584 ****************************************************************************/
4586 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4587 char **pparams, int total_params, char **ppdata, int total_data,
4588 unsigned int max_data_bytes)
4590 char *params = *pparams;
4593 int max_referral_level;
4595 DEBUG(10,("call_trans2getdfsreferral\n"));
4597 if (total_params < 2) {
4598 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4601 max_referral_level = SVAL(params,0);
4603 if(!lp_host_msdfs())
4604 return ERROR_DOS(ERRDOS,ERRbadfunc);
4606 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4607 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4608 return UNIXERROR(ERRDOS,ERRbadfile);
4610 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4611 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4616 #define LMCAT_SPL 0x53
4617 #define LMFUNC_GETJOBID 0x60
4619 /****************************************************************************
4620 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4621 ****************************************************************************/
4623 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4624 char **pparams, int total_params, char **ppdata, int total_data,
4625 unsigned int max_data_bytes)
4627 char *pdata = *ppdata;
4628 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4630 /* check for an invalid fid before proceeding */
4633 return(ERROR_DOS(ERRDOS,ERRbadfid));
4635 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4636 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4637 pdata = SMB_REALLOC(*ppdata, 32);
4639 return ERROR_NT(NT_STATUS_NO_MEMORY);
4643 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4644 CAN ACCEPT THIS IN UNICODE. JRA. */
4646 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4647 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4648 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4649 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4652 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4653 return ERROR_DOS(ERRSRV,ERRerror);
4657 /****************************************************************************
4658 Reply to a SMBfindclose (stop trans2 directory search).
4659 ****************************************************************************/
4661 int reply_findclose(connection_struct *conn,
4662 char *inbuf,char *outbuf,int length,int bufsize)
4665 int dptr_num=SVALS(inbuf,smb_vwv0);
4666 START_PROFILE(SMBfindclose);
4668 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4670 dptr_close(&dptr_num);
4672 outsize = set_message(outbuf,0,0,True);
4674 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4676 END_PROFILE(SMBfindclose);
4680 /****************************************************************************
4681 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4682 ****************************************************************************/
4684 int reply_findnclose(connection_struct *conn,
4685 char *inbuf,char *outbuf,int length,int bufsize)
4689 START_PROFILE(SMBfindnclose);
4691 dptr_num = SVAL(inbuf,smb_vwv0);
4693 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4695 /* We never give out valid handles for a
4696 findnotifyfirst - so any dptr_num is ok here.
4699 outsize = set_message(outbuf,0,0,True);
4701 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4703 END_PROFILE(SMBfindnclose);
4707 /****************************************************************************
4708 Reply to a SMBtranss2 - just ignore it!
4709 ****************************************************************************/
4711 int reply_transs2(connection_struct *conn,
4712 char *inbuf,char *outbuf,int length,int bufsize)
4714 START_PROFILE(SMBtranss2);
4715 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4716 END_PROFILE(SMBtranss2);
4720 /****************************************************************************
4721 Reply to a SMBtrans2.
4722 ****************************************************************************/
4724 int reply_trans2(connection_struct *conn,
4725 char *inbuf,char *outbuf,int length,int bufsize)
4728 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4729 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4730 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4732 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4733 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4734 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4735 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4736 int32 timeout = IVALS(inbuf,smb_timeout);
4738 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4739 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4740 char *params = NULL, *data = NULL;
4741 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4742 START_PROFILE(SMBtrans2);
4744 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4745 /* Queue this open message as we are the process of an
4748 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4749 DEBUGADD(2,( "in oplock break state.\n"));
4751 push_oplock_pending_smb_message(inbuf, length);
4752 END_PROFILE(SMBtrans2);
4756 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4757 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4758 END_PROFILE(SMBtrans2);
4759 return ERROR_DOS(ERRSRV,ERRaccess);
4762 outsize = set_message(outbuf,0,0,True);
4764 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4765 is so as a sanity check */
4768 * Need to have rc=0 for ioctl to get job id for OS/2.
4769 * Network printing will fail if function is not successful.
4770 * Similar function in reply.c will be used if protocol
4771 * is LANMAN1.0 instead of LM1.2X002.
4772 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4773 * outbuf doesn't have to be set(only job id is used).
4775 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4776 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4777 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4778 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4780 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4781 DEBUG(2,("Transaction is %d\n",tran_call));
4782 END_PROFILE(SMBtrans2);
4783 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4787 /* Allocate the space for the maximum needed parameters and data */
4788 if (total_params > 0)
4789 params = (char *)SMB_MALLOC(total_params);
4791 data = (char *)SMB_MALLOC(total_data);
4793 if ((total_params && !params) || (total_data && !data)) {
4794 DEBUG(2,("Out of memory in reply_trans2\n"));
4797 END_PROFILE(SMBtrans2);
4798 return ERROR_NT(NT_STATUS_NO_MEMORY);
4801 /* Copy the param and data bytes sent with this request into
4802 the params buffer */
4803 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4804 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4806 if (num_params > total_params || num_data > total_data)
4807 exit_server("invalid params in reply_trans2");
4810 unsigned int psoff = SVAL(inbuf, smb_psoff);
4811 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4813 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4814 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4816 memcpy( params, smb_base(inbuf) + psoff, num_params);
4819 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4820 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4822 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4823 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4825 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4828 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4830 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4831 /* We need to send an interim response then receive the rest
4832 of the parameter/data bytes */
4833 outsize = set_message(outbuf,0,0,True);
4834 srv_signing_trans_stop();
4835 if (!send_smb(smbd_server_fd(),outbuf))
4836 exit_server("reply_trans2: send_smb failed.");
4838 while (num_data_sofar < total_data ||
4839 num_params_sofar < total_params) {
4841 unsigned int param_disp;
4842 unsigned int param_off;
4843 unsigned int data_disp;
4844 unsigned int data_off;
4846 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4849 * The sequence number for the trans reply is always
4850 * based on the last secondary received.
4853 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4856 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4857 outsize = set_message(outbuf,0,0,True);
4859 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4861 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4862 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4866 /* Revise total_params and total_data in case
4867 they have changed downwards */
4868 if (SVAL(inbuf, smb_tpscnt) < total_params)
4869 total_params = SVAL(inbuf, smb_tpscnt);
4870 if (SVAL(inbuf, smb_tdscnt) < total_data)
4871 total_data = SVAL(inbuf, smb_tdscnt);
4873 num_params = SVAL(inbuf,smb_spscnt);
4874 param_off = SVAL(inbuf, smb_spsoff);
4875 param_disp = SVAL(inbuf, smb_spsdisp);
4876 num_params_sofar += num_params;
4878 num_data = SVAL(inbuf, smb_sdscnt);
4879 data_off = SVAL(inbuf, smb_sdsoff);
4880 data_disp = SVAL(inbuf, smb_sdsdisp);
4881 num_data_sofar += num_data;
4883 if (num_params_sofar > total_params || num_data_sofar > total_data)
4887 if (param_disp + num_params > total_params)
4889 if ((param_disp + num_params < param_disp) ||
4890 (param_disp + num_params < num_params))
4892 if (param_disp > total_params)
4894 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4895 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4897 if (params + param_disp < params)
4900 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4903 if (data_disp + num_data > total_data)
4905 if ((data_disp + num_data < data_disp) ||
4906 (data_disp + num_data < num_data))
4908 if (data_disp > total_data)
4910 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4911 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4913 if (data + data_disp < data)
4916 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4921 if (Protocol >= PROTOCOL_NT1) {
4922 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4925 /* Now we must call the relevant TRANS2 function */
4927 case TRANSACT2_OPEN:
4928 START_PROFILE_NESTED(Trans2_open);
4929 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4930 ¶ms, total_params, &data, total_data, max_data_bytes);
4931 END_PROFILE_NESTED(Trans2_open);
4934 case TRANSACT2_FINDFIRST:
4935 START_PROFILE_NESTED(Trans2_findfirst);
4936 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4937 ¶ms, total_params, &data, total_data, max_data_bytes);
4938 END_PROFILE_NESTED(Trans2_findfirst);
4941 case TRANSACT2_FINDNEXT:
4942 START_PROFILE_NESTED(Trans2_findnext);
4943 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4944 ¶ms, total_params, &data, total_data, max_data_bytes);
4945 END_PROFILE_NESTED(Trans2_findnext);
4948 case TRANSACT2_QFSINFO:
4949 START_PROFILE_NESTED(Trans2_qfsinfo);
4950 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4951 ¶ms, total_params, &data, total_data, max_data_bytes);
4952 END_PROFILE_NESTED(Trans2_qfsinfo);
4955 #ifdef HAVE_SYS_QUOTAS
4956 case TRANSACT2_SETFSINFO:
4957 START_PROFILE_NESTED(Trans2_setfsinfo);
4958 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4959 ¶ms, total_params, &data, total_data, max_data_bytes);
4960 END_PROFILE_NESTED(Trans2_setfsinfo);
4963 case TRANSACT2_QPATHINFO:
4964 case TRANSACT2_QFILEINFO:
4965 START_PROFILE_NESTED(Trans2_qpathinfo);
4966 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4967 ¶ms, total_params, &data, total_data, max_data_bytes);
4968 END_PROFILE_NESTED(Trans2_qpathinfo);
4970 case TRANSACT2_SETPATHINFO:
4971 case TRANSACT2_SETFILEINFO:
4972 START_PROFILE_NESTED(Trans2_setpathinfo);
4973 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4974 ¶ms, total_params, &data, total_data, max_data_bytes);
4975 END_PROFILE_NESTED(Trans2_setpathinfo);
4978 case TRANSACT2_FINDNOTIFYFIRST:
4979 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4980 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4981 ¶ms, total_params, &data, total_data, max_data_bytes);
4982 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4985 case TRANSACT2_FINDNOTIFYNEXT:
4986 START_PROFILE_NESTED(Trans2_findnotifynext);
4987 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4988 ¶ms, total_params, &data, total_data, max_data_bytes);
4989 END_PROFILE_NESTED(Trans2_findnotifynext);
4991 case TRANSACT2_MKDIR:
4992 START_PROFILE_NESTED(Trans2_mkdir);
4993 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4994 ¶ms, total_params, &data, total_data, max_data_bytes);
4995 END_PROFILE_NESTED(Trans2_mkdir);
4998 case TRANSACT2_GET_DFS_REFERRAL:
4999 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5000 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5001 ¶ms, total_params, &data, total_data, max_data_bytes);
5002 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5004 case TRANSACT2_IOCTL:
5005 START_PROFILE_NESTED(Trans2_ioctl);
5006 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5007 ¶ms, total_params, &data, total_data, max_data_bytes);
5008 END_PROFILE_NESTED(Trans2_ioctl);
5011 /* Error in request */
5012 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5015 END_PROFILE(SMBtrans2);
5016 srv_signing_trans_stop();
5017 return ERROR_DOS(ERRSRV,ERRerror);
5020 /* As we do not know how many data packets will need to be
5021 returned here the various call_trans2xxxx calls
5022 must send their own. Thus a call_trans2xxx routine only
5023 returns a value other than -1 when it wants to send
5027 srv_signing_trans_stop();
5031 END_PROFILE(SMBtrans2);
5032 return outsize; /* If a correct response was needed the
5033 call_trans2xxx calls have already sent
5034 it. If outsize != -1 then it is returning */
5038 srv_signing_trans_stop();
5041 END_PROFILE(SMBtrans2);
5042 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);