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;
717 BOOL return_additional_info;
726 int fmode=0,mtime=0,rmode;
728 SMB_STRUCT_STAT sbuf;
730 BOOL bad_path = False;
735 * Ensure we have enough parameters to perform the operation.
738 if (total_params < 29) {
739 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
742 open_mode = SVAL(params, 2);
743 open_attr = SVAL(params,6);
744 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
746 return_additional_info = BITSETW(params,0);
747 open_sattr = SVAL(params, 4);
748 open_time = make_unix_date3(params+8);
750 open_ofun = SVAL(params,12);
751 open_size = IVAL(params,14);
755 return(ERROR_DOS(ERRSRV,ERRaccess));
757 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
758 if (!NT_STATUS_IS_OK(status)) {
759 return ERROR_NT(status);
762 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
763 fname,open_mode, open_attr, open_ofun, open_size));
765 /* XXXX we need to handle passed times, sattr and flags */
767 unix_convert(fname,conn,0,&bad_path,&sbuf);
769 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
772 if (!check_name(fname,conn)) {
773 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
776 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
777 oplock_request, &rmode,&smb_action);
780 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
781 /* We have re-scheduled this call. */
782 clear_cached_errors();
785 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
788 size = get_file_size(sbuf);
789 fmode = dos_mode(conn,fname,&sbuf);
790 mtime = sbuf.st_mtime;
793 close_file(fsp,False);
794 return(ERROR_DOS(ERRDOS,ERRnoaccess));
797 /* Realloc the size of parameters and data we will return */
798 params = SMB_REALLOC(*pparams, 28);
799 if( params == NULL ) {
800 return ERROR_NT(NT_STATUS_NO_MEMORY);
804 memset((char *)params,'\0',28);
805 SSVAL(params,0,fsp->fnum);
806 SSVAL(params,2,fmode);
807 put_dos_date2(params,4, mtime);
808 SIVAL(params,8, (uint32)size);
809 SSVAL(params,12,rmode);
811 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
812 smb_action |= EXTENDED_OPLOCK_GRANTED;
814 SSVAL(params,18,smb_action);
817 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
819 SIVAL(params,20,inode);
821 /* Send the required number of replies */
822 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
827 /*********************************************************
828 Routine to check if a given string matches exactly.
829 as a special case a mask of "." does NOT match. That
830 is required for correct wildcard semantics
831 Case can be significant or not.
832 **********************************************************/
834 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
836 if (mask[0] == '.' && mask[1] == 0)
839 return strcmp(str,mask)==0;
840 if (StrCaseCmp(str,mask) != 0) {
843 if (ms_has_wild(str)) {
849 /****************************************************************************
850 Return the filetype for UNIX extensions.
851 ****************************************************************************/
853 static uint32 unix_filetype(mode_t mode)
856 return UNIX_TYPE_FILE;
857 else if(S_ISDIR(mode))
858 return UNIX_TYPE_DIR;
860 else if(S_ISLNK(mode))
861 return UNIX_TYPE_SYMLINK;
864 else if(S_ISCHR(mode))
865 return UNIX_TYPE_CHARDEV;
868 else if(S_ISBLK(mode))
869 return UNIX_TYPE_BLKDEV;
872 else if(S_ISFIFO(mode))
873 return UNIX_TYPE_FIFO;
876 else if(S_ISSOCK(mode))
877 return UNIX_TYPE_SOCKET;
880 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
881 return UNIX_TYPE_UNKNOWN;
884 /****************************************************************************
885 Map wire perms onto standard UNIX permissions. Obey share restrictions.
886 ****************************************************************************/
888 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
892 if (perms == SMB_MODE_NO_CHANGE)
895 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
896 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
897 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
898 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
899 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
900 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
901 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
902 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
903 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
905 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
908 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
911 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
914 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
915 ret &= lp_dir_mask(SNUM(conn));
916 /* Add in force bits */
917 ret |= lp_force_dir_mode(SNUM(conn));
919 /* Apply mode mask */
920 ret &= lp_create_mask(SNUM(conn));
921 /* Add in force bits */
922 ret |= lp_force_create_mode(SNUM(conn));
928 /****************************************************************************
929 Get a level dependent lanman2 dir entry.
930 ****************************************************************************/
932 static BOOL get_lanman2_dir_entry(connection_struct *conn,
933 void *inbuf, void *outbuf,
934 char *path_mask,int dirtype,int info_level,
935 int requires_resume_key,
936 BOOL dont_descend,char **ppdata,
937 char *base_data, int space_remaining,
938 BOOL *out_of_space, BOOL *got_exact_match,
939 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
943 SMB_STRUCT_STAT sbuf;
947 char *p, *q, *pdata = *ppdata;
951 SMB_OFF_T file_size = 0;
952 SMB_BIG_UINT allocation_size = 0;
954 time_t mdate=0, adate=0, cdate=0;
956 char *last_entry_ptr;
958 int nt_extmode; /* Used for NT connections instead of mode */
959 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
962 *out_of_space = False;
963 *got_exact_match = False;
968 p = strrchr_m(path_mask,'/');
975 pstrcpy(mask, path_mask);
980 /* Needed if we run out of space */
981 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
982 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
985 * Due to bugs in NT client redirectors we are not using
986 * resume keys any more - set them to zero.
987 * Check out the related comments in findfirst/findnext.
993 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
994 (long)conn->dirptr,curr_dirpos));
999 pstrcpy(fname,dname);
1001 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1002 got_match = mask_match(fname, mask, conn->case_sensitive);
1004 if(!got_match && !mangle_is_8_3(fname, False)) {
1007 * It turns out that NT matches wildcards against
1008 * both long *and* short names. This may explain some
1009 * of the wildcard wierdness from old DOS clients
1010 * that some people have been seeing.... JRA.
1014 pstrcpy( newname, fname);
1015 mangle_map( newname, True, False, SNUM(conn));
1016 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1017 got_match = mask_match(newname, mask, conn->case_sensitive);
1021 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1022 if (dont_descend && !isdots)
1025 pstrcpy(pathreal,conn->dirpath);
1027 pstrcat(pathreal,"/");
1028 pstrcat(pathreal,dname);
1030 if (INFO_LEVEL_IS_UNIX(info_level)) {
1031 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1032 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1033 pathreal,strerror(errno)));
1036 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1038 /* Needed to show the msdfs symlinks as
1041 if(lp_host_msdfs() &&
1042 lp_msdfs_root(SNUM(conn)) &&
1043 is_msdfs_link(conn, pathreal, NULL, NULL,
1046 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1047 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1051 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1052 pathreal,strerror(errno)));
1057 mode = dos_mode(conn,pathreal,&sbuf);
1059 if (!dir_check_ftype(conn,mode,dirtype)) {
1060 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1064 file_size = get_file_size(sbuf);
1065 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1066 mdate = sbuf.st_mtime;
1067 adate = sbuf.st_atime;
1068 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1070 if (lp_dos_filetime_resolution(SNUM(conn))) {
1077 /* This is necessary, as otherwise the
1078 * desktop.ini file in this folder is
1080 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1084 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1090 mangle_map(fname,False,True,SNUM(conn));
1095 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1097 switch (info_level) {
1098 case SMB_FIND_INFO_STANDARD:
1099 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1100 if(requires_resume_key) {
1104 put_dos_date2(p,l1_fdateCreation,cdate);
1105 put_dos_date2(p,l1_fdateLastAccess,adate);
1106 put_dos_date2(p,l1_fdateLastWrite,mdate);
1107 SIVAL(p,l1_cbFile,(uint32)file_size);
1108 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1109 SSVAL(p,l1_attrFile,mode);
1112 p += align_string(outbuf, p, 0);
1113 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1114 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1116 SCVAL(nameptr, -1, len - 2);
1118 SCVAL(nameptr, -1, 0);
1122 SCVAL(nameptr, -1, len - 1);
1124 SCVAL(nameptr, -1, 0);
1130 case SMB_FIND_EA_SIZE:
1131 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1132 if(requires_resume_key) {
1136 put_dos_date2(p,l2_fdateCreation,cdate);
1137 put_dos_date2(p,l2_fdateLastAccess,adate);
1138 put_dos_date2(p,l2_fdateLastWrite,mdate);
1139 SIVAL(p,l2_cbFile,(uint32)file_size);
1140 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1141 SSVAL(p,l2_attrFile,mode);
1143 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1144 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1148 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1149 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1162 SCVAL(nameptr,0,len);
1164 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1167 case SMB_FIND_EA_LIST:
1169 struct ea_list *file_list = NULL;
1172 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1176 if(requires_resume_key) {
1180 put_dos_date2(p,l2_fdateCreation,cdate);
1181 put_dos_date2(p,l2_fdateLastAccess,adate);
1182 put_dos_date2(p,l2_fdateLastWrite,mdate);
1183 SIVAL(p,l2_cbFile,(uint32)file_size);
1184 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1185 SSVAL(p,l2_attrFile,mode);
1186 p += l2_cbList; /* p now points to the EA area. */
1188 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1189 name_list = ea_list_union(name_list, file_list, &ea_len);
1191 /* We need to determine if this entry will fit in the space available. */
1192 /* Max string size is 255 bytes. */
1193 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1194 /* Move the dirptr back to prev_dirpos */
1195 dptr_SeekDir(conn->dirptr, prev_dirpos);
1196 *out_of_space = True;
1197 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1198 return False; /* Not finished - just out of space */
1201 /* Push the ea_data followed by the name. */
1202 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1204 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1205 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1218 SCVAL(nameptr,0,len);
1220 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1224 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1225 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1226 was_8_3 = mangle_is_8_3(fname, True);
1228 SIVAL(p,0,reskey); p += 4;
1229 put_long_date(p,cdate); p += 8;
1230 put_long_date(p,adate); p += 8;
1231 put_long_date(p,mdate); p += 8;
1232 put_long_date(p,mdate); p += 8;
1233 SOFF_T(p,0,file_size); p += 8;
1234 SOFF_T(p,0,allocation_size); p += 8;
1235 SIVAL(p,0,nt_extmode); p += 4;
1236 q = p; p += 4; /* q is placeholder for name length. */
1238 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1239 SIVAL(p,0,ea_size); /* Extended attributes */
1242 /* Clear the short name buffer. This is
1243 * IMPORTANT as not doing so will trigger
1244 * a Win2k client bug. JRA.
1247 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1248 pstring mangled_name;
1249 pstrcpy(mangled_name, fname);
1250 mangle_map(mangled_name,True,True,SNUM(conn));
1251 mangled_name[12] = 0;
1252 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1259 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1262 len = PTR_DIFF(p, pdata);
1263 len = (len + 3) & ~3;
1268 case SMB_FIND_FILE_DIRECTORY_INFO:
1269 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1271 SIVAL(p,0,reskey); p += 4;
1272 put_long_date(p,cdate); p += 8;
1273 put_long_date(p,adate); p += 8;
1274 put_long_date(p,mdate); p += 8;
1275 put_long_date(p,mdate); p += 8;
1276 SOFF_T(p,0,file_size); p += 8;
1277 SOFF_T(p,0,allocation_size); p += 8;
1278 SIVAL(p,0,nt_extmode); p += 4;
1279 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1282 len = PTR_DIFF(p, pdata);
1283 len = (len + 3) & ~3;
1288 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1289 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1291 SIVAL(p,0,reskey); p += 4;
1292 put_long_date(p,cdate); p += 8;
1293 put_long_date(p,adate); p += 8;
1294 put_long_date(p,mdate); p += 8;
1295 put_long_date(p,mdate); p += 8;
1296 SOFF_T(p,0,file_size); p += 8;
1297 SOFF_T(p,0,allocation_size); p += 8;
1298 SIVAL(p,0,nt_extmode); p += 4;
1299 q = p; p += 4; /* q is placeholder for name length. */
1301 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1302 SIVAL(p,0,ea_size); /* Extended attributes */
1305 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1309 len = PTR_DIFF(p, pdata);
1310 len = (len + 3) & ~3;
1315 case SMB_FIND_FILE_NAMES_INFO:
1316 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1318 SIVAL(p,0,reskey); p += 4;
1320 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1321 acl on a dir (tridge) */
1322 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1325 len = PTR_DIFF(p, pdata);
1326 len = (len + 3) & ~3;
1331 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1332 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1334 SIVAL(p,0,reskey); p += 4;
1335 put_long_date(p,cdate); p += 8;
1336 put_long_date(p,adate); p += 8;
1337 put_long_date(p,mdate); p += 8;
1338 put_long_date(p,mdate); p += 8;
1339 SOFF_T(p,0,file_size); p += 8;
1340 SOFF_T(p,0,allocation_size); p += 8;
1341 SIVAL(p,0,nt_extmode); p += 4;
1342 q = p; p += 4; /* q is placeholder for name length. */
1344 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1345 SIVAL(p,0,ea_size); /* Extended attributes */
1348 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1349 SIVAL(p,0,sbuf.st_dev); p += 4;
1350 SIVAL(p,0,sbuf.st_ino); p += 4;
1351 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1354 len = PTR_DIFF(p, pdata);
1355 len = (len + 3) & ~3;
1360 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1361 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1362 was_8_3 = mangle_is_8_3(fname, True);
1364 SIVAL(p,0,reskey); p += 4;
1365 put_long_date(p,cdate); p += 8;
1366 put_long_date(p,adate); p += 8;
1367 put_long_date(p,mdate); p += 8;
1368 put_long_date(p,mdate); p += 8;
1369 SOFF_T(p,0,file_size); p += 8;
1370 SOFF_T(p,0,allocation_size); p += 8;
1371 SIVAL(p,0,nt_extmode); p += 4;
1372 q = p; p += 4; /* q is placeholder for name length */
1374 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1375 SIVAL(p,0,ea_size); /* Extended attributes */
1378 /* Clear the short name buffer. This is
1379 * IMPORTANT as not doing so will trigger
1380 * a Win2k client bug. JRA.
1383 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1384 pstring mangled_name;
1385 pstrcpy(mangled_name, fname);
1386 mangle_map(mangled_name,True,True,SNUM(conn));
1387 mangled_name[12] = 0;
1388 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1395 SSVAL(p,0,0); p += 2; /* Reserved ? */
1396 SIVAL(p,0,sbuf.st_dev); p += 4;
1397 SIVAL(p,0,sbuf.st_ino); p += 4;
1398 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1401 len = PTR_DIFF(p, pdata);
1402 len = (len + 3) & ~3;
1407 /* CIFS UNIX Extension. */
1409 case SMB_FIND_FILE_UNIX:
1410 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1412 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1414 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1415 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1418 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1421 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1422 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1423 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1426 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1430 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1434 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1437 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1441 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1445 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1448 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1452 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1456 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1459 len = PTR_DIFF(p, pdata);
1460 len = (len + 3) & ~3;
1461 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1463 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1472 if (PTR_DIFF(p,pdata) > space_remaining) {
1473 /* Move the dirptr back to prev_dirpos */
1474 dptr_SeekDir(conn->dirptr, prev_dirpos);
1475 *out_of_space = True;
1476 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1477 return False; /* Not finished - just out of space */
1480 /* Setup the last entry pointer, as an offset from base_data */
1481 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1482 /* Advance the data pointer to the next slot */
1488 /****************************************************************************
1489 Reply to a TRANS2_FINDFIRST.
1490 ****************************************************************************/
1492 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1493 char **pparams, int total_params, char **ppdata, int total_data,
1494 unsigned int max_data_bytes)
1496 /* We must be careful here that we don't return more than the
1497 allowed number of data bytes. If this means returning fewer than
1498 maxentries then so be it. We assume that the redirector has
1499 enough room for the fixed number of parameter bytes it has
1501 char *params = *pparams;
1502 char *pdata = *ppdata;
1503 int dirtype = SVAL(params,0);
1504 int maxentries = SVAL(params,2);
1505 uint16 findfirst_flags = SVAL(params,4);
1506 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1507 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1508 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1509 int info_level = SVAL(params,6);
1513 int last_entry_off=0;
1517 BOOL finished = False;
1518 BOOL dont_descend = False;
1519 BOOL out_of_space = False;
1520 int space_remaining;
1521 BOOL bad_path = False;
1522 SMB_STRUCT_STAT sbuf;
1523 TALLOC_CTX *ea_ctx = NULL;
1524 struct ea_list *ea_list = NULL;
1525 NTSTATUS ntstatus = NT_STATUS_OK;
1527 if (total_params < 12) {
1528 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1531 *directory = *mask = 0;
1533 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1534 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1535 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1536 info_level, max_data_bytes));
1539 /* W2K3 seems to treat zero as 1. */
1543 switch (info_level) {
1544 case SMB_FIND_INFO_STANDARD:
1545 case SMB_FIND_EA_SIZE:
1546 case SMB_FIND_EA_LIST:
1547 case SMB_FIND_FILE_DIRECTORY_INFO:
1548 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1549 case SMB_FIND_FILE_NAMES_INFO:
1550 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1551 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1552 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1554 case SMB_FIND_FILE_UNIX:
1555 if (!lp_unix_extensions())
1556 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1559 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1562 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1563 if (!NT_STATUS_IS_OK(ntstatus)) {
1564 return ERROR_NT(ntstatus);
1567 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1569 unix_convert(directory,conn,0,&bad_path,&sbuf);
1571 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1573 if(!check_name(directory,conn)) {
1574 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1577 p = strrchr_m(directory,'/');
1579 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1580 if((directory[0] == '.') && (directory[1] == '\0'))
1583 pstrcpy(mask,directory);
1584 pstrcpy(directory,"./");
1590 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1592 if (info_level == SMB_FIND_EA_LIST) {
1595 if (total_data < 4) {
1596 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1599 ea_size = IVAL(pdata,0);
1600 if (ea_size != total_data) {
1601 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1602 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1603 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1606 if (!lp_ea_support(SNUM(conn))) {
1607 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1610 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1611 return ERROR_NT(NT_STATUS_NO_MEMORY);
1614 /* Pull out the list of names. */
1615 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1617 talloc_destroy(ea_ctx);
1618 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1622 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1623 if( pdata == NULL ) {
1624 talloc_destroy(ea_ctx);
1625 return ERROR_NT(NT_STATUS_NO_MEMORY);
1629 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1631 /* Realloc the params space */
1632 params = SMB_REALLOC(*pparams, 10);
1633 if (params == NULL) {
1634 talloc_destroy(ea_ctx);
1635 return ERROR_NT(NT_STATUS_NO_MEMORY);
1639 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1641 talloc_destroy(ea_ctx);
1642 return(UNIXERROR(ERRDOS,ERRbadfile));
1645 /* Save the wildcard match and attribs we are using on this directory -
1646 needed as lanman2 assumes these are being saved between calls */
1648 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1649 dptr_close(&dptr_num);
1650 talloc_destroy(ea_ctx);
1651 return ERROR_NT(NT_STATUS_NO_MEMORY);
1654 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1656 /* We don't need to check for VOL here as this is returned by
1657 a different TRANS2 call. */
1659 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1660 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1661 dont_descend = True;
1664 space_remaining = max_data_bytes;
1665 out_of_space = False;
1667 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1668 BOOL got_exact_match = False;
1670 /* this is a heuristic to avoid seeking the dirptr except when
1671 absolutely necessary. It allows for a filename of about 40 chars */
1672 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1673 out_of_space = True;
1676 finished = !get_lanman2_dir_entry(conn,
1678 mask,dirtype,info_level,
1679 requires_resume_key,dont_descend,
1680 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1681 &last_entry_off, ea_list, ea_ctx);
1684 if (finished && out_of_space)
1687 if (!finished && !out_of_space)
1691 * As an optimisation if we know we aren't looking
1692 * for a wildcard name (ie. the name matches the wildcard exactly)
1693 * then we can finish on any (first) match.
1694 * This speeds up large directory searches. JRA.
1700 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1703 talloc_destroy(ea_ctx);
1705 /* Check if we can close the dirptr */
1706 if(close_after_first || (finished && close_if_end)) {
1707 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1708 dptr_close(&dptr_num);
1712 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1713 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1714 * the protocol level is less than NT1. Tested with smbclient. JRA.
1715 * This should fix the OS/2 client bug #2335.
1718 if(numentries == 0) {
1719 dptr_close(&dptr_num);
1720 if (Protocol < PROTOCOL_NT1) {
1721 return ERROR_DOS(ERRDOS,ERRnofiles);
1723 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1727 /* At this point pdata points to numentries directory entries. */
1729 /* Set up the return parameter block */
1730 SSVAL(params,0,dptr_num);
1731 SSVAL(params,2,numentries);
1732 SSVAL(params,4,finished);
1733 SSVAL(params,6,0); /* Never an EA error */
1734 SSVAL(params,8,last_entry_off);
1736 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1738 if ((! *directory) && dptr_path(dptr_num))
1739 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1741 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1742 smb_fn_name(CVAL(inbuf,smb_com)),
1743 mask, directory, dirtype, numentries ) );
1746 * Force a name mangle here to ensure that the
1747 * mask as an 8.3 name is top of the mangled cache.
1748 * The reasons for this are subtle. Don't remove
1749 * this code unless you know what you are doing
1750 * (see PR#13758). JRA.
1753 if(!mangle_is_8_3_wildcards( mask, False))
1754 mangle_map(mask, True, True, SNUM(conn));
1759 /****************************************************************************
1760 Reply to a TRANS2_FINDNEXT.
1761 ****************************************************************************/
1763 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1764 char **pparams, int total_params, char **ppdata, int total_data,
1765 unsigned int max_data_bytes)
1767 /* We must be careful here that we don't return more than the
1768 allowed number of data bytes. If this means returning fewer than
1769 maxentries then so be it. We assume that the redirector has
1770 enough room for the fixed number of parameter bytes it has
1772 char *params = *pparams;
1773 char *pdata = *ppdata;
1774 int dptr_num = SVAL(params,0);
1775 int maxentries = SVAL(params,2);
1776 uint16 info_level = SVAL(params,4);
1777 uint32 resume_key = IVAL(params,6);
1778 uint16 findnext_flags = SVAL(params,10);
1779 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1780 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1781 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1782 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1783 pstring resume_name;
1789 int i, last_entry_off=0;
1790 BOOL finished = False;
1791 BOOL dont_descend = False;
1792 BOOL out_of_space = False;
1793 int space_remaining;
1794 TALLOC_CTX *ea_ctx = NULL;
1795 struct ea_list *ea_list = NULL;
1796 NTSTATUS ntstatus = NT_STATUS_OK;
1798 if (total_params < 12) {
1799 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1802 *mask = *directory = *resume_name = 0;
1804 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1805 if (!NT_STATUS_IS_OK(ntstatus)) {
1806 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1807 complain (it thinks we're asking for the directory above the shared
1808 path or an invalid name). Catch this as the resume name is only compared, never used in
1809 a file access. JRA. */
1810 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1811 pstrcpy(resume_name, "..");
1812 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1813 pstrcpy(resume_name, ".");
1815 return ERROR_NT(ntstatus);
1819 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1820 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1821 resume_key = %d resume name = %s continue=%d level = %d\n",
1822 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1823 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1826 /* W2K3 seems to treat zero as 1. */
1830 switch (info_level) {
1831 case SMB_FIND_INFO_STANDARD:
1832 case SMB_FIND_EA_SIZE:
1833 case SMB_FIND_EA_LIST:
1834 case SMB_FIND_FILE_DIRECTORY_INFO:
1835 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1836 case SMB_FIND_FILE_NAMES_INFO:
1837 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1839 case SMB_FIND_FILE_UNIX:
1840 if (!lp_unix_extensions())
1841 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1844 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1847 if (info_level == SMB_FIND_EA_LIST) {
1850 if (total_data < 4) {
1851 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1854 ea_size = IVAL(pdata,0);
1855 if (ea_size != total_data) {
1856 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1857 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1861 if (!lp_ea_support(SNUM(conn))) {
1862 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1865 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1866 return ERROR_NT(NT_STATUS_NO_MEMORY);
1869 /* Pull out the list of names. */
1870 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1872 talloc_destroy(ea_ctx);
1873 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1877 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1879 talloc_destroy(ea_ctx);
1880 return ERROR_NT(NT_STATUS_NO_MEMORY);
1884 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1886 /* Realloc the params space */
1887 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1888 if( params == NULL ) {
1889 talloc_destroy(ea_ctx);
1890 return ERROR_NT(NT_STATUS_NO_MEMORY);
1895 /* Check that the dptr is valid */
1896 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1897 talloc_destroy(ea_ctx);
1898 return ERROR_DOS(ERRDOS,ERRnofiles);
1901 string_set(&conn->dirpath,dptr_path(dptr_num));
1903 /* Get the wildcard mask from the dptr */
1904 if((p = dptr_wcard(dptr_num))== NULL) {
1905 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1906 talloc_destroy(ea_ctx);
1907 return ERROR_DOS(ERRDOS,ERRnofiles);
1911 pstrcpy(directory,conn->dirpath);
1913 /* Get the attr mask from the dptr */
1914 dirtype = dptr_attr(dptr_num);
1916 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1917 dptr_num, mask, dirtype,
1919 dptr_TellDir(conn->dirptr)));
1921 /* We don't need to check for VOL here as this is returned by
1922 a different TRANS2 call. */
1924 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1925 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1926 dont_descend = True;
1929 space_remaining = max_data_bytes;
1930 out_of_space = False;
1933 * Seek to the correct position. We no longer use the resume key but
1934 * depend on the last file name instead.
1937 if(*resume_name && !continue_bit) {
1940 long current_pos = 0;
1942 * Remember, mangle_map is called by
1943 * get_lanman2_dir_entry(), so the resume name
1944 * could be mangled. Ensure we check the unmangled name.
1947 if (mangle_is_mangled(resume_name)) {
1948 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1952 * Fix for NT redirector problem triggered by resume key indexes
1953 * changing between directory scans. We now return a resume key of 0
1954 * and instead look for the filename to continue from (also given
1955 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1956 * findfirst/findnext (as is usual) then the directory pointer
1957 * should already be at the correct place.
1960 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
1961 } /* end if resume_name && !continue_bit */
1963 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1964 BOOL got_exact_match = False;
1966 /* this is a heuristic to avoid seeking the dirptr except when
1967 absolutely necessary. It allows for a filename of about 40 chars */
1968 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1969 out_of_space = True;
1972 finished = !get_lanman2_dir_entry(conn,
1974 mask,dirtype,info_level,
1975 requires_resume_key,dont_descend,
1976 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1977 &last_entry_off, ea_list, ea_ctx);
1980 if (finished && out_of_space)
1983 if (!finished && !out_of_space)
1987 * As an optimisation if we know we aren't looking
1988 * for a wildcard name (ie. the name matches the wildcard exactly)
1989 * then we can finish on any (first) match.
1990 * This speeds up large directory searches. JRA.
1996 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1999 talloc_destroy(ea_ctx);
2001 /* Check if we can close the dirptr */
2002 if(close_after_request || (finished && close_if_end)) {
2003 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2004 dptr_close(&dptr_num); /* This frees up the saved mask */
2007 /* Set up the return parameter block */
2008 SSVAL(params,0,numentries);
2009 SSVAL(params,2,finished);
2010 SSVAL(params,4,0); /* Never an EA error */
2011 SSVAL(params,6,last_entry_off);
2013 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2015 if ((! *directory) && dptr_path(dptr_num))
2016 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2018 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2019 smb_fn_name(CVAL(inbuf,smb_com)),
2020 mask, directory, dirtype, numentries ) );
2025 /****************************************************************************
2026 Reply to a TRANS2_QFSINFO (query filesystem info).
2027 ****************************************************************************/
2029 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2030 char **pparams, int total_params, char **ppdata, int total_data,
2031 unsigned int max_data_bytes)
2033 char *pdata = *ppdata;
2034 char *params = *pparams;
2035 uint16 info_level = SVAL(params,0);
2038 char *vname = volume_label(SNUM(conn));
2039 int snum = SNUM(conn);
2040 char *fstype = lp_fstype(SNUM(conn));
2043 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2045 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2046 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2047 return ERROR_DOS(ERRSRV,ERRinvdevice);
2050 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2051 if ( pdata == NULL ) {
2052 return ERROR_NT(NT_STATUS_NO_MEMORY);
2056 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2058 switch (info_level) {
2059 case SMB_INFO_ALLOCATION:
2061 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2063 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2064 return(UNIXERROR(ERRHRD,ERRgeneral));
2067 block_size = lp_block_size(snum);
2068 if (bsize < block_size) {
2069 SMB_BIG_UINT factor = block_size/bsize;
2074 if (bsize > block_size) {
2075 SMB_BIG_UINT factor = bsize/block_size;
2080 bytes_per_sector = 512;
2081 sectors_per_unit = bsize/bytes_per_sector;
2083 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2084 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2085 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2087 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2088 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2089 SIVAL(pdata,l1_cUnit,dsize);
2090 SIVAL(pdata,l1_cUnitAvail,dfree);
2091 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2095 case SMB_INFO_VOLUME:
2096 /* Return volume name */
2098 * Add volume serial number - hash of a combination of
2099 * the called hostname and the service name.
2101 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2103 * Win2k3 and previous mess this up by sending a name length
2104 * one byte short. I believe only older clients (OS/2 Win9x) use
2105 * this call so try fixing this by adding a terminating null to
2106 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2108 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2109 SCVAL(pdata,l2_vol_cch,len);
2110 data_len = l2_vol_szVolLabel + len;
2111 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2112 (unsigned)st.st_ctime, len, vname));
2115 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2116 case SMB_FS_ATTRIBUTE_INFORMATION:
2119 #if defined(HAVE_SYS_QUOTAS)
2120 quota_flag = FILE_VOLUME_QUOTAS;
2123 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2124 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2125 quota_flag); /* FS ATTRIBUTES */
2127 SIVAL(pdata,4,255); /* Max filename component length */
2128 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2129 and will think we can't do long filenames */
2130 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2132 data_len = 12 + len;
2135 case SMB_QUERY_FS_LABEL_INFO:
2136 case SMB_FS_LABEL_INFORMATION:
2137 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2142 case SMB_QUERY_FS_VOLUME_INFO:
2143 case SMB_FS_VOLUME_INFORMATION:
2146 * Add volume serial number - hash of a combination of
2147 * the called hostname and the service name.
2149 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2150 (str_checksum(get_local_machine_name())<<16));
2152 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2153 SIVAL(pdata,12,len);
2155 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2156 (int)strlen(vname),vname, lp_servicename(snum)));
2159 case SMB_QUERY_FS_SIZE_INFO:
2160 case SMB_FS_SIZE_INFORMATION:
2162 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2164 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2165 return(UNIXERROR(ERRHRD,ERRgeneral));
2167 block_size = lp_block_size(snum);
2168 if (bsize < block_size) {
2169 SMB_BIG_UINT factor = block_size/bsize;
2174 if (bsize > block_size) {
2175 SMB_BIG_UINT factor = bsize/block_size;
2180 bytes_per_sector = 512;
2181 sectors_per_unit = bsize/bytes_per_sector;
2182 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2183 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2184 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2185 SBIG_UINT(pdata,0,dsize);
2186 SBIG_UINT(pdata,8,dfree);
2187 SIVAL(pdata,16,sectors_per_unit);
2188 SIVAL(pdata,20,bytes_per_sector);
2192 case SMB_FS_FULL_SIZE_INFORMATION:
2194 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2196 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2197 return(UNIXERROR(ERRHRD,ERRgeneral));
2199 block_size = lp_block_size(snum);
2200 if (bsize < block_size) {
2201 SMB_BIG_UINT factor = block_size/bsize;
2206 if (bsize > block_size) {
2207 SMB_BIG_UINT factor = bsize/block_size;
2212 bytes_per_sector = 512;
2213 sectors_per_unit = bsize/bytes_per_sector;
2214 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2215 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2216 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2217 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2218 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2219 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2220 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2221 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2225 case SMB_QUERY_FS_DEVICE_INFO:
2226 case SMB_FS_DEVICE_INFORMATION:
2228 SIVAL(pdata,0,0); /* dev type */
2229 SIVAL(pdata,4,0); /* characteristics */
2232 #ifdef HAVE_SYS_QUOTAS
2233 case SMB_FS_QUOTA_INFORMATION:
2235 * what we have to send --metze:
2237 * Unknown1: 24 NULL bytes
2238 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2239 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2240 * Quota Flags: 2 byte :
2241 * Unknown3: 6 NULL bytes
2245 * details for Quota Flags:
2247 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2248 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2249 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2250 * 0x0001 Enable Quotas: enable quota for this fs
2254 /* we need to fake up a fsp here,
2255 * because its not send in this call
2258 SMB_NTQUOTA_STRUCT quotas;
2261 ZERO_STRUCT(quotas);
2268 if (current_user.uid != 0) {
2269 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2270 lp_servicename(SNUM(conn)),conn->user));
2271 return ERROR_DOS(ERRDOS,ERRnoaccess);
2274 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2275 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2276 return ERROR_DOS(ERRSRV,ERRerror);
2281 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2283 /* Unknown1 24 NULL bytes*/
2284 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2285 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2286 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2288 /* Default Soft Quota 8 bytes */
2289 SBIG_UINT(pdata,24,quotas.softlim);
2291 /* Default Hard Quota 8 bytes */
2292 SBIG_UINT(pdata,32,quotas.hardlim);
2294 /* Quota flag 2 bytes */
2295 SSVAL(pdata,40,quotas.qflags);
2297 /* Unknown3 6 NULL bytes */
2303 #endif /* HAVE_SYS_QUOTAS */
2304 case SMB_FS_OBJECTID_INFORMATION:
2309 * Query the version and capabilities of the CIFS UNIX extensions
2313 case SMB_QUERY_CIFS_UNIX_INFO:
2314 if (!lp_unix_extensions())
2315 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2317 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2318 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2319 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2322 case SMB_MAC_QUERY_FS_INFO:
2324 * Thursby MAC extension... ONLY on NTFS filesystems
2325 * once we do streams then we don't need this
2327 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2329 SIVAL(pdata,84,0x100); /* Don't support mac... */
2334 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2338 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2340 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2345 #ifdef HAVE_SYS_QUOTAS
2346 /****************************************************************************
2347 Reply to a TRANS2_SETFSINFO (set filesystem info).
2348 ****************************************************************************/
2350 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2351 char **pparams, int total_params, char **ppdata, int total_data,
2352 unsigned int max_data_bytes)
2354 char *pdata = *ppdata;
2355 char *params = *pparams;
2356 files_struct *fsp = NULL;
2359 SMB_NTQUOTA_STRUCT quotas;
2361 ZERO_STRUCT(quotas);
2363 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2366 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2367 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2368 lp_servicename(SNUM(conn)),conn->user));
2369 return ERROR_DOS(ERRSRV,ERRaccess);
2373 if (total_params < 4) {
2374 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2376 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2379 fsp = file_fsp(params,0);
2381 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2382 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2383 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2386 info_level = SVAL(params,2);
2388 switch(info_level) {
2389 case SMB_FS_QUOTA_INFORMATION:
2390 /* note: normaly there're 48 bytes,
2391 * but we didn't use the last 6 bytes for now
2394 if (total_data < 42) {
2395 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2397 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2400 /* unknown_1 24 NULL bytes in pdata*/
2402 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2403 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2404 #ifdef LARGE_SMB_OFF_T
2405 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2406 #else /* LARGE_SMB_OFF_T */
2407 if ((IVAL(pdata,28) != 0)&&
2408 ((quotas.softlim != 0xFFFFFFFF)||
2409 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2410 /* more than 32 bits? */
2411 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2413 #endif /* LARGE_SMB_OFF_T */
2415 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2416 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2417 #ifdef LARGE_SMB_OFF_T
2418 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2419 #else /* LARGE_SMB_OFF_T */
2420 if ((IVAL(pdata,36) != 0)&&
2421 ((quotas.hardlim != 0xFFFFFFFF)||
2422 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2423 /* more than 32 bits? */
2424 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2426 #endif /* LARGE_SMB_OFF_T */
2428 /* quota_flags 2 bytes **/
2429 quotas.qflags = SVAL(pdata,40);
2431 /* unknown_2 6 NULL bytes follow*/
2433 /* now set the quotas */
2434 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2435 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2436 return ERROR_DOS(ERRSRV,ERRerror);
2441 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2443 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2448 * sending this reply works fine,
2449 * but I'm not sure it's the same
2450 * like windows do...
2453 outsize = set_message(outbuf,10,0,True);
2457 #endif /* HAVE_SYS_QUOTAS */
2459 /****************************************************************************
2460 Utility function to set bad path error.
2461 ****************************************************************************/
2463 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2465 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2466 err, (int)bad_path ));
2470 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2472 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2475 return UNIXERROR(def_class,def_code);
2478 #if defined(HAVE_POSIX_ACLS)
2479 /****************************************************************************
2480 Utility function to count the number of entries in a POSIX acl.
2481 ****************************************************************************/
2483 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2485 unsigned int ace_count = 0;
2486 int entry_id = SMB_ACL_FIRST_ENTRY;
2487 SMB_ACL_ENTRY_T entry;
2489 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2491 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2492 entry_id = SMB_ACL_NEXT_ENTRY;
2499 /****************************************************************************
2500 Utility function to marshall a POSIX acl into wire format.
2501 ****************************************************************************/
2503 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2505 int entry_id = SMB_ACL_FIRST_ENTRY;
2506 SMB_ACL_ENTRY_T entry;
2508 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2509 SMB_ACL_TAG_T tagtype;
2510 SMB_ACL_PERMSET_T permset;
2511 unsigned char perms = 0;
2512 unsigned int own_grp;
2515 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2516 entry_id = SMB_ACL_NEXT_ENTRY;
2519 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2520 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2524 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2525 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2529 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2530 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2531 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2533 SCVAL(pdata,1,perms);
2536 case SMB_ACL_USER_OBJ:
2537 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2538 own_grp = (unsigned int)pst->st_uid;
2539 SIVAL(pdata,2,own_grp);
2544 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2546 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2548 own_grp = (unsigned int)*puid;
2549 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2550 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2551 SIVAL(pdata,2,own_grp);
2555 case SMB_ACL_GROUP_OBJ:
2556 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2557 own_grp = (unsigned int)pst->st_gid;
2558 SIVAL(pdata,2,own_grp);
2563 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2565 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2567 own_grp = (unsigned int)*pgid;
2568 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2569 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2570 SIVAL(pdata,2,own_grp);
2575 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2576 SIVAL(pdata,2,0xFFFFFFFF);
2577 SIVAL(pdata,6,0xFFFFFFFF);
2580 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2581 SIVAL(pdata,2,0xFFFFFFFF);
2582 SIVAL(pdata,6,0xFFFFFFFF);
2585 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2588 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2595 /****************************************************************************
2596 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2597 file name or file id).
2598 ****************************************************************************/
2600 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2601 char **pparams, int total_params, char **ppdata, int total_data,
2602 unsigned int max_data_bytes)
2604 char *params = *pparams;
2605 char *pdata = *ppdata;
2606 uint16 tran_call = SVAL(inbuf, smb_setup0);
2609 SMB_OFF_T file_size=0;
2610 SMB_BIG_UINT allocation_size=0;
2611 unsigned int data_size = 0;
2612 unsigned int param_size = 2;
2613 SMB_STRUCT_STAT sbuf;
2614 pstring fname, dos_fname;
2619 BOOL bad_path = False;
2620 BOOL delete_pending = False;
2623 files_struct *fsp = NULL;
2624 TALLOC_CTX *ea_ctx = NULL;
2625 struct ea_list *ea_list = NULL;
2626 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2629 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2633 if (tran_call == TRANSACT2_QFILEINFO) {
2634 if (total_params < 4) {
2635 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2638 fsp = file_fsp(params,0);
2639 info_level = SVAL(params,2);
2641 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2643 if(fsp && (fsp->fake_file_handle)) {
2645 * This is actually for the QUOTA_FAKE_FILE --metze
2648 pstrcpy(fname, fsp->fsp_name);
2649 /* We know this name is ok, it's already passed the checks. */
2651 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2653 * This is actually a QFILEINFO on a directory
2654 * handle (returned from an NT SMB). NT5.0 seems
2655 * to do this call. JRA.
2657 /* We know this name is ok, it's already passed the checks. */
2658 pstrcpy(fname, fsp->fsp_name);
2660 if (INFO_LEVEL_IS_UNIX(info_level)) {
2661 /* Always do lstat for UNIX calls. */
2662 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2663 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2664 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2666 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2667 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2668 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2671 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2674 * Original code - this is an open file.
2676 CHECK_FSP(fsp,conn);
2678 pstrcpy(fname, fsp->fsp_name);
2679 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2680 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2681 return(UNIXERROR(ERRDOS,ERRbadfid));
2683 pos = fsp->position_information;
2684 delete_pending = fsp->delete_on_close;
2685 desired_access = fsp->desired_access;
2688 NTSTATUS status = NT_STATUS_OK;
2691 if (total_params < 6) {
2692 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2695 info_level = SVAL(params,0);
2697 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2699 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2700 if (!NT_STATUS_IS_OK(status)) {
2701 return ERROR_NT(status);
2704 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2706 unix_convert(fname,conn,0,&bad_path,&sbuf);
2708 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2710 if (!check_name(fname,conn)) {
2711 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2712 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2715 if (INFO_LEVEL_IS_UNIX(info_level)) {
2716 /* Always do lstat for UNIX calls. */
2717 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2718 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2719 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2721 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2722 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2723 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2727 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2728 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2730 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2731 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2733 p = strrchr_m(fname,'/');
2739 mode = dos_mode(conn,fname,&sbuf);
2741 mode = FILE_ATTRIBUTE_NORMAL;
2743 fullpathname = fname;
2744 file_size = get_file_size(sbuf);
2745 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2747 /* This is necessary, as otherwise the desktop.ini file in
2748 * this folder is ignored */
2749 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2753 /* Pull any EA list from the data portion. */
2754 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2757 if (total_data < 4) {
2758 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2760 ea_size = IVAL(pdata,0);
2762 if (total_data > 0 && ea_size != total_data) {
2763 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2764 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2765 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2768 if (!lp_ea_support(SNUM(conn))) {
2769 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2772 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2773 return ERROR_NT(NT_STATUS_NO_MEMORY);
2776 /* Pull out the list of names. */
2777 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2779 talloc_destroy(ea_ctx);
2780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2784 params = SMB_REALLOC(*pparams,2);
2785 if (params == NULL) {
2786 talloc_destroy(ea_ctx);
2787 return ERROR_NT(NT_STATUS_NO_MEMORY);
2790 memset((char *)params,'\0',2);
2791 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2792 pdata = SMB_REALLOC(*ppdata, data_size);
2793 if ( pdata == NULL ) {
2794 talloc_destroy(ea_ctx);
2795 return ERROR_NT(NT_STATUS_NO_MEMORY);
2799 memset((char *)pdata,'\0',data_size);
2801 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2804 if (fsp->pending_modtime) {
2805 /* the pending modtime overrides the current modtime */
2806 sbuf.st_mtime = fsp->pending_modtime;
2809 /* Do we have this path open ? */
2810 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2811 if (fsp1 && fsp1->pending_modtime) {
2812 /* the pending modtime overrides the current modtime */
2813 sbuf.st_mtime = fsp1->pending_modtime;
2817 if (lp_dos_filetime_resolution(SNUM(conn))) {
2819 sbuf.st_atime &= ~1;
2820 sbuf.st_ctime &= ~1;
2821 sbuf.st_mtime &= ~1;
2824 /* NT expects the name to be in an exact form of the *full*
2825 filename. See the trans2 torture test */
2826 if (strequal(base_name,".")) {
2827 pstrcpy(dos_fname, "\\");
2829 pstr_sprintf(dos_fname, "\\%s", fname);
2830 string_replace(dos_fname, '/', '\\');
2833 switch (info_level) {
2834 case SMB_INFO_STANDARD:
2835 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2837 put_dos_date2(pdata,l1_fdateCreation,c_time);
2838 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2839 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2840 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2841 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2842 SSVAL(pdata,l1_attrFile,mode);
2845 case SMB_INFO_QUERY_EA_SIZE:
2847 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2848 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2850 put_dos_date2(pdata,l1_fdateCreation,c_time);
2851 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2852 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2853 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2854 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2855 SSVAL(pdata,l1_attrFile,mode);
2856 SIVAL(pdata,l1_attrFile+2,ea_size);
2860 case SMB_INFO_IS_NAME_VALID:
2861 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2862 if (tran_call == TRANSACT2_QFILEINFO) {
2863 /* os/2 needs this ? really ?*/
2864 return ERROR_DOS(ERRDOS,ERRbadfunc);
2870 case SMB_INFO_QUERY_EAS_FROM_LIST:
2872 size_t total_ea_len = 0;
2873 struct ea_list *ea_file_list = NULL;
2875 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2877 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2878 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2880 if (!ea_list || (total_ea_len > data_size)) {
2881 talloc_destroy(ea_ctx);
2883 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
2887 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2888 talloc_destroy(ea_ctx);
2892 case SMB_INFO_QUERY_ALL_EAS:
2894 /* We have data_size bytes to put EA's into. */
2895 size_t total_ea_len = 0;
2897 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2899 ea_ctx = talloc_init("ea_ctx");
2901 return ERROR_NT(NT_STATUS_NO_MEMORY);
2904 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2905 if (!ea_list || (total_ea_len > data_size)) {
2906 talloc_destroy(ea_ctx);
2908 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
2912 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2913 talloc_destroy(ea_ctx);
2917 case SMB_FILE_BASIC_INFORMATION:
2918 case SMB_QUERY_FILE_BASIC_INFO:
2920 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2921 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2922 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2924 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2928 put_long_date(pdata,c_time);
2929 put_long_date(pdata+8,sbuf.st_atime);
2930 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2931 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2932 SIVAL(pdata,32,mode);
2934 DEBUG(5,("SMB_QFBI - "));
2936 time_t create_time = c_time;
2937 DEBUG(5,("create: %s ", ctime(&create_time)));
2939 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2940 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2941 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2942 DEBUG(5,("mode: %x\n", mode));
2946 case SMB_FILE_STANDARD_INFORMATION:
2947 case SMB_QUERY_FILE_STANDARD_INFO:
2949 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2951 SOFF_T(pdata,0,allocation_size);
2952 SOFF_T(pdata,8,file_size);
2953 if (delete_pending & sbuf.st_nlink)
2954 SIVAL(pdata,16,sbuf.st_nlink - 1);
2956 SIVAL(pdata,16,sbuf.st_nlink);
2958 SCVAL(pdata,21,(mode&aDIR)?1:0);
2961 case SMB_FILE_EA_INFORMATION:
2962 case SMB_QUERY_FILE_EA_INFO:
2964 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2965 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2967 SIVAL(pdata,0,ea_size);
2971 /* Get the 8.3 name - used if NT SMB was negotiated. */
2972 case SMB_QUERY_FILE_ALT_NAME_INFO:
2973 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2977 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2978 pstrcpy(short_name,base_name);
2979 /* Mangle if not already 8.3 */
2980 if(!mangle_is_8_3(short_name, True)) {
2981 mangle_map(short_name,True,True,SNUM(conn));
2983 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2984 data_size = 4 + len;
2989 case SMB_QUERY_FILE_NAME_INFO:
2991 this must be *exactly* right for ACLs on mapped drives to work
2993 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2994 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2995 data_size = 4 + len;
2999 case SMB_FILE_ALLOCATION_INFORMATION:
3000 case SMB_QUERY_FILE_ALLOCATION_INFO:
3001 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3003 SOFF_T(pdata,0,allocation_size);
3006 case SMB_FILE_END_OF_FILE_INFORMATION:
3007 case SMB_QUERY_FILE_END_OF_FILEINFO:
3008 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3010 SOFF_T(pdata,0,file_size);
3013 case SMB_QUERY_FILE_ALL_INFO:
3014 case SMB_FILE_ALL_INFORMATION:
3016 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3017 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3018 put_long_date(pdata,c_time);
3019 put_long_date(pdata+8,sbuf.st_atime);
3020 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3021 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3022 SIVAL(pdata,32,mode);
3024 SOFF_T(pdata,0,allocation_size);
3025 SOFF_T(pdata,8,file_size);
3026 if (delete_pending && sbuf.st_nlink)
3027 SIVAL(pdata,16,sbuf.st_nlink - 1);
3029 SIVAL(pdata,16,sbuf.st_nlink);
3030 SCVAL(pdata,20,delete_pending);
3031 SCVAL(pdata,21,(mode&aDIR)?1:0);
3033 SIVAL(pdata,0,ea_size);
3034 pdata += 4; /* EA info */
3035 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3038 data_size = PTR_DIFF(pdata,(*ppdata));
3041 case SMB_FILE_INTERNAL_INFORMATION:
3042 /* This should be an index number - looks like
3045 I think this causes us to fail the IFSKIT
3046 BasicFileInformationTest. -tpot */
3048 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3049 SIVAL(pdata,0,sbuf.st_dev);
3050 SIVAL(pdata,4,sbuf.st_ino);
3054 case SMB_FILE_ACCESS_INFORMATION:
3055 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3056 SIVAL(pdata,0,desired_access);
3060 case SMB_FILE_NAME_INFORMATION:
3061 /* Pathname with leading '\'. */
3064 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3065 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3066 SIVAL(pdata,0,byte_len);
3067 data_size = 4 + byte_len;
3071 case SMB_FILE_DISPOSITION_INFORMATION:
3072 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3074 SCVAL(pdata,0,delete_pending);
3077 case SMB_FILE_POSITION_INFORMATION:
3078 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3080 SOFF_T(pdata,0,pos);
3083 case SMB_FILE_MODE_INFORMATION:
3084 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3085 SIVAL(pdata,0,mode);
3089 case SMB_FILE_ALIGNMENT_INFORMATION:
3090 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3091 SIVAL(pdata,0,0); /* No alignment needed. */
3097 * NT4 server just returns "invalid query" to this - if we try to answer
3098 * it then NTws gets a BSOD! (tridge).
3099 * W2K seems to want this. JRA.
3101 case SMB_QUERY_FILE_STREAM_INFO:
3103 case SMB_FILE_STREAM_INFORMATION:
3104 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3108 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3109 SIVAL(pdata,0,0); /* ??? */
3110 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3111 SOFF_T(pdata,8,file_size);
3112 SIVAL(pdata,16,allocation_size);
3113 SIVAL(pdata,20,0); /* ??? */
3114 data_size = 24 + byte_len;
3118 case SMB_QUERY_COMPRESSION_INFO:
3119 case SMB_FILE_COMPRESSION_INFORMATION:
3120 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3121 SOFF_T(pdata,0,file_size);
3122 SIVAL(pdata,8,0); /* ??? */
3123 SIVAL(pdata,12,0); /* ??? */
3127 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3128 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3129 put_long_date(pdata,c_time);
3130 put_long_date(pdata+8,sbuf.st_atime);
3131 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3132 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3133 SIVAL(pdata,32,allocation_size);
3134 SOFF_T(pdata,40,file_size);
3135 SIVAL(pdata,48,mode);
3136 SIVAL(pdata,52,0); /* ??? */
3140 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3141 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3142 SIVAL(pdata,0,mode);
3148 * CIFS UNIX Extensions.
3151 case SMB_QUERY_FILE_UNIX_BASIC:
3153 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3154 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3156 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3159 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3162 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3163 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3164 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3167 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3171 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3175 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3178 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3182 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3186 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3189 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3193 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3196 data_size = PTR_DIFF(pdata,(*ppdata));
3200 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3202 for (i=0; i<100; i++)
3203 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3209 case SMB_QUERY_FILE_UNIX_LINK:
3213 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3215 if(!S_ISLNK(sbuf.st_mode))
3216 return(UNIXERROR(ERRSRV,ERRbadlink));
3218 return(UNIXERROR(ERRDOS,ERRbadlink));
3220 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3222 return(UNIXERROR(ERRDOS,ERRnoaccess));
3224 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3226 data_size = PTR_DIFF(pdata,(*ppdata));
3231 #if defined(HAVE_POSIX_ACLS)
3232 case SMB_QUERY_POSIX_ACL:
3234 SMB_ACL_T file_acl = NULL;
3235 SMB_ACL_T def_acl = NULL;
3236 uint16 num_file_acls = 0;
3237 uint16 num_def_acls = 0;
3239 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3240 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3242 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3245 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3246 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3248 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3251 if (S_ISDIR(sbuf.st_mode)) {
3252 if (fsp && fsp->is_directory) {
3253 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3255 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3257 def_acl = free_empty_sys_acl(conn, def_acl);
3260 num_file_acls = count_acl_entries(conn, file_acl);
3261 num_def_acls = count_acl_entries(conn, def_acl);
3263 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3264 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3266 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3267 SMB_POSIX_ACL_HEADER_SIZE) ));
3269 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3272 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3274 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3277 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3278 SSVAL(pdata,2,num_file_acls);
3279 SSVAL(pdata,4,num_def_acls);
3280 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3282 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3285 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3287 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3289 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3291 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3294 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3296 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3300 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3303 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3305 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3311 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3314 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3319 /****************************************************************************
3320 Deal with the internal needs of setting the delete on close flag. Note that
3321 as the tdb locking is recursive, it is safe to call this from within
3322 open_file_shared. JRA.
3323 ****************************************************************************/
3325 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3327 if (delete_on_close) {
3329 * Only allow delete on close for writable files.
3332 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3333 if (dosmode & aRONLY) {
3334 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3336 return NT_STATUS_CANNOT_DELETE;
3341 * Only allow delete on close for writable shares.
3344 if (!CAN_WRITE(fsp->conn)) {
3345 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3347 return NT_STATUS_ACCESS_DENIED;
3351 * Only allow delete on close for files/directories opened with delete intent.
3354 if (!(fsp->desired_access & DELETE_ACCESS)) {
3355 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3357 return NT_STATUS_ACCESS_DENIED;
3361 if(fsp->is_directory) {
3362 fsp->directory_delete_on_close = delete_on_close;
3363 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3364 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3366 fsp->delete_on_close = delete_on_close;
3367 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3368 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3371 return NT_STATUS_OK;
3374 /****************************************************************************
3375 Sets the delete on close flag over all share modes on this file.
3376 Modify the share mode entry for all files open
3377 on this device and inode to tell other smbds we have
3378 changed the delete on close flag. This will be noticed
3379 in the close code, the last closer will delete the file
3381 ****************************************************************************/
3383 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3385 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3386 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3388 if (fsp->is_directory || fsp->is_stat)
3389 return NT_STATUS_OK;
3391 if (lock_share_entry_fsp(fsp) == False)
3392 return NT_STATUS_ACCESS_DENIED;
3394 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3395 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3397 unlock_share_entry_fsp(fsp);
3398 return NT_STATUS_ACCESS_DENIED;
3401 unlock_share_entry_fsp(fsp);
3402 return NT_STATUS_OK;
3405 /****************************************************************************
3406 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3408 ****************************************************************************/
3410 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3412 BOOL bad_path_oldname = False;
3413 BOOL bad_path_newname = False;
3414 SMB_STRUCT_STAT sbuf1, sbuf2;
3415 pstring last_component_oldname;
3416 pstring last_component_newname;
3417 NTSTATUS status = NT_STATUS_OK;
3423 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3424 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3427 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3428 if (bad_path_oldname) {
3429 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3432 /* Quick check for "." and ".." */
3433 if (last_component_oldname[0] == '.') {
3434 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3435 return NT_STATUS_OBJECT_NAME_INVALID;
3439 /* source must already exist. */
3440 if (!VALID_STAT(sbuf1)) {
3441 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3444 if (!check_name(oldname,conn)) {
3445 return NT_STATUS_ACCESS_DENIED;
3448 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3449 if (bad_path_newname) {
3450 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3453 /* Quick check for "." and ".." */
3454 if (last_component_newname[0] == '.') {
3455 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3456 return NT_STATUS_OBJECT_NAME_INVALID;
3460 /* Disallow if newname already exists. */
3461 if (VALID_STAT(sbuf2)) {
3462 return NT_STATUS_OBJECT_NAME_COLLISION;
3465 if (!check_name(newname,conn)) {
3466 return NT_STATUS_ACCESS_DENIED;
3469 /* No links from a directory. */
3470 if (S_ISDIR(sbuf1.st_mode)) {
3471 return NT_STATUS_FILE_IS_A_DIRECTORY;
3474 /* Ensure this is within the share. */
3475 if (!reduce_name(conn, oldname) != 0)
3476 return NT_STATUS_ACCESS_DENIED;
3478 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3480 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3481 status = map_nt_error_from_unix(errno);
3482 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3483 nt_errstr(status), newname, oldname));
3489 /****************************************************************************
3490 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3491 ****************************************************************************/
3493 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3494 char **pparams, int total_params, char **ppdata, int total_data,
3495 unsigned int max_data_bytes)
3497 char *params = *pparams;
3498 char *pdata = *ppdata;
3499 uint16 tran_call = SVAL(inbuf, smb_setup0);
3504 SMB_STRUCT_STAT sbuf;
3507 BOOL bad_path = False;
3508 files_struct *fsp = NULL;
3509 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3510 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3511 mode_t unixmode = 0;
3512 NTSTATUS status = NT_STATUS_OK;
3515 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3519 if (tran_call == TRANSACT2_SETFILEINFO) {
3520 if (total_params < 4) {
3521 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3524 fsp = file_fsp(params,0);
3525 info_level = SVAL(params,2);
3527 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3529 * This is actually a SETFILEINFO on a directory
3530 * handle (returned from an NT SMB). NT5.0 seems
3531 * to do this call. JRA.
3533 pstrcpy(fname, fsp->fsp_name);
3534 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3535 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3536 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3538 } else if (fsp && fsp->print_file) {
3540 * Doing a DELETE_ON_CLOSE should cancel a print job.
3542 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3543 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3545 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3548 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3551 return (UNIXERROR(ERRDOS,ERRbadpath));
3554 * Original code - this is an open file.
3556 CHECK_FSP(fsp,conn);
3558 pstrcpy(fname, fsp->fsp_name);
3561 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3562 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3563 return(UNIXERROR(ERRDOS,ERRbadfid));
3568 if (total_params < 6) {
3569 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3572 info_level = SVAL(params,0);
3573 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3574 if (!NT_STATUS_IS_OK(status)) {
3575 return ERROR_NT(status);
3577 unix_convert(fname,conn,0,&bad_path,&sbuf);
3579 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3583 * For CIFS UNIX extensions the target name may not exist.
3586 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3587 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3588 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3591 if(!check_name(fname, conn)) {
3592 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3597 if (!CAN_WRITE(conn))
3598 return ERROR_DOS(ERRSRV,ERRaccess);
3600 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3601 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3603 if (VALID_STAT(sbuf))
3604 unixmode = sbuf.st_mode;
3606 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3607 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3609 /* Realloc the parameter size */
3610 params = SMB_REALLOC(*pparams,2);
3611 if(params == NULL) {
3612 return ERROR_NT(NT_STATUS_NO_MEMORY);
3618 if (fsp && fsp->pending_modtime) {
3619 /* the pending modtime overrides the current modtime */
3620 sbuf.st_mtime = fsp->pending_modtime;
3623 size = get_file_size(sbuf);
3624 tvs.modtime = sbuf.st_mtime;
3625 tvs.actime = sbuf.st_atime;
3626 dosmode = dos_mode(conn,fname,&sbuf);
3627 unixmode = sbuf.st_mode;
3629 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3630 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3632 switch (info_level) {
3633 case SMB_INFO_STANDARD:
3635 if (total_data < 12) {
3636 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3640 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3642 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3646 case SMB_INFO_SET_EA:
3648 struct ea_list *ea_list = NULL;
3649 TALLOC_CTX *ctx = NULL;
3651 if (total_data < 10) {
3652 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3655 if (IVAL(pdata,0) > total_data) {
3656 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3657 IVAL(pdata,0), (unsigned int)total_data));
3658 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3661 ctx = talloc_init("SMB_INFO_SET_EA");
3663 return ERROR_NT(NT_STATUS_NO_MEMORY);
3665 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3667 talloc_destroy(ctx);
3668 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3670 status = set_ea(conn, fsp, fname, ea_list);
3671 talloc_destroy(ctx);
3673 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) {
3674 return ERROR_NT(status);
3680 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3681 /* XXXX um, i don't think this is right.
3682 it's also not in the cifs6.txt spec.
3684 case SMB_INFO_QUERY_EAS_FROM_LIST:
3685 if (total_data < 28)
3686 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3688 tvs.actime = make_unix_date2(pdata+8);
3689 tvs.modtime = make_unix_date2(pdata+12);
3690 size = IVAL(pdata,16);
3691 dosmode = IVAL(pdata,24);
3694 /* XXXX nor this. not in cifs6.txt, either. */
3695 case SMB_INFO_QUERY_ALL_EAS:
3696 if (total_data < 28)
3697 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3699 tvs.actime = make_unix_date2(pdata+8);
3700 tvs.modtime = make_unix_date2(pdata+12);
3701 size = IVAL(pdata,16);
3702 dosmode = IVAL(pdata,24);
3706 case SMB_SET_FILE_BASIC_INFO:
3707 case SMB_FILE_BASIC_INFORMATION:
3709 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3711 time_t changed_time;
3713 if (total_data < 36) {
3714 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3717 /* Ignore create time at offset pdata. */
3720 tvs.actime = interpret_long_date(pdata+8);
3722 write_time = interpret_long_date(pdata+16);
3723 changed_time = interpret_long_date(pdata+24);
3725 tvs.modtime = MIN(write_time, changed_time);
3727 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3728 tvs.modtime = write_time;
3730 /* Prefer a defined time to an undefined one. */
3731 if (null_mtime(tvs.modtime)) {
3732 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3736 dosmode = IVAL(pdata,32);
3740 case SMB_FILE_ALLOCATION_INFORMATION:
3741 case SMB_SET_FILE_ALLOCATION_INFO:
3744 SMB_BIG_UINT allocation_size;
3746 if (total_data < 8) {
3747 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3750 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3751 #ifdef LARGE_SMB_OFF_T
3752 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3753 #else /* LARGE_SMB_OFF_T */
3754 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3755 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3756 #endif /* LARGE_SMB_OFF_T */
3757 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3758 fname, (double)allocation_size ));
3760 if (allocation_size) {
3761 allocation_size = smb_roundup(conn, allocation_size);
3764 if(allocation_size != get_file_size(sbuf)) {
3765 SMB_STRUCT_STAT new_sbuf;
3767 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3768 fname, (double)allocation_size ));
3771 files_struct *new_fsp = NULL;
3772 int access_mode = 0;
3775 if(global_oplock_break) {
3776 /* Queue this file modify as we are the process of an oplock break. */
3778 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3779 DEBUGADD(2,( "in oplock break state.\n"));
3781 push_oplock_pending_smb_message(inbuf, length);
3785 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3786 SET_OPEN_MODE(DOS_OPEN_RDWR),
3787 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3788 FILE_ATTRIBUTE_NORMAL,
3789 INTERNAL_OPEN_ONLY, &access_mode, &action);
3791 if (new_fsp == NULL)
3792 return(UNIXERROR(ERRDOS,ERRbadpath));
3793 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3794 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3795 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3796 new_fsp->fnum, strerror(errno)));
3799 close_file(new_fsp,True);
3801 ret = vfs_allocate_file_space(fsp, allocation_size);
3802 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3803 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3804 fsp->fnum, strerror(errno)));
3809 return ERROR_NT(NT_STATUS_DISK_FULL);
3811 /* Allocate can truncate size... */
3812 size = get_file_size(new_sbuf);
3818 case SMB_FILE_END_OF_FILE_INFORMATION:
3819 case SMB_SET_FILE_END_OF_FILE_INFO:
3821 if (total_data < 8) {
3822 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3825 size = IVAL(pdata,0);
3826 #ifdef LARGE_SMB_OFF_T
3827 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3828 #else /* LARGE_SMB_OFF_T */
3829 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3830 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3831 #endif /* LARGE_SMB_OFF_T */
3832 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3836 case SMB_FILE_DISPOSITION_INFORMATION:
3837 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3839 BOOL delete_on_close;
3841 if (total_data < 1) {
3842 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3845 delete_on_close = (CVAL(pdata,0) ? True : False);
3847 /* Just ignore this set on a path. */
3848 if (tran_call != TRANSACT2_SETFILEINFO)
3852 return(UNIXERROR(ERRDOS,ERRbadfid));
3854 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3856 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3857 return ERROR_NT(status);
3859 /* The set is across all open files on this dev/inode pair. */
3860 status =set_delete_on_close_over_all(fsp, delete_on_close);
3861 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3862 return ERROR_NT(status);
3867 case SMB_FILE_POSITION_INFORMATION:
3869 SMB_BIG_UINT position_information;
3871 if (total_data < 8) {
3872 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3875 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3876 #ifdef LARGE_SMB_OFF_T
3877 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3878 #else /* LARGE_SMB_OFF_T */
3879 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3880 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3881 #endif /* LARGE_SMB_OFF_T */
3882 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3883 fname, (double)position_information ));
3885 fsp->position_information = position_information;
3889 /* From tridge Samba4 :
3890 * MODE_INFORMATION in setfileinfo (I have no
3891 * idea what "mode information" on a file is - it takes a value of 0,
3892 * 2, 4 or 6. What could it be?).
3895 case SMB_FILE_MODE_INFORMATION:
3899 if (total_data < 4) {
3900 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3902 mode = IVAL(pdata,0);
3903 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3904 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3910 * CIFS UNIX extensions.
3913 case SMB_SET_FILE_UNIX_BASIC:
3915 uint32 raw_unixmode;
3917 if (total_data < 100) {
3918 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3921 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3922 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3923 size=IVAL(pdata,0); /* first 8 Bytes are size */
3924 #ifdef LARGE_SMB_OFF_T
3925 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3926 #else /* LARGE_SMB_OFF_T */
3927 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3928 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3929 #endif /* LARGE_SMB_OFF_T */
3931 pdata+=24; /* ctime & st_blocks are not changed */
3932 tvs.actime = interpret_long_date(pdata); /* access_time */
3933 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3935 set_owner = (uid_t)IVAL(pdata,0);
3937 set_grp = (gid_t)IVAL(pdata,0);
3939 raw_unixmode = IVAL(pdata,28);
3940 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3941 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3943 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3944 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3945 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3947 if (!VALID_STAT(sbuf)) {
3950 * The only valid use of this is to create character and block
3951 * devices, and named pipes. This is deprecated (IMHO) and
3952 * a new info level should be used for mknod. JRA.
3955 uint32 file_type = IVAL(pdata,0);
3956 #if defined(HAVE_MAKEDEV)
3957 uint32 dev_major = IVAL(pdata,4);
3958 uint32 dev_minor = IVAL(pdata,12);
3961 uid_t myuid = geteuid();
3962 gid_t mygid = getegid();
3963 SMB_DEV_T dev = (SMB_DEV_T)0;
3965 if (tran_call == TRANSACT2_SETFILEINFO)
3966 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3968 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
3969 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3972 #if defined(HAVE_MAKEDEV)
3973 dev = makedev(dev_major, dev_minor);
3976 /* We can only create as the owner/group we are. */
3978 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3979 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3980 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3981 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3983 switch (file_type) {
3984 #if defined(S_IFIFO)
3985 case UNIX_TYPE_FIFO:
3986 unixmode |= S_IFIFO;
3989 #if defined(S_IFSOCK)
3990 case UNIX_TYPE_SOCKET:
3991 unixmode |= S_IFSOCK;
3994 #if defined(S_IFCHR)
3995 case UNIX_TYPE_CHARDEV:
3996 unixmode |= S_IFCHR;
3999 #if defined(S_IFBLK)
4000 case UNIX_TYPE_BLKDEV:
4001 unixmode |= S_IFBLK;
4005 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4008 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4009 0%o for file %s\n", (double)dev, unixmode, fname ));
4011 /* Ok - do the mknod. */
4012 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4013 return(UNIXERROR(ERRDOS,ERRnoaccess));
4015 inherit_access_acl(conn, fname, unixmode);
4018 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4023 * Deal with the UNIX specific mode set.
4026 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4027 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4028 (unsigned int)unixmode, fname ));
4029 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4030 return(UNIXERROR(ERRDOS,ERRnoaccess));
4034 * Deal with the UNIX specific uid set.
4037 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4038 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4039 (unsigned int)set_owner, fname ));
4040 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4041 return(UNIXERROR(ERRDOS,ERRnoaccess));
4045 * Deal with the UNIX specific gid set.
4048 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4049 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4050 (unsigned int)set_owner, fname ));
4051 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4052 return(UNIXERROR(ERRDOS,ERRnoaccess));
4057 case SMB_SET_FILE_UNIX_LINK:
4059 pstring link_target;
4060 char *newname = fname;
4062 /* Set a symbolic link. */
4063 /* Don't allow this if follow links is false. */
4065 if (!lp_symlinks(SNUM(conn)))
4066 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4068 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4070 /* !widelinks forces the target path to be within the share. */
4071 /* This means we can interpret the target as a pathname. */
4072 if (!lp_widelinks(SNUM(conn))) {
4074 char *last_dirp = NULL;
4076 unix_format(link_target);
4077 if (*link_target == '/') {
4078 /* No absolute paths allowed. */
4079 return(UNIXERROR(ERRDOS,ERRnoaccess));
4081 pstrcpy(rel_name, newname);
4082 last_dirp = strrchr_m(rel_name, '/');
4084 last_dirp[1] = '\0';
4086 pstrcpy(rel_name, "./");
4088 pstrcat(rel_name, link_target);
4090 if (!check_name(rel_name, conn)) {
4091 return(UNIXERROR(ERRDOS,ERRnoaccess));
4095 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4096 fname, link_target ));
4098 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4099 return(UNIXERROR(ERRDOS,ERRnoaccess));
4101 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4105 case SMB_SET_FILE_UNIX_HLINK:
4108 char *newname = fname;
4110 /* Set a hard link. */
4111 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4112 if (!NT_STATUS_IS_OK(status)) {
4113 return ERROR_NT(status);
4116 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4119 status = hardlink_internals(conn, oldname, newname);
4120 if (!NT_STATUS_IS_OK(status)) {
4121 return ERROR_NT(status);
4125 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4129 case SMB_FILE_RENAME_INFORMATION:
4138 if (total_data < 12) {
4139 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4142 overwrite = (CVAL(pdata,0) ? True : False);
4143 root_fid = IVAL(pdata,4);
4144 len = IVAL(pdata,8);
4145 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4146 if (!NT_STATUS_IS_OK(status)) {
4147 return ERROR_NT(status);
4150 /* Check the new name has no '/' characters. */
4151 if (strchr_m(newname, '/'))
4152 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4154 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4156 /* Create the base directory. */
4157 pstrcpy(base_name, fname);
4158 p = strrchr_m(base_name, '/');
4161 /* Append the new name. */
4162 pstrcat(base_name, "/");
4163 pstrcat(base_name, newname);
4166 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4167 fsp->fnum, fsp->fsp_name, base_name ));
4168 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4170 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4172 status = rename_internals(conn, fname, base_name, 0, overwrite);
4174 if (!NT_STATUS_IS_OK(status)) {
4175 return ERROR_NT(status);
4177 process_pending_change_notify_queue((time_t)0);
4179 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4183 #if defined(HAVE_POSIX_ACLS)
4184 case SMB_SET_POSIX_ACL:
4186 uint16 posix_acl_version;
4187 uint16 num_file_acls;
4188 uint16 num_def_acls;
4189 BOOL valid_file_acls = True;
4190 BOOL valid_def_acls = True;
4192 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4193 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4195 posix_acl_version = SVAL(pdata,0);
4196 num_file_acls = SVAL(pdata,2);
4197 num_def_acls = SVAL(pdata,4);
4199 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4200 valid_file_acls = False;
4204 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4205 valid_def_acls = False;
4209 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4210 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4213 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4214 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4215 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4218 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4219 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4220 return(UNIXERROR(ERRDOS,ERRnoaccess));
4223 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4224 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4225 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4226 return(UNIXERROR(ERRDOS,ERRnoaccess));
4230 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4236 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4239 /* get some defaults (no modifications) if any info is zero or -1. */
4240 if (null_mtime(tvs.actime)) {
4241 tvs.actime = sbuf.st_atime;
4244 if (null_mtime(tvs.modtime)) {
4245 tvs.modtime = sbuf.st_mtime;
4248 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4249 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4250 DEBUG(6,("size: %.0f ", (double)size));
4253 if (S_ISDIR(sbuf.st_mode))
4259 DEBUG(6,("dosmode: %x\n" , dosmode));
4261 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4262 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4263 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4264 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4267 * Only do this test if we are not explicitly
4268 * changing the size of a file.
4271 size = get_file_size(sbuf);
4275 * Try and set the times, size and mode of this file -
4276 * if they are different from the current values
4279 /* check the mode isn't different, before changing it */
4280 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4282 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4284 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4285 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4286 return(UNIXERROR(ERRDOS,ERRnoaccess));
4291 if (size != get_file_size(sbuf)) {
4295 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4296 fname, (double)size ));
4299 files_struct *new_fsp = NULL;
4300 int access_mode = 0;
4303 if(global_oplock_break) {
4304 /* Queue this file modify as we are the process of an oplock break. */
4306 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4307 DEBUGADD(2,( "in oplock break state.\n"));
4309 push_oplock_pending_smb_message(inbuf, length);
4313 new_fsp = open_file_shared(conn, fname, &sbuf,
4314 SET_OPEN_MODE(DOS_OPEN_RDWR),
4315 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4316 FILE_ATTRIBUTE_NORMAL,
4317 INTERNAL_OPEN_ONLY, &access_mode, &action);
4319 if (new_fsp == NULL)
4320 return(UNIXERROR(ERRDOS,ERRbadpath));
4321 ret = vfs_set_filelen(new_fsp, size);
4322 close_file(new_fsp,True);
4324 ret = vfs_set_filelen(fsp, size);
4328 return (UNIXERROR(ERRHRD,ERRdiskfull));
4332 * Finally the times.
4334 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4337 * This was a setfileinfo on an open file.
4338 * NT does this a lot. We also need to
4339 * set the time here, as it can be read by
4340 * FindFirst/FindNext and with the patch for bug #2045
4341 * in smbd/fileio.c it ensures that this timestamp is
4342 * kept sticky even after a write. We save the request
4343 * away and will set it on file close and after a write. JRA.
4346 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4347 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4348 fsp_set_pending_modtime(fsp, tvs.modtime);
4352 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4354 if(file_utime(conn, fname, &tvs)!=0) {
4355 return(UNIXERROR(ERRDOS,ERRnoaccess));
4360 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4365 /****************************************************************************
4366 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4367 ****************************************************************************/
4369 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4370 char **pparams, int total_params, char **ppdata, int total_data,
4371 unsigned int max_data_bytes)
4373 char *params = *pparams;
4376 SMB_STRUCT_STAT sbuf;
4377 BOOL bad_path = False;
4378 NTSTATUS status = NT_STATUS_OK;
4380 if (!CAN_WRITE(conn))
4381 return ERROR_DOS(ERRSRV,ERRaccess);
4383 if (total_params < 4) {
4384 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4387 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4388 if (!NT_STATUS_IS_OK(status)) {
4389 return ERROR_NT(status);
4392 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4394 unix_convert(directory,conn,0,&bad_path,&sbuf);
4396 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4398 if (check_name(directory,conn))
4399 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4402 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4403 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4406 /* Realloc the parameter and data sizes */
4407 params = SMB_REALLOC(*pparams,2);
4408 if(params == NULL) {
4409 return ERROR_NT(NT_STATUS_NO_MEMORY);
4415 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4420 /****************************************************************************
4421 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4422 We don't actually do this - we just send a null response.
4423 ****************************************************************************/
4425 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4426 char **pparams, int total_params, char **ppdata, int total_data,
4427 unsigned int max_data_bytes)
4429 static uint16 fnf_handle = 257;
4430 char *params = *pparams;
4433 if (total_params < 6) {
4434 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4437 info_level = SVAL(params,4);
4438 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4440 switch (info_level) {
4445 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4448 /* Realloc the parameter and data sizes */
4449 params = SMB_REALLOC(*pparams,6);
4450 if(params == NULL) {
4451 return ERROR_NT(NT_STATUS_NO_MEMORY);
4455 SSVAL(params,0,fnf_handle);
4456 SSVAL(params,2,0); /* No changes */
4457 SSVAL(params,4,0); /* No EA errors */
4464 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4469 /****************************************************************************
4470 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4471 changes). Currently this does nothing.
4472 ****************************************************************************/
4474 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4475 char **pparams, int total_params, char **ppdata, int total_data,
4476 unsigned int max_data_bytes)
4478 char *params = *pparams;
4480 DEBUG(3,("call_trans2findnotifynext\n"));
4482 /* Realloc the parameter and data sizes */
4483 params = SMB_REALLOC(*pparams,4);
4484 if(params == NULL) {
4485 return ERROR_NT(NT_STATUS_NO_MEMORY);
4489 SSVAL(params,0,0); /* No changes */
4490 SSVAL(params,2,0); /* No EA errors */
4492 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4497 /****************************************************************************
4498 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4499 ****************************************************************************/
4501 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4502 char **pparams, int total_params, char **ppdata, int total_data,
4503 unsigned int max_data_bytes)
4505 char *params = *pparams;
4508 int max_referral_level;
4510 DEBUG(10,("call_trans2getdfsreferral\n"));
4512 if (total_params < 2) {
4513 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4516 max_referral_level = SVAL(params,0);
4518 if(!lp_host_msdfs())
4519 return ERROR_DOS(ERRDOS,ERRbadfunc);
4521 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4522 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4523 return UNIXERROR(ERRDOS,ERRbadfile);
4525 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4526 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4531 #define LMCAT_SPL 0x53
4532 #define LMFUNC_GETJOBID 0x60
4534 /****************************************************************************
4535 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4536 ****************************************************************************/
4538 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4539 char **pparams, int total_params, char **ppdata, int total_data,
4540 unsigned int max_data_bytes)
4542 char *pdata = *ppdata;
4543 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4545 /* check for an invalid fid before proceeding */
4548 return(ERROR_DOS(ERRDOS,ERRbadfid));
4550 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4551 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4552 pdata = SMB_REALLOC(*ppdata, 32);
4554 return ERROR_NT(NT_STATUS_NO_MEMORY);
4558 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4559 CAN ACCEPT THIS IN UNICODE. JRA. */
4561 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4562 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4563 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4564 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4567 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4568 return ERROR_DOS(ERRSRV,ERRerror);
4572 /****************************************************************************
4573 Reply to a SMBfindclose (stop trans2 directory search).
4574 ****************************************************************************/
4576 int reply_findclose(connection_struct *conn,
4577 char *inbuf,char *outbuf,int length,int bufsize)
4580 int dptr_num=SVALS(inbuf,smb_vwv0);
4581 START_PROFILE(SMBfindclose);
4583 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4585 dptr_close(&dptr_num);
4587 outsize = set_message(outbuf,0,0,True);
4589 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4591 END_PROFILE(SMBfindclose);
4595 /****************************************************************************
4596 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4597 ****************************************************************************/
4599 int reply_findnclose(connection_struct *conn,
4600 char *inbuf,char *outbuf,int length,int bufsize)
4604 START_PROFILE(SMBfindnclose);
4606 dptr_num = SVAL(inbuf,smb_vwv0);
4608 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4610 /* We never give out valid handles for a
4611 findnotifyfirst - so any dptr_num is ok here.
4614 outsize = set_message(outbuf,0,0,True);
4616 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4618 END_PROFILE(SMBfindnclose);
4622 /****************************************************************************
4623 Reply to a SMBtranss2 - just ignore it!
4624 ****************************************************************************/
4626 int reply_transs2(connection_struct *conn,
4627 char *inbuf,char *outbuf,int length,int bufsize)
4629 START_PROFILE(SMBtranss2);
4630 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4631 END_PROFILE(SMBtranss2);
4635 /****************************************************************************
4636 Reply to a SMBtrans2.
4637 ****************************************************************************/
4639 int reply_trans2(connection_struct *conn,
4640 char *inbuf,char *outbuf,int length,int bufsize)
4643 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4644 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4645 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4647 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4648 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4649 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4650 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4651 int32 timeout = IVALS(inbuf,smb_timeout);
4653 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4654 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4655 char *params = NULL, *data = NULL;
4656 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4657 START_PROFILE(SMBtrans2);
4659 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4660 /* Queue this open message as we are the process of an
4663 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4664 DEBUGADD(2,( "in oplock break state.\n"));
4666 push_oplock_pending_smb_message(inbuf, length);
4667 END_PROFILE(SMBtrans2);
4671 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4672 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4673 END_PROFILE(SMBtrans2);
4674 return ERROR_DOS(ERRSRV,ERRaccess);
4677 outsize = set_message(outbuf,0,0,True);
4679 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4680 is so as a sanity check */
4683 * Need to have rc=0 for ioctl to get job id for OS/2.
4684 * Network printing will fail if function is not successful.
4685 * Similar function in reply.c will be used if protocol
4686 * is LANMAN1.0 instead of LM1.2X002.
4687 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4688 * outbuf doesn't have to be set(only job id is used).
4690 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4691 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4692 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4693 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4695 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4696 DEBUG(2,("Transaction is %d\n",tran_call));
4697 END_PROFILE(SMBtrans2);
4698 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4702 /* Allocate the space for the maximum needed parameters and data */
4703 if (total_params > 0)
4704 params = (char *)SMB_MALLOC(total_params);
4706 data = (char *)SMB_MALLOC(total_data);
4708 if ((total_params && !params) || (total_data && !data)) {
4709 DEBUG(2,("Out of memory in reply_trans2\n"));
4712 END_PROFILE(SMBtrans2);
4713 return ERROR_NT(NT_STATUS_NO_MEMORY);
4716 /* Copy the param and data bytes sent with this request into
4717 the params buffer */
4718 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4719 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4721 if (num_params > total_params || num_data > total_data)
4722 exit_server("invalid params in reply_trans2");
4725 unsigned int psoff = SVAL(inbuf, smb_psoff);
4726 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4728 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4729 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4731 memcpy( params, smb_base(inbuf) + psoff, num_params);
4734 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4735 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4737 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4738 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4740 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4743 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4745 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4746 /* We need to send an interim response then receive the rest
4747 of the parameter/data bytes */
4748 outsize = set_message(outbuf,0,0,True);
4749 srv_signing_trans_stop();
4750 if (!send_smb(smbd_server_fd(),outbuf))
4751 exit_server("reply_trans2: send_smb failed.");
4753 while (num_data_sofar < total_data ||
4754 num_params_sofar < total_params) {
4756 unsigned int param_disp;
4757 unsigned int param_off;
4758 unsigned int data_disp;
4759 unsigned int data_off;
4761 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4764 * The sequence number for the trans reply is always
4765 * based on the last secondary received.
4768 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4771 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4772 outsize = set_message(outbuf,0,0,True);
4774 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4776 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4777 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4781 /* Revise total_params and total_data in case
4782 they have changed downwards */
4783 if (SVAL(inbuf, smb_tpscnt) < total_params)
4784 total_params = SVAL(inbuf, smb_tpscnt);
4785 if (SVAL(inbuf, smb_tdscnt) < total_data)
4786 total_data = SVAL(inbuf, smb_tdscnt);
4788 num_params = SVAL(inbuf,smb_spscnt);
4789 param_off = SVAL(inbuf, smb_spsoff);
4790 param_disp = SVAL(inbuf, smb_spsdisp);
4791 num_params_sofar += num_params;
4793 num_data = SVAL(inbuf, smb_sdscnt);
4794 data_off = SVAL(inbuf, smb_sdsoff);
4795 data_disp = SVAL(inbuf, smb_sdsdisp);
4796 num_data_sofar += num_data;
4798 if (num_params_sofar > total_params || num_data_sofar > total_data)
4802 if (param_disp + num_params > total_params)
4804 if ((param_disp + num_params < param_disp) ||
4805 (param_disp + num_params < num_params))
4807 if (param_disp > total_params)
4809 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4810 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4812 if (params + param_disp < params)
4815 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4818 if (data_disp + num_data > total_data)
4820 if ((data_disp + num_data < data_disp) ||
4821 (data_disp + num_data < num_data))
4823 if (data_disp > total_data)
4825 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4826 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4828 if (data + data_disp < data)
4831 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4836 if (Protocol >= PROTOCOL_NT1) {
4837 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4840 /* Now we must call the relevant TRANS2 function */
4842 case TRANSACT2_OPEN:
4843 START_PROFILE_NESTED(Trans2_open);
4844 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4845 ¶ms, total_params, &data, total_data, max_data_bytes);
4846 END_PROFILE_NESTED(Trans2_open);
4849 case TRANSACT2_FINDFIRST:
4850 START_PROFILE_NESTED(Trans2_findfirst);
4851 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4852 ¶ms, total_params, &data, total_data, max_data_bytes);
4853 END_PROFILE_NESTED(Trans2_findfirst);
4856 case TRANSACT2_FINDNEXT:
4857 START_PROFILE_NESTED(Trans2_findnext);
4858 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4859 ¶ms, total_params, &data, total_data, max_data_bytes);
4860 END_PROFILE_NESTED(Trans2_findnext);
4863 case TRANSACT2_QFSINFO:
4864 START_PROFILE_NESTED(Trans2_qfsinfo);
4865 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4866 ¶ms, total_params, &data, total_data, max_data_bytes);
4867 END_PROFILE_NESTED(Trans2_qfsinfo);
4870 #ifdef HAVE_SYS_QUOTAS
4871 case TRANSACT2_SETFSINFO:
4872 START_PROFILE_NESTED(Trans2_setfsinfo);
4873 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4874 ¶ms, total_params, &data, total_data, max_data_bytes);
4875 END_PROFILE_NESTED(Trans2_setfsinfo);
4878 case TRANSACT2_QPATHINFO:
4879 case TRANSACT2_QFILEINFO:
4880 START_PROFILE_NESTED(Trans2_qpathinfo);
4881 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4882 ¶ms, total_params, &data, total_data, max_data_bytes);
4883 END_PROFILE_NESTED(Trans2_qpathinfo);
4885 case TRANSACT2_SETPATHINFO:
4886 case TRANSACT2_SETFILEINFO:
4887 START_PROFILE_NESTED(Trans2_setpathinfo);
4888 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4889 ¶ms, total_params, &data, total_data, max_data_bytes);
4890 END_PROFILE_NESTED(Trans2_setpathinfo);
4893 case TRANSACT2_FINDNOTIFYFIRST:
4894 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4895 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4896 ¶ms, total_params, &data, total_data, max_data_bytes);
4897 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4900 case TRANSACT2_FINDNOTIFYNEXT:
4901 START_PROFILE_NESTED(Trans2_findnotifynext);
4902 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4903 ¶ms, total_params, &data, total_data, max_data_bytes);
4904 END_PROFILE_NESTED(Trans2_findnotifynext);
4906 case TRANSACT2_MKDIR:
4907 START_PROFILE_NESTED(Trans2_mkdir);
4908 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4909 ¶ms, total_params, &data, total_data, max_data_bytes);
4910 END_PROFILE_NESTED(Trans2_mkdir);
4913 case TRANSACT2_GET_DFS_REFERRAL:
4914 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4915 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4916 ¶ms, total_params, &data, total_data, max_data_bytes);
4917 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4919 case TRANSACT2_IOCTL:
4920 START_PROFILE_NESTED(Trans2_ioctl);
4921 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4922 ¶ms, total_params, &data, total_data, max_data_bytes);
4923 END_PROFILE_NESTED(Trans2_ioctl);
4926 /* Error in request */
4927 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4930 END_PROFILE(SMBtrans2);
4931 srv_signing_trans_stop();
4932 return ERROR_DOS(ERRSRV,ERRerror);
4935 /* As we do not know how many data packets will need to be
4936 returned here the various call_trans2xxxx calls
4937 must send their own. Thus a call_trans2xxx routine only
4938 returns a value other than -1 when it wants to send
4942 srv_signing_trans_stop();
4946 END_PROFILE(SMBtrans2);
4947 return outsize; /* If a correct response was needed the
4948 call_trans2xxx calls have already sent
4949 it. If outsize != -1 then it is returning */
4953 srv_signing_trans_stop();
4956 END_PROFILE(SMBtrans2);
4957 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);