2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 static char *store_file_unix_basic(connection_struct *conn,
40 const SMB_STRUCT_STAT *psbuf);
42 static char *store_file_unix_basic_info2(connection_struct *conn,
45 const SMB_STRUCT_STAT *psbuf);
47 /********************************************************************
48 Roundup a value to the nearest allocation roundup size boundary.
49 Only do this for Windows clients.
50 ********************************************************************/
52 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
54 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
56 /* Only roundup for Windows clients. */
57 enum remote_arch_types ra_type = get_remote_arch();
58 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
59 val = SMB_ROUNDUP(val,rval);
64 /********************************************************************
65 Given a stat buffer return the allocated size on disk, taking into
67 ********************************************************************/
69 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
73 if(S_ISDIR(sbuf->st_mode)) {
77 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
78 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
83 if (fsp && fsp->initial_allocation_size)
84 ret = MAX(ret,fsp->initial_allocation_size);
86 return smb_roundup(conn, ret);
89 /****************************************************************************
90 Utility functions for dealing with extended attributes.
91 ****************************************************************************/
93 /****************************************************************************
94 Refuse to allow clients to overwrite our private xattrs.
95 ****************************************************************************/
97 static BOOL samba_private_attr_name(const char *unix_ea_name)
99 static const char *prohibited_ea_names[] = {
100 SAMBA_POSIX_INHERITANCE_EA_NAME,
101 SAMBA_XATTR_DOS_ATTRIB,
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
114 /****************************************************************************
115 Get one EA value. Fill in a struct ea_struct.
116 ****************************************************************************/
118 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
119 const char *fname, char *ea_name, struct ea_struct *pea)
121 /* Get the value of this xattr. Max size is 64k. */
122 size_t attr_size = 256;
128 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 if (fsp && fsp->fh->fd != -1) {
134 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
139 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
148 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
149 dump_data(10, (uint8 *)val, sizeret);
152 if (strnequal(ea_name, "user.", 5)) {
153 pea->name = &ea_name[5];
157 pea->value.data = (unsigned char *)val;
158 pea->value.length = (size_t)sizeret;
162 /****************************************************************************
163 Return a linked list of the total EA's. Plus the total size
164 ****************************************************************************/
166 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
167 const char *fname, size_t *pea_total_len)
169 /* Get a list of all xattrs. Max namesize is 64k. */
170 size_t ea_namelist_size = 1024;
175 struct ea_list *ea_list_head = NULL;
179 if (!lp_ea_support(SNUM(conn))) {
183 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
184 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
190 if (fsp && fsp->fh->fd != -1) {
191 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
196 if (sizeret == -1 && errno == ERANGE) {
197 ea_namelist_size *= 2;
206 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
209 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
210 struct ea_list *listp;
212 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
215 listp = TALLOC_P(mem_ctx, struct ea_list);
219 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
225 push_ascii_fstring(dos_ea_name, listp->ea.name);
226 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
227 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
228 (unsigned int)*pea_total_len, dos_ea_name,
229 (unsigned int)listp->ea.value.length ));
231 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
233 /* Add on 4 for total length. */
234 if (*pea_total_len) {
239 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
243 /****************************************************************************
244 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246 ****************************************************************************/
248 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
249 connection_struct *conn, struct ea_list *ea_list)
251 unsigned int ret_data_size = 4;
254 SMB_ASSERT(total_data_size >= 4);
256 if (!lp_ea_support(SNUM(conn))) {
261 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
264 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
265 dos_namelen = strlen(dos_ea_name);
266 if (dos_namelen > 255 || dos_namelen == 0) {
269 if (ea_list->ea.value.length > 65535) {
272 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
276 /* We know we have room. */
277 SCVAL(p,0,ea_list->ea.flags);
278 SCVAL(p,1,dos_namelen);
279 SSVAL(p,2,ea_list->ea.value.length);
280 fstrcpy(p+4, dos_ea_name);
281 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
283 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
284 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
287 ret_data_size = PTR_DIFF(p, pdata);
288 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
289 SIVAL(pdata,0,ret_data_size);
290 return ret_data_size;
293 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
295 size_t total_ea_len = 0;
296 TALLOC_CTX *mem_ctx = NULL;
298 if (!lp_ea_support(SNUM(conn))) {
301 mem_ctx = talloc_init("estimate_ea_size");
302 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
303 talloc_destroy(mem_ctx);
307 /****************************************************************************
308 Ensure the EA name is case insensitive by matching any existing EA name.
309 ****************************************************************************/
311 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
314 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
315 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
317 for (; ea_list; ea_list = ea_list->next) {
318 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
319 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
320 &unix_ea_name[5], ea_list->ea.name));
321 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
325 talloc_destroy(mem_ctx);
328 /****************************************************************************
329 Set or delete an extended attribute.
330 ****************************************************************************/
332 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
334 if (!lp_ea_support(SNUM(conn))) {
335 return NT_STATUS_EAS_NOT_SUPPORTED;
338 for (;ea_list; ea_list = ea_list->next) {
340 fstring unix_ea_name;
342 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
343 fstrcat(unix_ea_name, ea_list->ea.name);
345 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
347 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
349 if (samba_private_attr_name(unix_ea_name)) {
350 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
351 return NT_STATUS_ACCESS_DENIED;
354 if (ea_list->ea.value.length == 0) {
355 /* Remove the attribute. */
356 if (fsp && (fsp->fh->fd != -1)) {
357 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
358 unix_ea_name, fsp->fsp_name));
359 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
362 unix_ea_name, fname));
363 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 /* Removing a non existent attribute always succeeds. */
367 if (ret == -1 && errno == ENOATTR) {
368 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
374 if (fsp && (fsp->fh->fd != -1)) {
375 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
376 unix_ea_name, fsp->fsp_name));
377 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
378 ea_list->ea.value.data, ea_list->ea.value.length, 0);
380 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
381 unix_ea_name, fname));
382 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
383 ea_list->ea.value.data, ea_list->ea.value.length, 0);
389 if (errno == ENOTSUP) {
390 return NT_STATUS_EAS_NOT_SUPPORTED;
393 return map_nt_error_from_unix(errno);
399 /****************************************************************************
400 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
401 ****************************************************************************/
403 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
405 struct ea_list *ea_list_head = NULL;
408 while (offset + 2 < data_size) {
409 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
410 unsigned int namelen = CVAL(pdata,offset);
412 offset++; /* Go past the namelen byte. */
414 /* integer wrap paranioa. */
415 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
416 (offset > data_size) || (namelen > data_size) ||
417 (offset + namelen >= data_size)) {
420 /* Ensure the name is null terminated. */
421 if (pdata[offset + namelen] != '\0') {
424 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
429 offset += (namelen + 1); /* Go past the name + terminating zero. */
430 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
431 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
437 /****************************************************************************
438 Read one EA list entry from the buffer.
439 ****************************************************************************/
441 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
443 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 unsigned int namelen;
455 eal->ea.flags = CVAL(pdata,0);
456 namelen = CVAL(pdata,1);
457 val_len = SVAL(pdata,2);
459 if (4 + namelen + 1 + val_len > data_size) {
463 /* Ensure the name is null terminated. */
464 if (pdata[namelen + 4] != '\0') {
467 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
472 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
473 if (!eal->ea.value.data) {
477 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
479 /* Ensure we're null terminated just in case we print the value. */
480 eal->ea.value.data[val_len] = '\0';
481 /* But don't count the null. */
482 eal->ea.value.length--;
485 *pbytes_used = 4 + namelen + 1 + val_len;
488 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
489 dump_data(10, eal->ea.value.data, eal->ea.value.length);
494 /****************************************************************************
495 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
496 ****************************************************************************/
498 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
500 struct ea_list *ea_list_head = NULL;
502 size_t bytes_used = 0;
504 while (offset < data_size) {
505 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
511 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
512 offset += bytes_used;
518 /****************************************************************************
519 Count the total EA size needed.
520 ****************************************************************************/
522 static size_t ea_list_size(struct ea_list *ealist)
525 struct ea_list *listp;
528 for (listp = ealist; listp; listp = listp->next) {
529 push_ascii_fstring(dos_ea_name, listp->ea.name);
530 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
532 /* Add on 4 for total length. */
540 /****************************************************************************
541 Return a union of EA's from a file list and a list of names.
542 The TALLOC context for the two lists *MUST* be identical as we steal
543 memory from one list to add to another. JRA.
544 ****************************************************************************/
546 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
548 struct ea_list *nlistp, *flistp;
550 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
551 for (flistp = file_list; flistp; flistp = flistp->next) {
552 if (strequal(nlistp->ea.name, flistp->ea.name)) {
558 /* Copy the data from this entry. */
559 nlistp->ea.flags = flistp->ea.flags;
560 nlistp->ea.value = flistp->ea.value;
563 nlistp->ea.flags = 0;
564 ZERO_STRUCT(nlistp->ea.value);
568 *total_ea_len = ea_list_size(name_list);
572 /****************************************************************************
573 Send the required number of replies back.
574 We assume all fields other than the data fields are
575 set correctly for the type of call.
576 HACK ! Always assumes smb_setup field is zero.
577 ****************************************************************************/
579 int send_trans2_replies(const char *inbuf,
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(inbuf,outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(inbuf, outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
738 static void send_trans2_replies_new(struct smb_request *req,
745 char *inbuf, *outbuf;
748 if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) {
749 reply_nterror(req, NT_STATUS_NO_MEMORY);
753 reply_post_legacy(req, send_trans2_replies(
754 inbuf, outbuf, bufsize,
760 /****************************************************************************
761 Reply to a TRANSACT2_OPEN.
762 ****************************************************************************/
764 static void call_trans2open(connection_struct *conn,
765 struct smb_request *req,
766 char **pparams, int total_params,
767 char **ppdata, int total_data,
768 unsigned int max_data_bytes)
770 char *params = *pparams;
771 char *pdata = *ppdata;
776 BOOL return_additional_info;
787 SMB_STRUCT_STAT sbuf;
790 struct ea_list *ea_list = NULL;
795 uint32 create_disposition;
796 uint32 create_options = 0;
799 * Ensure we have enough parameters to perform the operation.
802 if (total_params < 29) {
803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
807 flags = SVAL(params, 0);
808 deny_mode = SVAL(params, 2);
809 open_attr = SVAL(params,6);
810 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
811 if (oplock_request) {
812 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
816 return_additional_info = BITSETW(params,0);
817 open_sattr = SVAL(params, 4);
818 open_time = make_unix_date3(params+8);
820 open_ofun = SVAL(params,12);
821 open_size = IVAL(params,14);
825 reply_doserror(req, ERRSRV, ERRaccess);
829 srvstr_get_path(params, req->flags2, fname, pname,
830 sizeof(fname), total_params - 28, STR_TERMINATE,
832 if (!NT_STATUS_IS_OK(status)) {
833 reply_nterror(req, status);
837 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
838 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
839 (unsigned int)open_ofun, open_size));
841 /* XXXX we need to handle passed times, sattr and flags */
843 status = unix_convert(conn, fname, False, NULL, &sbuf);
844 if (!NT_STATUS_IS_OK(status)) {
845 reply_nterror(req, status);
849 status = check_name(conn, fname);
850 if (!NT_STATUS_IS_OK(status)) {
851 reply_nterror(req, status);
855 if (open_ofun == 0) {
856 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
860 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
865 reply_doserror(req, ERRDOS, ERRbadaccess);
869 /* Any data in this call is an EA list. */
870 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
871 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
875 if (total_data != 4) {
876 if (total_data < 10) {
877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
881 if (IVAL(pdata,0) > total_data) {
882 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
883 IVAL(pdata,0), (unsigned int)total_data));
884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
888 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
894 } else if (IVAL(pdata,0) != 4) {
895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
899 status = open_file_ntcreate(conn, req, fname, &sbuf,
908 if (!NT_STATUS_IS_OK(status)) {
909 if (open_was_deferred(req->mid)) {
910 /* We have re-scheduled this call. */
913 reply_nterror(req, status);
917 size = get_file_size(sbuf);
918 fattr = dos_mode(conn,fname,&sbuf);
919 mtime = sbuf.st_mtime;
922 close_file(fsp,ERROR_CLOSE);
923 reply_doserror(req, ERRDOS,ERRnoaccess);
927 /* Save the requested allocation size. */
928 /* Allocate space for the file if a size hint is supplied */
929 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
930 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
931 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
932 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
933 if (fsp->is_directory) {
934 close_file(fsp,ERROR_CLOSE);
935 /* Can't set allocation size on a directory. */
936 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
939 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
940 close_file(fsp,ERROR_CLOSE);
941 reply_nterror(req, NT_STATUS_DISK_FULL);
945 /* Adjust size here to return the right size in the reply.
946 Windows does it this way. */
947 size = fsp->initial_allocation_size;
949 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
953 if (ea_list && smb_action == FILE_WAS_CREATED) {
954 status = set_ea(conn, fsp, fname, ea_list);
955 if (!NT_STATUS_IS_OK(status)) {
956 close_file(fsp,ERROR_CLOSE);
957 reply_nterror(req, status);
962 /* Realloc the size of parameters and data we will return */
963 *pparams = (char *)SMB_REALLOC(*pparams, 30);
964 if(*pparams == NULL ) {
965 reply_nterror(req, NT_STATUS_NO_MEMORY);
970 SSVAL(params,0,fsp->fnum);
971 SSVAL(params,2,fattr);
972 srv_put_dos_date2(params,4, mtime);
973 SIVAL(params,8, (uint32)size);
974 SSVAL(params,12,deny_mode);
975 SSVAL(params,14,0); /* open_type - file or directory. */
976 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
978 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
979 smb_action |= EXTENDED_OPLOCK_GRANTED;
982 SSVAL(params,18,smb_action);
985 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
987 SIVAL(params,20,inode);
988 SSVAL(params,24,0); /* Padding. */
990 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
991 SIVAL(params, 26, ea_size);
993 SIVAL(params, 26, 0);
996 /* Send the required number of replies */
997 send_trans2_replies_new(req, params, 30, *ppdata, 0, max_data_bytes);
1000 /*********************************************************
1001 Routine to check if a given string matches exactly.
1002 as a special case a mask of "." does NOT match. That
1003 is required for correct wildcard semantics
1004 Case can be significant or not.
1005 **********************************************************/
1007 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
1009 if (mask[0] == '.' && mask[1] == 0)
1011 if (conn->case_sensitive)
1012 return strcmp(str,mask)==0;
1013 if (StrCaseCmp(str,mask) != 0) {
1016 if (dptr_has_wild(conn->dirptr)) {
1022 /****************************************************************************
1023 Return the filetype for UNIX extensions.
1024 ****************************************************************************/
1026 static uint32 unix_filetype(mode_t mode)
1029 return UNIX_TYPE_FILE;
1030 else if(S_ISDIR(mode))
1031 return UNIX_TYPE_DIR;
1033 else if(S_ISLNK(mode))
1034 return UNIX_TYPE_SYMLINK;
1037 else if(S_ISCHR(mode))
1038 return UNIX_TYPE_CHARDEV;
1041 else if(S_ISBLK(mode))
1042 return UNIX_TYPE_BLKDEV;
1045 else if(S_ISFIFO(mode))
1046 return UNIX_TYPE_FIFO;
1049 else if(S_ISSOCK(mode))
1050 return UNIX_TYPE_SOCKET;
1053 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1054 return UNIX_TYPE_UNKNOWN;
1057 /****************************************************************************
1058 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1059 ****************************************************************************/
1061 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1063 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1064 SMB_STRUCT_STAT *psbuf,
1066 enum perm_type ptype,
1071 if (perms == SMB_MODE_NO_CHANGE) {
1072 if (!VALID_STAT(*psbuf)) {
1073 return NT_STATUS_INVALID_PARAMETER;
1075 *ret_perms = psbuf->st_mode;
1076 return NT_STATUS_OK;
1080 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1081 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1082 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1083 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1084 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1085 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1086 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1087 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1088 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1090 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1093 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1096 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1101 /* Apply mode mask */
1102 ret &= lp_create_mask(SNUM(conn));
1103 /* Add in force bits */
1104 ret |= lp_force_create_mode(SNUM(conn));
1107 ret &= lp_dir_mask(SNUM(conn));
1108 /* Add in force bits */
1109 ret |= lp_force_dir_mode(SNUM(conn));
1111 case PERM_EXISTING_FILE:
1112 /* Apply mode mask */
1113 ret &= lp_security_mask(SNUM(conn));
1114 /* Add in force bits */
1115 ret |= lp_force_security_mode(SNUM(conn));
1117 case PERM_EXISTING_DIR:
1118 /* Apply mode mask */
1119 ret &= lp_dir_security_mask(SNUM(conn));
1120 /* Add in force bits */
1121 ret |= lp_force_dir_security_mode(SNUM(conn));
1126 return NT_STATUS_OK;
1129 /****************************************************************************
1130 Get a level dependent lanman2 dir entry.
1131 ****************************************************************************/
1133 static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
1134 char *path_mask,uint32 dirtype,int info_level,
1135 int requires_resume_key,
1136 BOOL dont_descend,char **ppdata,
1137 char *base_data, char *end_data,
1138 int space_remaining,
1139 BOOL *out_of_space, BOOL *got_exact_match,
1140 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1144 SMB_STRUCT_STAT sbuf;
1148 char *p, *q, *pdata = *ppdata;
1152 SMB_OFF_T file_size = 0;
1153 SMB_BIG_UINT allocation_size = 0;
1155 struct timespec mdate_ts, adate_ts, create_date_ts;
1156 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1158 char *last_entry_ptr;
1160 uint32 nt_extmode; /* Used for NT connections instead of mode */
1161 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1162 BOOL check_mangled_names = lp_manglednames(conn->params);
1165 *out_of_space = False;
1166 *got_exact_match = False;
1168 ZERO_STRUCT(mdate_ts);
1169 ZERO_STRUCT(adate_ts);
1170 ZERO_STRUCT(create_date_ts);
1175 p = strrchr_m(path_mask,'/');
1178 pstrcpy(mask,"*.*");
1182 pstrcpy(mask, path_mask);
1187 BOOL ms_dfs_link = False;
1189 /* Needed if we run out of space */
1190 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1191 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1194 * Due to bugs in NT client redirectors we are not using
1195 * resume keys any more - set them to zero.
1196 * Check out the related comments in findfirst/findnext.
1202 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1203 (long)conn->dirptr,curr_dirpos));
1210 * fname may get mangled, dname is never mangled.
1211 * Whenever we're accessing the filesystem we use
1212 * pathreal which is composed from dname.
1215 pstrcpy(fname,dname);
1217 /* This will mangle fname if it's an illegal name. */
1218 mangle_map(fname,False,True,conn->params);
1220 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1221 got_match = mask_match(fname, mask, conn->case_sensitive);
1224 if(!got_match && check_mangled_names &&
1225 !mangle_is_8_3(fname, False, conn->params)) {
1226 pstring mangled_name;
1229 * It turns out that NT matches wildcards against
1230 * both long *and* short names. This may explain some
1231 * of the wildcard wierdness from old DOS clients
1232 * that some people have been seeing.... JRA.
1235 pstrcpy(mangled_name, fname);
1237 /* Force the mangling into 8.3. */
1238 mangle_map( mangled_name, True, False, conn->params);
1239 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1240 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1245 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1246 if (dont_descend && !isdots) {
1250 pstrcpy(pathreal,conn->dirpath);
1252 pstrcat(pathreal,"/");
1254 pstrcat(pathreal,dname);
1256 if (INFO_LEVEL_IS_UNIX(info_level)) {
1257 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1258 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1259 pathreal,strerror(errno)));
1262 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1263 pstring link_target;
1265 /* Needed to show the msdfs symlinks as
1268 if(lp_host_msdfs() &&
1269 lp_msdfs_root(SNUM(conn)) &&
1270 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1271 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1274 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1278 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1279 pathreal,strerror(errno)));
1285 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1287 mode = dos_mode(conn,pathreal,&sbuf);
1290 if (!dir_check_ftype(conn,mode,dirtype)) {
1291 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1295 if (!(mode & aDIR)) {
1296 file_size = get_file_size(sbuf);
1298 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1300 mdate_ts = get_mtimespec(&sbuf);
1301 adate_ts = get_atimespec(&sbuf);
1302 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1304 if (lp_dos_filetime_resolution(SNUM(conn))) {
1305 dos_filetime_timespec(&create_date_ts);
1306 dos_filetime_timespec(&mdate_ts);
1307 dos_filetime_timespec(&adate_ts);
1310 create_date = convert_timespec_to_time_t(create_date_ts);
1311 mdate = convert_timespec_to_time_t(mdate_ts);
1312 adate = convert_timespec_to_time_t(adate_ts);
1314 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1318 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1325 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1327 switch (info_level) {
1328 case SMB_FIND_INFO_STANDARD:
1329 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1330 if(requires_resume_key) {
1334 srv_put_dos_date2(p,0,create_date);
1335 srv_put_dos_date2(p,4,adate);
1336 srv_put_dos_date2(p,8,mdate);
1337 SIVAL(p,12,(uint32)file_size);
1338 SIVAL(p,16,(uint32)allocation_size);
1342 p += align_string(pdata, p, 0);
1343 len = srvstr_push(base_data, flags2, p,
1344 fname, PTR_DIFF(end_data, p),
1346 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1348 SCVAL(nameptr, -1, len - 2);
1350 SCVAL(nameptr, -1, 0);
1354 SCVAL(nameptr, -1, len - 1);
1356 SCVAL(nameptr, -1, 0);
1362 case SMB_FIND_EA_SIZE:
1363 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1364 if(requires_resume_key) {
1368 srv_put_dos_date2(p,0,create_date);
1369 srv_put_dos_date2(p,4,adate);
1370 srv_put_dos_date2(p,8,mdate);
1371 SIVAL(p,12,(uint32)file_size);
1372 SIVAL(p,16,(uint32)allocation_size);
1375 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1376 SIVAL(p,22,ea_size); /* Extended attributes */
1380 len = srvstr_push(base_data, flags2,
1381 p, fname, PTR_DIFF(end_data, p),
1382 STR_TERMINATE | STR_NOALIGN);
1383 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1396 SCVAL(nameptr,0,len);
1398 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1401 case SMB_FIND_EA_LIST:
1403 struct ea_list *file_list = NULL;
1406 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1410 if(requires_resume_key) {
1414 srv_put_dos_date2(p,0,create_date);
1415 srv_put_dos_date2(p,4,adate);
1416 srv_put_dos_date2(p,8,mdate);
1417 SIVAL(p,12,(uint32)file_size);
1418 SIVAL(p,16,(uint32)allocation_size);
1420 p += 22; /* p now points to the EA area. */
1422 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1423 name_list = ea_list_union(name_list, file_list, &ea_len);
1425 /* We need to determine if this entry will fit in the space available. */
1426 /* Max string size is 255 bytes. */
1427 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1428 /* Move the dirptr back to prev_dirpos */
1429 dptr_SeekDir(conn->dirptr, prev_dirpos);
1430 *out_of_space = True;
1431 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1432 return False; /* Not finished - just out of space */
1435 /* Push the ea_data followed by the name. */
1436 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1438 len = srvstr_push(base_data, flags2,
1439 p + 1, fname, PTR_DIFF(end_data, p),
1440 STR_TERMINATE | STR_NOALIGN);
1441 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1454 SCVAL(nameptr,0,len);
1456 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1460 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1461 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1462 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1464 SIVAL(p,0,reskey); p += 4;
1465 put_long_date_timespec(p,create_date_ts); p += 8;
1466 put_long_date_timespec(p,adate_ts); p += 8;
1467 put_long_date_timespec(p,mdate_ts); p += 8;
1468 put_long_date_timespec(p,mdate_ts); p += 8;
1469 SOFF_T(p,0,file_size); p += 8;
1470 SOFF_T(p,0,allocation_size); p += 8;
1471 SIVAL(p,0,nt_extmode); p += 4;
1472 q = p; p += 4; /* q is placeholder for name length. */
1474 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1475 SIVAL(p,0,ea_size); /* Extended attributes */
1478 /* Clear the short name buffer. This is
1479 * IMPORTANT as not doing so will trigger
1480 * a Win2k client bug. JRA.
1482 if (!was_8_3 && check_mangled_names) {
1483 pstring mangled_name;
1484 pstrcpy(mangled_name, fname);
1485 mangle_map(mangled_name,True,True,
1487 mangled_name[12] = 0;
1488 len = srvstr_push(base_data, flags2,
1489 p+2, mangled_name, 24,
1490 STR_UPPER|STR_UNICODE);
1492 memset(p + 2 + len,'\0',24 - len);
1499 len = srvstr_push(base_data, flags2, p,
1500 fname, PTR_DIFF(end_data, p),
1501 STR_TERMINATE_ASCII);
1504 SIVAL(p,0,0); /* Ensure any padding is null. */
1505 len = PTR_DIFF(p, pdata);
1506 len = (len + 3) & ~3;
1511 case SMB_FIND_FILE_DIRECTORY_INFO:
1512 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1514 SIVAL(p,0,reskey); p += 4;
1515 put_long_date_timespec(p,create_date_ts); p += 8;
1516 put_long_date_timespec(p,adate_ts); p += 8;
1517 put_long_date_timespec(p,mdate_ts); p += 8;
1518 put_long_date_timespec(p,mdate_ts); p += 8;
1519 SOFF_T(p,0,file_size); p += 8;
1520 SOFF_T(p,0,allocation_size); p += 8;
1521 SIVAL(p,0,nt_extmode); p += 4;
1522 len = srvstr_push(base_data, flags2,
1523 p + 4, fname, PTR_DIFF(end_data, p),
1524 STR_TERMINATE_ASCII);
1527 SIVAL(p,0,0); /* Ensure any padding is null. */
1528 len = PTR_DIFF(p, pdata);
1529 len = (len + 3) & ~3;
1534 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1535 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1537 SIVAL(p,0,reskey); p += 4;
1538 put_long_date_timespec(p,create_date_ts); p += 8;
1539 put_long_date_timespec(p,adate_ts); p += 8;
1540 put_long_date_timespec(p,mdate_ts); p += 8;
1541 put_long_date_timespec(p,mdate_ts); p += 8;
1542 SOFF_T(p,0,file_size); p += 8;
1543 SOFF_T(p,0,allocation_size); p += 8;
1544 SIVAL(p,0,nt_extmode); p += 4;
1545 q = p; p += 4; /* q is placeholder for name length. */
1547 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1548 SIVAL(p,0,ea_size); /* Extended attributes */
1551 len = srvstr_push(base_data, flags2, p,
1552 fname, PTR_DIFF(end_data, p),
1553 STR_TERMINATE_ASCII);
1557 SIVAL(p,0,0); /* Ensure any padding is null. */
1558 len = PTR_DIFF(p, pdata);
1559 len = (len + 3) & ~3;
1564 case SMB_FIND_FILE_NAMES_INFO:
1565 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1567 SIVAL(p,0,reskey); p += 4;
1569 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1570 acl on a dir (tridge) */
1571 len = srvstr_push(base_data, flags2, p,
1572 fname, PTR_DIFF(end_data, p),
1573 STR_TERMINATE_ASCII);
1576 SIVAL(p,0,0); /* Ensure any padding is null. */
1577 len = PTR_DIFF(p, pdata);
1578 len = (len + 3) & ~3;
1583 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1584 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1586 SIVAL(p,0,reskey); p += 4;
1587 put_long_date_timespec(p,create_date_ts); p += 8;
1588 put_long_date_timespec(p,adate_ts); p += 8;
1589 put_long_date_timespec(p,mdate_ts); p += 8;
1590 put_long_date_timespec(p,mdate_ts); p += 8;
1591 SOFF_T(p,0,file_size); p += 8;
1592 SOFF_T(p,0,allocation_size); p += 8;
1593 SIVAL(p,0,nt_extmode); p += 4;
1594 q = p; p += 4; /* q is placeholder for name length. */
1596 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1597 SIVAL(p,0,ea_size); /* Extended attributes */
1600 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1601 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1602 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1603 len = srvstr_push(base_data, flags2, p,
1604 fname, PTR_DIFF(end_data, p),
1605 STR_TERMINATE_ASCII);
1608 SIVAL(p,0,0); /* Ensure any padding is null. */
1609 len = PTR_DIFF(p, pdata);
1610 len = (len + 3) & ~3;
1615 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1616 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1617 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1619 SIVAL(p,0,reskey); p += 4;
1620 put_long_date_timespec(p,create_date_ts); p += 8;
1621 put_long_date_timespec(p,adate_ts); p += 8;
1622 put_long_date_timespec(p,mdate_ts); p += 8;
1623 put_long_date_timespec(p,mdate_ts); p += 8;
1624 SOFF_T(p,0,file_size); p += 8;
1625 SOFF_T(p,0,allocation_size); p += 8;
1626 SIVAL(p,0,nt_extmode); p += 4;
1627 q = p; p += 4; /* q is placeholder for name length */
1629 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1630 SIVAL(p,0,ea_size); /* Extended attributes */
1633 /* Clear the short name buffer. This is
1634 * IMPORTANT as not doing so will trigger
1635 * a Win2k client bug. JRA.
1637 if (!was_8_3 && check_mangled_names) {
1638 pstring mangled_name;
1639 pstrcpy(mangled_name, fname);
1640 mangle_map(mangled_name,True,True,
1642 mangled_name[12] = 0;
1643 len = srvstr_push(base_data, flags2,
1644 p+2, mangled_name, 24,
1645 STR_UPPER|STR_UNICODE);
1648 memset(p + 2 + len,'\0',24 - len);
1655 SSVAL(p,0,0); p += 2; /* Reserved ? */
1656 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1657 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1658 len = srvstr_push(base_data, flags2, p,
1659 fname, PTR_DIFF(end_data, p),
1660 STR_TERMINATE_ASCII);
1663 SIVAL(p,0,0); /* Ensure any padding is null. */
1664 len = PTR_DIFF(p, pdata);
1665 len = (len + 3) & ~3;
1670 /* CIFS UNIX Extension. */
1672 case SMB_FIND_FILE_UNIX:
1673 case SMB_FIND_FILE_UNIX_INFO2:
1675 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1677 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1679 if (info_level == SMB_FIND_FILE_UNIX) {
1680 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1681 p = store_file_unix_basic(conn, p,
1683 len = srvstr_push(base_data, flags2, p,
1684 fname, PTR_DIFF(end_data, p),
1687 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1688 p = store_file_unix_basic_info2(conn, p,
1692 len = srvstr_push(base_data, flags2, p, fname,
1693 PTR_DIFF(end_data, p), 0);
1694 SIVAL(nameptr, 0, len);
1698 SIVAL(p,0,0); /* Ensure any padding is null. */
1700 len = PTR_DIFF(p, pdata);
1701 len = (len + 3) & ~3;
1702 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1704 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1713 if (PTR_DIFF(p,pdata) > space_remaining) {
1714 /* Move the dirptr back to prev_dirpos */
1715 dptr_SeekDir(conn->dirptr, prev_dirpos);
1716 *out_of_space = True;
1717 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1718 return False; /* Not finished - just out of space */
1721 /* Setup the last entry pointer, as an offset from base_data */
1722 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1723 /* Advance the data pointer to the next slot */
1729 /****************************************************************************
1730 Reply to a TRANS2_FINDFIRST.
1731 ****************************************************************************/
1733 static void call_trans2findfirst(connection_struct *conn,
1734 struct smb_request *req,
1735 char **pparams, int total_params,
1736 char **ppdata, int total_data,
1737 unsigned int max_data_bytes)
1739 /* We must be careful here that we don't return more than the
1740 allowed number of data bytes. If this means returning fewer than
1741 maxentries then so be it. We assume that the redirector has
1742 enough room for the fixed number of parameter bytes it has
1744 char *params = *pparams;
1745 char *pdata = *ppdata;
1749 uint16 findfirst_flags;
1750 BOOL close_after_first;
1752 BOOL requires_resume_key;
1757 int last_entry_off=0;
1761 BOOL finished = False;
1762 BOOL dont_descend = False;
1763 BOOL out_of_space = False;
1764 int space_remaining;
1765 BOOL mask_contains_wcard = False;
1766 SMB_STRUCT_STAT sbuf;
1767 TALLOC_CTX *ea_ctx = NULL;
1768 struct ea_list *ea_list = NULL;
1769 NTSTATUS ntstatus = NT_STATUS_OK;
1771 if (total_params < 13) {
1772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1776 dirtype = SVAL(params,0);
1777 maxentries = SVAL(params,2);
1778 findfirst_flags = SVAL(params,4);
1779 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1780 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1781 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1782 info_level = SVAL(params,6);
1784 *directory = *mask = 0;
1786 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1787 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1788 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1789 info_level, max_data_bytes));
1792 /* W2K3 seems to treat zero as 1. */
1796 switch (info_level) {
1797 case SMB_FIND_INFO_STANDARD:
1798 case SMB_FIND_EA_SIZE:
1799 case SMB_FIND_EA_LIST:
1800 case SMB_FIND_FILE_DIRECTORY_INFO:
1801 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1802 case SMB_FIND_FILE_NAMES_INFO:
1803 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1804 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1805 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1807 case SMB_FIND_FILE_UNIX:
1808 case SMB_FIND_FILE_UNIX_INFO2:
1809 if (!lp_unix_extensions()) {
1810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1815 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1819 srvstr_get_path_wcard(params, req->flags2, directory,
1820 params+12, sizeof(directory), total_params - 12,
1821 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1822 if (!NT_STATUS_IS_OK(ntstatus)) {
1823 reply_nterror(req, ntstatus);
1827 ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1828 if (!NT_STATUS_IS_OK(ntstatus)) {
1829 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1830 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1831 ERRSRV, ERRbadpath);
1834 reply_nterror(req, ntstatus);
1838 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1839 if (!NT_STATUS_IS_OK(ntstatus)) {
1840 reply_nterror(req, ntstatus);
1843 ntstatus = check_name(conn, directory);
1844 if (!NT_STATUS_IS_OK(ntstatus)) {
1845 reply_nterror(req, ntstatus);
1849 p = strrchr_m(directory,'/');
1851 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1852 if((directory[0] == '.') && (directory[1] == '\0')) {
1854 mask_contains_wcard = True;
1856 pstrcpy(mask,directory);
1858 pstrcpy(directory,"./");
1864 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1866 if (info_level == SMB_FIND_EA_LIST) {
1869 if (total_data < 4) {
1870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1874 ea_size = IVAL(pdata,0);
1875 if (ea_size != total_data) {
1876 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1877 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1882 if (!lp_ea_support(SNUM(conn))) {
1883 reply_doserror(req, ERRDOS, ERReasnotsupported);
1887 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1888 reply_nterror(req, NT_STATUS_NO_MEMORY);
1892 /* Pull out the list of names. */
1893 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1895 talloc_destroy(ea_ctx);
1896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1901 *ppdata = (char *)SMB_REALLOC(
1902 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1903 if(*ppdata == NULL ) {
1904 talloc_destroy(ea_ctx);
1905 reply_nterror(req, NT_STATUS_NO_MEMORY);
1909 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1911 /* Realloc the params space */
1912 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1913 if (*pparams == NULL) {
1914 talloc_destroy(ea_ctx);
1915 reply_nterror(req, NT_STATUS_NO_MEMORY);
1920 /* Save the wildcard match and attribs we are using on this directory -
1921 needed as lanman2 assumes these are being saved between calls */
1923 ntstatus = dptr_create(conn,
1929 mask_contains_wcard,
1933 if (!NT_STATUS_IS_OK(ntstatus)) {
1934 talloc_destroy(ea_ctx);
1935 reply_nterror(req, ntstatus);
1939 dptr_num = dptr_dnum(conn->dirptr);
1940 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1942 /* We don't need to check for VOL here as this is returned by
1943 a different TRANS2 call. */
1945 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1946 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1947 dont_descend = True;
1950 space_remaining = max_data_bytes;
1951 out_of_space = False;
1953 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1954 BOOL got_exact_match = False;
1956 /* this is a heuristic to avoid seeking the dirptr except when
1957 absolutely necessary. It allows for a filename of about 40 chars */
1958 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1959 out_of_space = True;
1962 finished = !get_lanman2_dir_entry(conn,
1964 mask,dirtype,info_level,
1965 requires_resume_key,dont_descend,
1967 space_remaining, &out_of_space,
1969 &last_entry_off, ea_list, ea_ctx);
1972 if (finished && out_of_space)
1975 if (!finished && !out_of_space)
1979 * As an optimisation if we know we aren't looking
1980 * for a wildcard name (ie. the name matches the wildcard exactly)
1981 * then we can finish on any (first) match.
1982 * This speeds up large directory searches. JRA.
1988 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1991 talloc_destroy(ea_ctx);
1993 /* Check if we can close the dirptr */
1994 if(close_after_first || (finished && close_if_end)) {
1995 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1996 dptr_close(&dptr_num);
2000 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2001 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2002 * the protocol level is less than NT1. Tested with smbclient. JRA.
2003 * This should fix the OS/2 client bug #2335.
2006 if(numentries == 0) {
2007 dptr_close(&dptr_num);
2008 if (Protocol < PROTOCOL_NT1) {
2009 reply_doserror(req, ERRDOS, ERRnofiles);
2012 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2013 ERRDOS, ERRbadfile);
2018 /* At this point pdata points to numentries directory entries. */
2020 /* Set up the return parameter block */
2021 SSVAL(params,0,dptr_num);
2022 SSVAL(params,2,numentries);
2023 SSVAL(params,4,finished);
2024 SSVAL(params,6,0); /* Never an EA error */
2025 SSVAL(params,8,last_entry_off);
2027 send_trans2_replies_new(req, params, 10, pdata, PTR_DIFF(p,pdata),
2030 if ((! *directory) && dptr_path(dptr_num))
2031 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2033 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2034 smb_fn_name(CVAL(req->inbuf,smb_com)),
2035 mask, directory, dirtype, numentries ) );
2038 * Force a name mangle here to ensure that the
2039 * mask as an 8.3 name is top of the mangled cache.
2040 * The reasons for this are subtle. Don't remove
2041 * this code unless you know what you are doing
2042 * (see PR#13758). JRA.
2045 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
2046 mangle_map(mask, True, True, conn->params);
2051 /****************************************************************************
2052 Reply to a TRANS2_FINDNEXT.
2053 ****************************************************************************/
2055 static void call_trans2findnext(connection_struct *conn,
2056 struct smb_request *req,
2057 char **pparams, int total_params,
2058 char **ppdata, int total_data,
2059 unsigned int max_data_bytes)
2061 /* We must be careful here that we don't return more than the
2062 allowed number of data bytes. If this means returning fewer than
2063 maxentries then so be it. We assume that the redirector has
2064 enough room for the fixed number of parameter bytes it has
2066 char *params = *pparams;
2067 char *pdata = *ppdata;
2073 uint16 findnext_flags;
2074 BOOL close_after_request;
2076 BOOL requires_resume_key;
2078 BOOL mask_contains_wcard = False;
2079 pstring resume_name;
2085 int i, last_entry_off=0;
2086 BOOL finished = False;
2087 BOOL dont_descend = False;
2088 BOOL out_of_space = False;
2089 int space_remaining;
2090 TALLOC_CTX *ea_ctx = NULL;
2091 struct ea_list *ea_list = NULL;
2092 NTSTATUS ntstatus = NT_STATUS_OK;
2094 if (total_params < 13) {
2095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2099 dptr_num = SVAL(params,0);
2100 maxentries = SVAL(params,2);
2101 info_level = SVAL(params,4);
2102 resume_key = IVAL(params,6);
2103 findnext_flags = SVAL(params,10);
2104 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2105 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2106 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2107 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2109 *mask = *directory = *resume_name = 0;
2111 srvstr_get_path_wcard(params, req->flags2, resume_name,
2112 params+12, sizeof(resume_name),
2113 total_params - 12, STR_TERMINATE, &ntstatus,
2114 &mask_contains_wcard);
2115 if (!NT_STATUS_IS_OK(ntstatus)) {
2116 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2117 complain (it thinks we're asking for the directory above the shared
2118 path or an invalid name). Catch this as the resume name is only compared, never used in
2119 a file access. JRA. */
2120 srvstr_pull(params, req->flags2,
2121 resume_name, params+12,
2122 sizeof(resume_name), total_params - 12,
2125 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2126 reply_nterror(req, ntstatus);
2131 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2132 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2133 resume_key = %d resume name = %s continue=%d level = %d\n",
2134 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2135 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2138 /* W2K3 seems to treat zero as 1. */
2142 switch (info_level) {
2143 case SMB_FIND_INFO_STANDARD:
2144 case SMB_FIND_EA_SIZE:
2145 case SMB_FIND_EA_LIST:
2146 case SMB_FIND_FILE_DIRECTORY_INFO:
2147 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2148 case SMB_FIND_FILE_NAMES_INFO:
2149 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2150 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2151 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2153 case SMB_FIND_FILE_UNIX:
2154 case SMB_FIND_FILE_UNIX_INFO2:
2155 if (!lp_unix_extensions()) {
2156 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2161 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2165 if (info_level == SMB_FIND_EA_LIST) {
2168 if (total_data < 4) {
2169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2173 ea_size = IVAL(pdata,0);
2174 if (ea_size != total_data) {
2175 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2176 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2181 if (!lp_ea_support(SNUM(conn))) {
2182 reply_doserror(req, ERRDOS, ERReasnotsupported);
2186 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2191 /* Pull out the list of names. */
2192 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2194 talloc_destroy(ea_ctx);
2195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2200 *ppdata = (char *)SMB_REALLOC(
2201 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2202 if(*ppdata == NULL) {
2203 talloc_destroy(ea_ctx);
2204 reply_nterror(req, NT_STATUS_NO_MEMORY);
2209 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2211 /* Realloc the params space */
2212 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2213 if(*pparams == NULL ) {
2214 talloc_destroy(ea_ctx);
2215 reply_nterror(req, NT_STATUS_NO_MEMORY);
2221 /* Check that the dptr is valid */
2222 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2223 talloc_destroy(ea_ctx);
2224 reply_doserror(req, ERRDOS, ERRnofiles);
2228 string_set(&conn->dirpath,dptr_path(dptr_num));
2230 /* Get the wildcard mask from the dptr */
2231 if((p = dptr_wcard(dptr_num))== NULL) {
2232 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2233 talloc_destroy(ea_ctx);
2234 reply_doserror(req, ERRDOS, ERRnofiles);
2239 pstrcpy(directory,conn->dirpath);
2241 /* Get the attr mask from the dptr */
2242 dirtype = dptr_attr(dptr_num);
2244 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2245 dptr_num, mask, dirtype,
2247 dptr_TellDir(conn->dirptr)));
2249 /* We don't need to check for VOL here as this is returned by
2250 a different TRANS2 call. */
2252 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2253 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2254 dont_descend = True;
2257 space_remaining = max_data_bytes;
2258 out_of_space = False;
2261 * Seek to the correct position. We no longer use the resume key but
2262 * depend on the last file name instead.
2265 if(*resume_name && !continue_bit) {
2268 long current_pos = 0;
2270 * Remember, mangle_map is called by
2271 * get_lanman2_dir_entry(), so the resume name
2272 * could be mangled. Ensure we check the unmangled name.
2275 if (mangle_is_mangled(resume_name, conn->params)) {
2276 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2281 * Fix for NT redirector problem triggered by resume key indexes
2282 * changing between directory scans. We now return a resume key of 0
2283 * and instead look for the filename to continue from (also given
2284 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2285 * findfirst/findnext (as is usual) then the directory pointer
2286 * should already be at the correct place.
2289 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2290 } /* end if resume_name && !continue_bit */
2292 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2293 BOOL got_exact_match = False;
2295 /* this is a heuristic to avoid seeking the dirptr except when
2296 absolutely necessary. It allows for a filename of about 40 chars */
2297 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2298 out_of_space = True;
2301 finished = !get_lanman2_dir_entry(conn,
2303 mask,dirtype,info_level,
2304 requires_resume_key,dont_descend,
2306 space_remaining, &out_of_space,
2308 &last_entry_off, ea_list, ea_ctx);
2311 if (finished && out_of_space)
2314 if (!finished && !out_of_space)
2318 * As an optimisation if we know we aren't looking
2319 * for a wildcard name (ie. the name matches the wildcard exactly)
2320 * then we can finish on any (first) match.
2321 * This speeds up large directory searches. JRA.
2327 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2330 talloc_destroy(ea_ctx);
2332 /* Check if we can close the dirptr */
2333 if(close_after_request || (finished && close_if_end)) {
2334 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2335 dptr_close(&dptr_num); /* This frees up the saved mask */
2338 /* Set up the return parameter block */
2339 SSVAL(params,0,numentries);
2340 SSVAL(params,2,finished);
2341 SSVAL(params,4,0); /* Never an EA error */
2342 SSVAL(params,6,last_entry_off);
2344 send_trans2_replies_new(req, params, 8, pdata, PTR_DIFF(p,pdata),
2347 if ((! *directory) && dptr_path(dptr_num))
2348 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2350 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2351 smb_fn_name(CVAL(req->inbuf,smb_com)),
2352 mask, directory, dirtype, numentries ) );
2357 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2359 E_md4hash(lp_servicename(SNUM(conn)),objid);
2363 /****************************************************************************
2364 Reply to a TRANS2_QFSINFO (query filesystem info).
2365 ****************************************************************************/
2367 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2368 char **pparams, int total_params, char **ppdata, int total_data,
2369 unsigned int max_data_bytes)
2372 char *params = *pparams;
2376 const char *vname = volume_label(SNUM(conn));
2377 int snum = SNUM(conn);
2378 char *fstype = lp_fstype(SNUM(conn));
2381 if (total_params < 2) {
2382 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2385 info_level = SVAL(params,0);
2387 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2389 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2390 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2391 return ERROR_DOS(ERRSRV,ERRinvdevice);
2394 *ppdata = (char *)SMB_REALLOC(
2395 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2396 if (*ppdata == NULL ) {
2397 return ERROR_NT(NT_STATUS_NO_MEMORY);
2401 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2403 switch (info_level) {
2404 case SMB_INFO_ALLOCATION:
2406 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2408 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2409 return(UNIXERROR(ERRHRD,ERRgeneral));
2412 block_size = lp_block_size(snum);
2413 if (bsize < block_size) {
2414 SMB_BIG_UINT factor = block_size/bsize;
2419 if (bsize > block_size) {
2420 SMB_BIG_UINT factor = bsize/block_size;
2425 bytes_per_sector = 512;
2426 sectors_per_unit = bsize/bytes_per_sector;
2428 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2429 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2430 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2432 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2433 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2434 SIVAL(pdata,l1_cUnit,dsize);
2435 SIVAL(pdata,l1_cUnitAvail,dfree);
2436 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2440 case SMB_INFO_VOLUME:
2441 /* Return volume name */
2443 * Add volume serial number - hash of a combination of
2444 * the called hostname and the service name.
2446 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2448 * Win2k3 and previous mess this up by sending a name length
2449 * one byte short. I believe only older clients (OS/2 Win9x) use
2450 * this call so try fixing this by adding a terminating null to
2451 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2453 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2454 pdata+l2_vol_szVolLabel, vname,
2455 -1, STR_NOALIGN|STR_TERMINATE);
2456 SCVAL(pdata,l2_vol_cch,len);
2457 data_len = l2_vol_szVolLabel + len;
2458 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2459 (unsigned)st.st_ctime, len, vname));
2462 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2463 case SMB_FS_ATTRIBUTE_INFORMATION:
2466 #if defined(HAVE_SYS_QUOTAS)
2467 quota_flag = FILE_VOLUME_QUOTAS;
2470 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2471 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2472 FILE_SUPPORTS_OBJECT_IDS|
2473 FILE_UNICODE_ON_DISK|
2474 quota_flag); /* FS ATTRIBUTES */
2476 SIVAL(pdata,4,255); /* Max filename component length */
2477 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2478 and will think we can't do long filenames */
2479 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2480 pdata+12, fstype, -1, STR_UNICODE);
2482 data_len = 12 + len;
2485 case SMB_QUERY_FS_LABEL_INFO:
2486 case SMB_FS_LABEL_INFORMATION:
2487 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2488 pdata+4, vname, -1, 0);
2493 case SMB_QUERY_FS_VOLUME_INFO:
2494 case SMB_FS_VOLUME_INFORMATION:
2497 * Add volume serial number - hash of a combination of
2498 * the called hostname and the service name.
2500 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2501 (str_checksum(get_local_machine_name())<<16));
2503 /* Max label len is 32 characters. */
2504 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2505 pdata+18, vname, -1, STR_UNICODE);
2506 SIVAL(pdata,12,len);
2509 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2510 (int)strlen(vname),vname, lp_servicename(snum)));
2513 case SMB_QUERY_FS_SIZE_INFO:
2514 case SMB_FS_SIZE_INFORMATION:
2516 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2518 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2519 return(UNIXERROR(ERRHRD,ERRgeneral));
2521 block_size = lp_block_size(snum);
2522 if (bsize < block_size) {
2523 SMB_BIG_UINT factor = block_size/bsize;
2528 if (bsize > block_size) {
2529 SMB_BIG_UINT factor = bsize/block_size;
2534 bytes_per_sector = 512;
2535 sectors_per_unit = bsize/bytes_per_sector;
2536 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2537 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2538 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2539 SBIG_UINT(pdata,0,dsize);
2540 SBIG_UINT(pdata,8,dfree);
2541 SIVAL(pdata,16,sectors_per_unit);
2542 SIVAL(pdata,20,bytes_per_sector);
2546 case SMB_FS_FULL_SIZE_INFORMATION:
2548 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2550 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2551 return(UNIXERROR(ERRHRD,ERRgeneral));
2553 block_size = lp_block_size(snum);
2554 if (bsize < block_size) {
2555 SMB_BIG_UINT factor = block_size/bsize;
2560 if (bsize > block_size) {
2561 SMB_BIG_UINT factor = bsize/block_size;
2566 bytes_per_sector = 512;
2567 sectors_per_unit = bsize/bytes_per_sector;
2568 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2569 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2570 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2571 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2572 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2573 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2574 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2575 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2579 case SMB_QUERY_FS_DEVICE_INFO:
2580 case SMB_FS_DEVICE_INFORMATION:
2582 SIVAL(pdata,0,0); /* dev type */
2583 SIVAL(pdata,4,0); /* characteristics */
2586 #ifdef HAVE_SYS_QUOTAS
2587 case SMB_FS_QUOTA_INFORMATION:
2589 * what we have to send --metze:
2591 * Unknown1: 24 NULL bytes
2592 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2593 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2594 * Quota Flags: 2 byte :
2595 * Unknown3: 6 NULL bytes
2599 * details for Quota Flags:
2601 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2602 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2603 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2604 * 0x0001 Enable Quotas: enable quota for this fs
2608 /* we need to fake up a fsp here,
2609 * because its not send in this call
2612 SMB_NTQUOTA_STRUCT quotas;
2615 ZERO_STRUCT(quotas);
2621 if (current_user.ut.uid != 0) {
2622 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2623 lp_servicename(SNUM(conn)),conn->user));
2624 return ERROR_DOS(ERRDOS,ERRnoaccess);
2627 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2628 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2629 return ERROR_DOS(ERRSRV,ERRerror);
2634 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2636 /* Unknown1 24 NULL bytes*/
2637 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2638 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2639 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2641 /* Default Soft Quota 8 bytes */
2642 SBIG_UINT(pdata,24,quotas.softlim);
2644 /* Default Hard Quota 8 bytes */
2645 SBIG_UINT(pdata,32,quotas.hardlim);
2647 /* Quota flag 2 bytes */
2648 SSVAL(pdata,40,quotas.qflags);
2650 /* Unknown3 6 NULL bytes */
2656 #endif /* HAVE_SYS_QUOTAS */
2657 case SMB_FS_OBJECTID_INFORMATION:
2659 unsigned char objid[16];
2660 memcpy(pdata,create_volume_objectid(conn, objid),16);
2666 * Query the version and capabilities of the CIFS UNIX extensions
2670 case SMB_QUERY_CIFS_UNIX_INFO:
2671 if (!lp_unix_extensions()) {
2672 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2675 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2676 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2677 /* We have POSIX ACLs, pathname and locking capability. */
2678 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2679 CIFS_UNIX_POSIX_ACLS_CAP|
2680 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2681 CIFS_UNIX_FCNTL_LOCKS_CAP|
2682 CIFS_UNIX_EXTATTR_CAP|
2683 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2684 /* Ensure we don't do this on signed or sealed data. */
2685 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2689 case SMB_QUERY_POSIX_FS_INFO:
2692 vfs_statvfs_struct svfs;
2694 if (!lp_unix_extensions()) {
2695 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2698 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2702 SIVAL(pdata,0,svfs.OptimalTransferSize);
2703 SIVAL(pdata,4,svfs.BlockSize);
2704 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2705 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2706 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2707 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2708 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2709 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2710 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2712 } else if (rc == EOPNOTSUPP) {
2713 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2714 #endif /* EOPNOTSUPP */
2716 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2717 return ERROR_DOS(ERRSRV,ERRerror);
2722 case SMB_QUERY_POSIX_WHOAMI:
2728 if (!lp_unix_extensions()) {
2729 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2732 if (max_data_bytes < 40) {
2733 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2736 /* We ARE guest if global_sid_Builtin_Guests is
2737 * in our list of SIDs.
2739 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2740 current_user.nt_user_token)) {
2741 flags |= SMB_WHOAMI_GUEST;
2744 /* We are NOT guest if global_sid_Authenticated_Users
2745 * is in our list of SIDs.
2747 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2748 current_user.nt_user_token)) {
2749 flags &= ~SMB_WHOAMI_GUEST;
2752 /* NOTE: 8 bytes for UID/GID, irrespective of native
2753 * platform size. This matches
2754 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2756 data_len = 4 /* flags */
2763 + 4 /* pad/reserved */
2764 + (current_user.ut.ngroups * 8)
2766 + (current_user.nt_user_token->num_sids *
2770 SIVAL(pdata, 0, flags);
2771 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2772 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2773 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2776 if (data_len >= max_data_bytes) {
2777 /* Potential overflow, skip the GIDs and SIDs. */
2779 SIVAL(pdata, 24, 0); /* num_groups */
2780 SIVAL(pdata, 28, 0); /* num_sids */
2781 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2782 SIVAL(pdata, 36, 0); /* reserved */
2788 SIVAL(pdata, 24, current_user.ut.ngroups);
2790 current_user.nt_user_token->num_sids);
2792 /* We walk the SID list twice, but this call is fairly
2793 * infrequent, and I don't expect that it's performance
2794 * sensitive -- jpeach
2796 for (i = 0, sid_bytes = 0;
2797 i < current_user.nt_user_token->num_sids; ++i) {
2799 sid_size(¤t_user.nt_user_token->user_sids[i]);
2802 /* SID list byte count */
2803 SIVAL(pdata, 32, sid_bytes);
2805 /* 4 bytes pad/reserved - must be zero */
2806 SIVAL(pdata, 36, 0);
2810 for (i = 0; i < current_user.ut.ngroups; ++i) {
2811 SBIG_UINT(pdata, data_len,
2812 (SMB_BIG_UINT)current_user.ut.groups[i]);
2818 i < current_user.nt_user_token->num_sids; ++i) {
2820 sid_size(¤t_user.nt_user_token->user_sids[i]);
2822 sid_linearize(pdata + data_len, sid_len,
2823 ¤t_user.nt_user_token->user_sids[i]);
2824 data_len += sid_len;
2830 case SMB_MAC_QUERY_FS_INFO:
2832 * Thursby MAC extension... ONLY on NTFS filesystems
2833 * once we do streams then we don't need this
2835 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2837 SIVAL(pdata,84,0x100); /* Don't support mac... */
2842 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2846 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2848 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2853 /****************************************************************************
2854 Reply to a TRANS2_SETFSINFO (set filesystem info).
2855 ****************************************************************************/
2857 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2858 char **pparams, int total_params, char **ppdata, int total_data,
2859 unsigned int max_data_bytes)
2861 char *pdata = *ppdata;
2862 char *params = *pparams;
2866 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2869 if (total_params < 4) {
2870 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2872 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2875 info_level = SVAL(params,2);
2877 switch(info_level) {
2878 case SMB_SET_CIFS_UNIX_INFO:
2880 uint16 client_unix_major;
2881 uint16 client_unix_minor;
2882 uint32 client_unix_cap_low;
2883 uint32 client_unix_cap_high;
2885 if (!lp_unix_extensions()) {
2886 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2889 /* There should be 12 bytes of capabilities set. */
2890 if (total_data < 8) {
2891 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2893 client_unix_major = SVAL(pdata,0);
2894 client_unix_minor = SVAL(pdata,2);
2895 client_unix_cap_low = IVAL(pdata,4);
2896 client_unix_cap_high = IVAL(pdata,8);
2897 /* Just print these values for now. */
2898 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2899 cap_low = 0x%x, cap_high = 0x%x\n",
2900 (unsigned int)client_unix_major,
2901 (unsigned int)client_unix_minor,
2902 (unsigned int)client_unix_cap_low,
2903 (unsigned int)client_unix_cap_high ));
2905 /* Here is where we must switch to posix pathname processing... */
2906 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2907 lp_set_posix_pathnames();
2908 mangle_change_to_posix();
2911 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2912 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2913 /* Client that knows how to do posix locks,
2914 * but not posix open/mkdir operations. Set a
2915 * default type for read/write checks. */
2917 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2922 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2925 size_t param_len = 0;
2926 size_t data_len = total_data;
2928 if (!lp_unix_extensions()) {
2929 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2932 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2934 status = srv_request_encryption_setup(conn,
2935 (unsigned char **)ppdata,
2937 (unsigned char **)pparams,
2941 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2942 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2943 } else if (!NT_STATUS_IS_OK(status)) {
2944 return ERROR_NT(status);
2947 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2949 if (NT_STATUS_IS_OK(status)) {
2950 /* Server-side transport encryption is now *on*. */
2951 status = srv_encryption_start(conn);
2952 if (!NT_STATUS_IS_OK(status)) {
2953 exit_server_cleanly("Failure in setting up encrypted transport");
2958 case SMB_FS_QUOTA_INFORMATION:
2960 files_struct *fsp = NULL;
2961 SMB_NTQUOTA_STRUCT quotas;
2963 ZERO_STRUCT(quotas);
2966 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2967 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2968 lp_servicename(SNUM(conn)),conn->user));
2969 return ERROR_DOS(ERRSRV,ERRaccess);
2972 /* note: normaly there're 48 bytes,
2973 * but we didn't use the last 6 bytes for now
2976 fsp = file_fsp(SVAL(params,0));
2977 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2978 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2979 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2982 if (total_data < 42) {
2983 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2985 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2988 /* unknown_1 24 NULL bytes in pdata*/
2990 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2991 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2992 #ifdef LARGE_SMB_OFF_T
2993 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2994 #else /* LARGE_SMB_OFF_T */
2995 if ((IVAL(pdata,28) != 0)&&
2996 ((quotas.softlim != 0xFFFFFFFF)||
2997 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2998 /* more than 32 bits? */
2999 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3001 #endif /* LARGE_SMB_OFF_T */
3003 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3004 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3005 #ifdef LARGE_SMB_OFF_T
3006 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3007 #else /* LARGE_SMB_OFF_T */
3008 if ((IVAL(pdata,36) != 0)&&
3009 ((quotas.hardlim != 0xFFFFFFFF)||
3010 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3011 /* more than 32 bits? */
3012 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3014 #endif /* LARGE_SMB_OFF_T */
3016 /* quota_flags 2 bytes **/
3017 quotas.qflags = SVAL(pdata,40);
3019 /* unknown_2 6 NULL bytes follow*/
3021 /* now set the quotas */
3022 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3023 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3024 return ERROR_DOS(ERRSRV,ERRerror);
3030 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3032 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3037 * sending this reply works fine,
3038 * but I'm not sure it's the same
3039 * like windows do...
3042 outsize = set_message(inbuf, outbuf,10,0,True);
3047 #if defined(HAVE_POSIX_ACLS)
3048 /****************************************************************************
3049 Utility function to count the number of entries in a POSIX acl.
3050 ****************************************************************************/
3052 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3054 unsigned int ace_count = 0;
3055 int entry_id = SMB_ACL_FIRST_ENTRY;
3056 SMB_ACL_ENTRY_T entry;
3058 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3060 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3061 entry_id = SMB_ACL_NEXT_ENTRY;
3068 /****************************************************************************
3069 Utility function to marshall a POSIX acl into wire format.
3070 ****************************************************************************/
3072 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3074 int entry_id = SMB_ACL_FIRST_ENTRY;
3075 SMB_ACL_ENTRY_T entry;
3077 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3078 SMB_ACL_TAG_T tagtype;
3079 SMB_ACL_PERMSET_T permset;
3080 unsigned char perms = 0;
3081 unsigned int own_grp;
3084 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3085 entry_id = SMB_ACL_NEXT_ENTRY;
3088 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3089 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3093 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3094 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3098 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3099 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3100 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3102 SCVAL(pdata,1,perms);
3105 case SMB_ACL_USER_OBJ:
3106 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3107 own_grp = (unsigned int)pst->st_uid;
3108 SIVAL(pdata,2,own_grp);
3113 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3115 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3118 own_grp = (unsigned int)*puid;
3119 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3120 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3121 SIVAL(pdata,2,own_grp);
3125 case SMB_ACL_GROUP_OBJ:
3126 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3127 own_grp = (unsigned int)pst->st_gid;
3128 SIVAL(pdata,2,own_grp);
3133 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3135 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3138 own_grp = (unsigned int)*pgid;
3139 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3140 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3141 SIVAL(pdata,2,own_grp);
3146 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3147 SIVAL(pdata,2,0xFFFFFFFF);
3148 SIVAL(pdata,6,0xFFFFFFFF);
3151 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3152 SIVAL(pdata,2,0xFFFFFFFF);
3153 SIVAL(pdata,6,0xFFFFFFFF);
3156 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3159 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3166 /****************************************************************************
3167 Store the FILE_UNIX_BASIC info.
3168 ****************************************************************************/
3170 static char *store_file_unix_basic(connection_struct *conn,
3173 const SMB_STRUCT_STAT *psbuf)
3175 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3176 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3178 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3181 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3184 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3185 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3186 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3189 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3193 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3197 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3200 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3204 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3208 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3211 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3215 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3222 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3223 * the chflags(2) (or equivalent) flags.
3225 * XXX: this really should be behind the VFS interface. To do this, we would
3226 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3227 * Each VFS module could then implement it's own mapping as appropriate for the
3228 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3230 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3234 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3238 { UF_IMMUTABLE, EXT_IMMUTABLE },
3242 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3246 { UF_HIDDEN, EXT_HIDDEN },
3249 /* Do not remove. We need to guarantee that this array has at least one
3250 * entry to build on HP-UX.
3256 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3257 uint32 *smb_fflags, uint32 *smb_fmask)
3259 #ifdef HAVE_STAT_ST_FLAGS
3262 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3263 *smb_fmask |= info2_flags_map[i].smb_fflag;
3264 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3265 *smb_fflags |= info2_flags_map[i].smb_fflag;
3268 #endif /* HAVE_STAT_ST_FLAGS */
3271 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3272 const uint32 smb_fflags,
3273 const uint32 smb_fmask,
3276 #ifdef HAVE_STAT_ST_FLAGS
3277 uint32 max_fmask = 0;
3280 *stat_fflags = psbuf->st_flags;
3282 /* For each flags requested in smb_fmask, check the state of the
3283 * corresponding flag in smb_fflags and set or clear the matching
3287 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3288 max_fmask |= info2_flags_map[i].smb_fflag;
3289 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3290 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3291 *stat_fflags |= info2_flags_map[i].stat_fflag;
3293 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3298 /* If smb_fmask is asking to set any bits that are not supported by
3299 * our flag mappings, we should fail.
3301 if ((smb_fmask & max_fmask) != smb_fmask) {
3308 #endif /* HAVE_STAT_ST_FLAGS */
3312 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3313 * of file flags and birth (create) time.
3315 static char *store_file_unix_basic_info2(connection_struct *conn,
3318 const SMB_STRUCT_STAT *psbuf)
3320 uint32 file_flags = 0;
3321 uint32 flags_mask = 0;
3323 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3325 /* Create (birth) time 64 bit */
3326 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3329 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3330 SIVAL(pdata, 0, file_flags); /* flags */
3331 SIVAL(pdata, 4, flags_mask); /* mask */
3337 /****************************************************************************
3338 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3339 ****************************************************************************/
3341 static void call_trans2qpipeinfo(connection_struct *conn,
3342 struct smb_request *req,
3343 unsigned int tran_call,
3344 char **pparams, int total_params,
3345 char **ppdata, int total_data,
3346 unsigned int max_data_bytes)
3348 char *params = *pparams;
3349 char *pdata = *ppdata;
3350 unsigned int data_size = 0;
3351 unsigned int param_size = 2;
3353 smb_np_struct *p_pipe = NULL;
3356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3360 if (total_params < 4) {
3361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3365 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3366 if (p_pipe == NULL) {
3367 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3371 info_level = SVAL(params,2);
3373 *pparams = (char *)SMB_REALLOC(*pparams,2);
3374 if (*pparams == NULL) {
3375 reply_nterror(req, NT_STATUS_NO_MEMORY);
3380 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3381 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3382 if (*ppdata == NULL ) {
3383 reply_nterror(req, NT_STATUS_NO_MEMORY);
3388 switch (info_level) {
3389 case SMB_FILE_STANDARD_INFORMATION:
3391 SOFF_T(pdata,0,4096LL);
3398 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3402 send_trans2_replies_new(req, params, param_size, *ppdata, data_size,
3408 /****************************************************************************
3409 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3410 file name or file id).
3411 ****************************************************************************/
3413 static void call_trans2qfilepathinfo(connection_struct *conn,
3414 struct smb_request *req,
3415 unsigned int tran_call,
3416 char **pparams, int total_params,
3417 char **ppdata, int total_data,
3418 unsigned int max_data_bytes)
3420 char *params = *pparams;
3421 char *pdata = *ppdata;
3422 char *dstart, *dend;
3426 SMB_OFF_T file_size=0;
3427 SMB_BIG_UINT allocation_size=0;
3428 unsigned int data_size = 0;
3429 unsigned int param_size = 2;
3430 SMB_STRUCT_STAT sbuf;
3431 pstring fname, dos_fname;
3436 BOOL delete_pending = False;
3438 time_t create_time, mtime, atime;
3439 struct timespec create_time_ts, mtime_ts, atime_ts;
3440 files_struct *fsp = NULL;
3441 struct file_id fileid;
3442 TALLOC_CTX *data_ctx = NULL;
3443 struct ea_list *ea_list = NULL;
3444 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3445 char *lock_data = NULL;
3448 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3454 if (tran_call == TRANSACT2_QFILEINFO) {
3455 if (total_params < 4) {
3456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3461 call_trans2qpipeinfo(conn, req, tran_call,
3462 pparams, total_params,
3468 fsp = file_fsp(SVAL(params,0));
3469 info_level = SVAL(params,2);
3471 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3473 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3474 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3478 if(fsp && (fsp->fake_file_handle)) {
3480 * This is actually for the QUOTA_FAKE_FILE --metze
3483 pstrcpy(fname, fsp->fsp_name);
3484 /* We know this name is ok, it's already passed the checks. */
3486 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3488 * This is actually a QFILEINFO on a directory
3489 * handle (returned from an NT SMB). NT5.0 seems
3490 * to do this call. JRA.
3492 /* We know this name is ok, it's already passed the checks. */
3493 pstrcpy(fname, fsp->fsp_name);
3495 if (INFO_LEVEL_IS_UNIX(info_level)) {
3496 /* Always do lstat for UNIX calls. */
3497 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3498 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3499 reply_unixerror(req,ERRDOS,ERRbadpath);
3502 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3503 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3504 reply_unixerror(req, ERRDOS, ERRbadpath);
3508 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3509 delete_pending = get_delete_on_close_flag(fileid);
3512 * Original code - this is an open file.
3514 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3518 pstrcpy(fname, fsp->fsp_name);
3519 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3520 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3521 reply_unixerror(req, ERRDOS, ERRbadfid);
3524 pos = fsp->fh->position_information;
3525 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3526 delete_pending = get_delete_on_close_flag(fileid);
3527 access_mask = fsp->access_mask;
3530 NTSTATUS status = NT_STATUS_OK;
3533 if (total_params < 7) {
3534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3538 info_level = SVAL(params,0);
3540 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3542 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3543 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3547 srvstr_get_path(params, req->flags2, fname, ¶ms[6],
3548 sizeof(fname), total_params - 6,
3549 STR_TERMINATE, &status);
3550 if (!NT_STATUS_IS_OK(status)) {
3551 reply_nterror(req, status);
3555 status = resolve_dfspath(conn,
3556 req->flags2 & FLAGS2_DFS_PATHNAMES,
3558 if (!NT_STATUS_IS_OK(status)) {
3559 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3560 reply_botherror(req,
3561 NT_STATUS_PATH_NOT_COVERED,
3562 ERRSRV, ERRbadpath);
3564 reply_nterror(req, status);
3568 status = unix_convert(conn, fname, False, NULL, &sbuf);
3569 if (!NT_STATUS_IS_OK(status)) {
3570 reply_nterror(req, status);
3573 status = check_name(conn, fname);
3574 if (!NT_STATUS_IS_OK(status)) {
3575 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3576 reply_nterror(req, status);
3580 if (INFO_LEVEL_IS_UNIX(info_level)) {
3581 /* Always do lstat for UNIX calls. */
3582 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3583 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3584 reply_unixerror(req, ERRDOS, ERRbadpath);
3587 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3588 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3589 reply_unixerror(req, ERRDOS, ERRbadpath);
3593 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3594 delete_pending = get_delete_on_close_flag(fileid);
3595 if (delete_pending) {
3596 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3601 nlink = sbuf.st_nlink;
3603 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3604 /* NTFS does not seem to count ".." */
3608 if ((nlink > 0) && delete_pending) {
3612 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3613 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3617 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3618 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3620 p = strrchr_m(fname,'/');
3626 mode = dos_mode(conn,fname,&sbuf);
3628 mode = FILE_ATTRIBUTE_NORMAL;
3630 fullpathname = fname;
3632 file_size = get_file_size(sbuf);
3634 /* Pull out any data sent here before we realloc. */
3635 switch (info_level) {
3636 case SMB_INFO_QUERY_EAS_FROM_LIST:
3638 /* Pull any EA list from the data portion. */
3641 if (total_data < 4) {
3643 req, NT_STATUS_INVALID_PARAMETER);
3646 ea_size = IVAL(pdata,0);
3648 if (total_data > 0 && ea_size != total_data) {
3649 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3650 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3652 req, NT_STATUS_INVALID_PARAMETER);
3656 if (!lp_ea_support(SNUM(conn))) {
3657 reply_doserror(req, ERRDOS,
3658 ERReasnotsupported);
3662 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3663 reply_nterror(req, NT_STATUS_NO_MEMORY);
3667 /* Pull out the list of names. */
3668 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3670 talloc_destroy(data_ctx);
3672 req, NT_STATUS_INVALID_PARAMETER);
3678 case SMB_QUERY_POSIX_LOCK:
3680 if (fsp == NULL || fsp->fh->fd == -1) {
3681 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3685 if (total_data != POSIX_LOCK_DATA_SIZE) {
3687 req, NT_STATUS_INVALID_PARAMETER);
3691 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3692 reply_nterror(req, NT_STATUS_NO_MEMORY);
3696 /* Copy the lock range data. */
3697 lock_data = (char *)TALLOC_MEMDUP(
3698 data_ctx, pdata, total_data);
3700 talloc_destroy(data_ctx);
3701 reply_nterror(req, NT_STATUS_NO_MEMORY);
3709 *pparams = (char *)SMB_REALLOC(*pparams,2);
3710 if (*pparams == NULL) {
3711 talloc_destroy(data_ctx);
3712 reply_nterror(req, NT_STATUS_NO_MEMORY);
3717 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3718 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3719 if (*ppdata == NULL ) {
3720 talloc_destroy(data_ctx);
3721 reply_nterror(req, NT_STATUS_NO_MEMORY);
3726 dend = dstart + data_size - 1;
3728 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3729 mtime_ts = get_mtimespec(&sbuf);
3730 atime_ts = get_atimespec(&sbuf);
3732 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3735 if (!null_timespec(fsp->pending_modtime)) {
3736 /* the pending modtime overrides the current modtime */
3737 mtime_ts = fsp->pending_modtime;
3741 /* Do we have this path open ? */
3742 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3743 fsp1 = file_find_di_first(fileid);
3744 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3745 /* the pending modtime overrides the current modtime */
3746 mtime_ts = fsp1->pending_modtime;
3748 if (fsp1 && fsp1->initial_allocation_size) {
3749 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3753 if (lp_dos_filetime_resolution(SNUM(conn))) {
3754 dos_filetime_timespec(&create_time_ts);
3755 dos_filetime_timespec(&mtime_ts);
3756 dos_filetime_timespec(&atime_ts);
3759 create_time = convert_timespec_to_time_t(create_time_ts);
3760 mtime = convert_timespec_to_time_t(mtime_ts);
3761 atime = convert_timespec_to_time_t(atime_ts);
3763 /* NT expects the name to be in an exact form of the *full*
3764 filename. See the trans2 torture test */
3765 if (strequal(base_name,".")) {
3766 pstrcpy(dos_fname, "\\");
3768 pstr_sprintf(dos_fname, "\\%s", fname);
3769 string_replace(dos_fname, '/', '\\');
3772 switch (info_level) {
3773 case SMB_INFO_STANDARD:
3774 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3776 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3777 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3778 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3779 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3780 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3781 SSVAL(pdata,l1_attrFile,mode);
3784 case SMB_INFO_QUERY_EA_SIZE:
3786 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3787 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3789 srv_put_dos_date2(pdata,0,create_time);
3790 srv_put_dos_date2(pdata,4,atime);
3791 srv_put_dos_date2(pdata,8,mtime); /* write time */
3792 SIVAL(pdata,12,(uint32)file_size);
3793 SIVAL(pdata,16,(uint32)allocation_size);
3794 SSVAL(pdata,20,mode);
3795 SIVAL(pdata,22,ea_size);
3799 case SMB_INFO_IS_NAME_VALID:
3800 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3801 if (tran_call == TRANSACT2_QFILEINFO) {
3802 /* os/2 needs this ? really ?*/
3803 reply_doserror(req, ERRDOS, ERRbadfunc);
3810 case SMB_INFO_QUERY_EAS_FROM_LIST:
3812 size_t total_ea_len = 0;
3813 struct ea_list *ea_file_list = NULL;
3815 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3817 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3818 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3820 if (!ea_list || (total_ea_len > data_size)) {
3821 talloc_destroy(data_ctx);
3823 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3827 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3828 talloc_destroy(data_ctx);
3832 case SMB_INFO_QUERY_ALL_EAS:
3834 /* We have data_size bytes to put EA's into. */
3835 size_t total_ea_len = 0;
3837 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3839 data_ctx = talloc_init("ea_ctx");
3841 reply_nterror(req, NT_STATUS_NO_MEMORY);
3845 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3846 if (!ea_list || (total_ea_len > data_size)) {
3847 talloc_destroy(data_ctx);
3849 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3853 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3854 talloc_destroy(data_ctx);
3858 case SMB_FILE_BASIC_INFORMATION:
3859 case SMB_QUERY_FILE_BASIC_INFO:
3861 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3862 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3863 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3865 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3869 put_long_date_timespec(pdata,create_time_ts);
3870 put_long_date_timespec(pdata+8,atime_ts);
3871 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3872 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3873 SIVAL(pdata,32,mode);
3875 DEBUG(5,("SMB_QFBI - "));
3876 DEBUG(5,("create: %s ", ctime(&create_time)));
3877 DEBUG(5,("access: %s ", ctime(&atime)));
3878 DEBUG(5,("write: %s ", ctime(&mtime)));
3879 DEBUG(5,("change: %s ", ctime(&mtime)));
3880 DEBUG(5,("mode: %x\n", mode));
3883 case SMB_FILE_STANDARD_INFORMATION:
3884 case SMB_QUERY_FILE_STANDARD_INFO:
3886 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3888 SOFF_T(pdata,0,allocation_size);
3889 SOFF_T(pdata,8,file_size);
3890 SIVAL(pdata,16,nlink);
3891 SCVAL(pdata,20,delete_pending?1:0);
3892 SCVAL(pdata,21,(mode&aDIR)?1:0);
3893 SSVAL(pdata,22,0); /* Padding. */
3896 case SMB_FILE_EA_INFORMATION:
3897 case SMB_QUERY_FILE_EA_INFO:
3899 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3900 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3902 SIVAL(pdata,0,ea_size);
3906 /* Get the 8.3 name - used if NT SMB was negotiated. */
3907 case SMB_QUERY_FILE_ALT_NAME_INFO:
3908 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3912 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3913 pstrcpy(short_name,base_name);
3914 /* Mangle if not already 8.3 */
3915 if(!mangle_is_8_3(short_name, True, conn->params)) {
3916 mangle_map(short_name,True,True,conn->params);
3918 len = srvstr_push(dstart, req->flags2,
3919 pdata+4, short_name,
3920 PTR_DIFF(dend, pdata+4),
3922 data_size = 4 + len;
3927 case SMB_QUERY_FILE_NAME_INFO:
3929 this must be *exactly* right for ACLs on mapped drives to work
3931 len = srvstr_push(dstart, req->flags2,
3933 PTR_DIFF(dend, pdata+4),
3935 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3936 data_size = 4 + len;
3940 case SMB_FILE_ALLOCATION_INFORMATION:
3941 case SMB_QUERY_FILE_ALLOCATION_INFO:
3942 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3944 SOFF_T(pdata,0,allocation_size);
3947 case SMB_FILE_END_OF_FILE_INFORMATION:
3948 case SMB_QUERY_FILE_END_OF_FILEINFO:
3949 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3951 SOFF_T(pdata,0,file_size);
3954 case SMB_QUERY_FILE_ALL_INFO:
3955 case SMB_FILE_ALL_INFORMATION:
3957 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3958 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3959 put_long_date_timespec(pdata,create_time_ts);
3960 put_long_date_timespec(pdata+8,atime_ts);
3961 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3962 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3963 SIVAL(pdata,32,mode);
3964 SIVAL(pdata,36,0); /* padding. */
3966 SOFF_T(pdata,0,allocation_size);
3967 SOFF_T(pdata,8,file_size);
3968 SIVAL(pdata,16,nlink);
3969 SCVAL(pdata,20,delete_pending);
3970 SCVAL(pdata,21,(mode&aDIR)?1:0);
3973 SIVAL(pdata,0,ea_size);
3974 pdata += 4; /* EA info */
3975 len = srvstr_push(dstart, req->flags2,
3977 PTR_DIFF(dend, pdata+4),
3981 data_size = PTR_DIFF(pdata,(*ppdata));
3984 case SMB_FILE_INTERNAL_INFORMATION:
3985 /* This should be an index number - looks like
3988 I think this causes us to fail the IFSKIT
3989 BasicFileInformationTest. -tpot */
3991 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3992 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3993 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3997 case SMB_FILE_ACCESS_INFORMATION:
3998 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3999 SIVAL(pdata,0,access_mask);
4003 case SMB_FILE_NAME_INFORMATION:
4004 /* Pathname with leading '\'. */
4007 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4008 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4009 SIVAL(pdata,0,byte_len);
4010 data_size = 4 + byte_len;
4014 case SMB_FILE_DISPOSITION_INFORMATION:
4015 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4017 SCVAL(pdata,0,delete_pending);
4020 case SMB_FILE_POSITION_INFORMATION:
4021 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4023 SOFF_T(pdata,0,pos);
4026 case SMB_FILE_MODE_INFORMATION:
4027 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4028 SIVAL(pdata,0,mode);
4032 case SMB_FILE_ALIGNMENT_INFORMATION:
4033 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4034 SIVAL(pdata,0,0); /* No alignment needed. */
4040 * NT4 server just returns "invalid query" to this - if we try to answer
4041 * it then NTws gets a BSOD! (tridge).
4042 * W2K seems to want this. JRA.
4044 case SMB_QUERY_FILE_STREAM_INFO:
4046 case SMB_FILE_STREAM_INFORMATION:
4047 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4051 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4052 SIVAL(pdata,0,0); /* ??? */
4053 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4054 SOFF_T(pdata,8,file_size);
4055 SOFF_T(pdata,16,allocation_size);
4056 data_size = 24 + byte_len;
4060 case SMB_QUERY_COMPRESSION_INFO:
4061 case SMB_FILE_COMPRESSION_INFORMATION:
4062 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4063 SOFF_T(pdata,0,file_size);
4064 SIVAL(pdata,8,0); /* ??? */
4065 SIVAL(pdata,12,0); /* ??? */
4069 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4070 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4071 put_long_date_timespec(pdata,create_time_ts);
4072 put_long_date_timespec(pdata+8,atime_ts);
4073 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4074 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4075 SOFF_T(pdata,32,allocation_size);
4076 SOFF_T(pdata,40,file_size);
4077 SIVAL(pdata,48,mode);
4078 SIVAL(pdata,52,0); /* ??? */
4082 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4083 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4084 SIVAL(pdata,0,mode);
4090 * CIFS UNIX Extensions.
4093 case SMB_QUERY_FILE_UNIX_BASIC:
4095 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4096 data_size = PTR_DIFF(pdata,(*ppdata));
4100 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4102 for (i=0; i<100; i++)
4103 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4109 case SMB_QUERY_FILE_UNIX_INFO2:
4111 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4112 data_size = PTR_DIFF(pdata,(*ppdata));
4116 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4118 for (i=0; i<100; i++)
4119 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4125 case SMB_QUERY_FILE_UNIX_LINK:
4129 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4131 if(!S_ISLNK(sbuf.st_mode)) {
4132 reply_unixerror(req, ERRSRV,
4137 reply_unixerror(req, ERRDOS, ERRbadlink);
4140 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
4142 reply_unixerror(req, ERRDOS,
4147 len = srvstr_push(dstart, req->flags2,
4149 PTR_DIFF(dend, pdata),
4152 data_size = PTR_DIFF(pdata,(*ppdata));
4157 #if defined(HAVE_POSIX_ACLS)
4158 case SMB_QUERY_POSIX_ACL:
4160 SMB_ACL_T file_acl = NULL;
4161 SMB_ACL_T def_acl = NULL;
4162 uint16 num_file_acls = 0;
4163 uint16 num_def_acls = 0;
4165 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4166 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4168 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4171 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4172 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4176 NT_STATUS_NOT_IMPLEMENTED);
4180 if (S_ISDIR(sbuf.st_mode)) {
4181 if (fsp && fsp->is_directory) {
4182 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4184 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4186 def_acl = free_empty_sys_acl(conn, def_acl);
4189 num_file_acls = count_acl_entries(conn, file_acl);
4190 num_def_acls = count_acl_entries(conn, def_acl);
4192 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4193 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4195 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4196 SMB_POSIX_ACL_HEADER_SIZE) ));
4198 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4201 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4205 NT_STATUS_BUFFER_TOO_SMALL);
4209 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4210 SSVAL(pdata,2,num_file_acls);
4211 SSVAL(pdata,4,num_def_acls);
4212 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4214 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4217 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4220 req, NT_STATUS_INTERNAL_ERROR);
4223 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4225 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4228 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4232 NT_STATUS_INTERNAL_ERROR);
4237 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4240 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4242 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4248 case SMB_QUERY_POSIX_LOCK:
4250 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4252 SMB_BIG_UINT offset;
4254 enum brl_type lock_type;
4256 if (total_data != POSIX_LOCK_DATA_SIZE) {
4258 req, NT_STATUS_INVALID_PARAMETER);
4262 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4263 case POSIX_LOCK_TYPE_READ:
4264 lock_type = READ_LOCK;
4266 case POSIX_LOCK_TYPE_WRITE:
4267 lock_type = WRITE_LOCK;
4269 case POSIX_LOCK_TYPE_UNLOCK:
4271 /* There's no point in asking for an unlock... */
4272 talloc_destroy(data_ctx);
4275 NT_STATUS_INVALID_PARAMETER);
4279 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4280 #if defined(HAVE_LONGLONG)
4281 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4282 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4283 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4284 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4285 #else /* HAVE_LONGLONG */
4286 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4287 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4288 #endif /* HAVE_LONGLONG */
4290 status = query_lock(fsp,
4297 if (ERROR_WAS_LOCK_DENIED(status)) {
4298 /* Here we need to report who has it locked... */
4299 data_size = POSIX_LOCK_DATA_SIZE;
4301 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4302 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4303 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4304 #if defined(HAVE_LONGLONG)
4305 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4306 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4307 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4308 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4309 #else /* HAVE_LONGLONG */
4310 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4311 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4312 #endif /* HAVE_LONGLONG */
4314 } else if (NT_STATUS_IS_OK(status)) {
4315 /* For success we just return a copy of what we sent
4316 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4317 data_size = POSIX_LOCK_DATA_SIZE;
4318 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4319 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4321 reply_nterror(req, status);
4328 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4332 send_trans2_replies_new(req, params, param_size, *ppdata, data_size,
4338 /****************************************************************************
4339 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4341 ****************************************************************************/
4343 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4345 SMB_STRUCT_STAT sbuf1, sbuf2;
4346 pstring last_component_oldname;
4347 pstring last_component_newname;
4348 NTSTATUS status = NT_STATUS_OK;
4353 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4354 if (!NT_STATUS_IS_OK(status)) {
4358 status = check_name(conn, oldname);
4359 if (!NT_STATUS_IS_OK(status)) {
4363 /* source must already exist. */
4364 if (!VALID_STAT(sbuf1)) {
4365 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4368 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4369 if (!NT_STATUS_IS_OK(status)) {
4373 status = check_name(conn, newname);
4374 if (!NT_STATUS_IS_OK(status)) {
4378 /* Disallow if newname already exists. */
4379 if (VALID_STAT(sbuf2)) {
4380 return NT_STATUS_OBJECT_NAME_COLLISION;
4383 /* No links from a directory. */
4384 if (S_ISDIR(sbuf1.st_mode)) {
4385 return NT_STATUS_FILE_IS_A_DIRECTORY;
4388 /* Ensure this is within the share. */
4389 status = check_reduced_name(conn, oldname);
4390 if (!NT_STATUS_IS_OK(status)) {
4394 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4396 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4397 status = map_nt_error_from_unix(errno);
4398 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4399 nt_errstr(status), newname, oldname));
4405 /****************************************************************************
4406 Deal with setting the time from any of the setfilepathinfo functions.
4407 ****************************************************************************/
4409 static NTSTATUS smb_set_file_time(connection_struct *conn,
4412 const SMB_STRUCT_STAT *psbuf,
4413 struct timespec ts[2])
4416 FILE_NOTIFY_CHANGE_LAST_ACCESS
4417 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4420 if (!VALID_STAT(*psbuf)) {
4421 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4424 /* get some defaults (no modifications) if any info is zero or -1. */
4425 if (null_timespec(ts[0])) {
4426 ts[0] = get_atimespec(psbuf);
4427 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4430 if (null_timespec(ts[1])) {
4431 ts[1] = get_mtimespec(psbuf);
4432 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4435 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4436 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4439 * Try and set the times of this file if
4440 * they are different from the current values.
4444 struct timespec mts = get_mtimespec(psbuf);
4445 struct timespec ats = get_atimespec(psbuf);
4446 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4447 return NT_STATUS_OK;
4453 * This was a setfileinfo on an open file.
4454 * NT does this a lot. We also need to
4455 * set the time here, as it can be read by
4456 * FindFirst/FindNext and with the patch for bug #2045
4457 * in smbd/fileio.c it ensures that this timestamp is
4458 * kept sticky even after a write. We save the request
4459 * away and will set it on file close and after a write. JRA.
4462 if (!null_timespec(ts[1])) {
4463 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4464 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4465 fsp_set_pending_modtime(fsp, ts[1]);
4469 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4471 if(file_ntimes(conn, fname, ts)!=0) {
4472 return map_nt_error_from_unix(errno);
4475 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4477 return NT_STATUS_OK;
4480 /****************************************************************************
4481 Deal with setting the dosmode from any of the setfilepathinfo functions.
4482 ****************************************************************************/
4484 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4486 SMB_STRUCT_STAT *psbuf,
4489 if (!VALID_STAT(*psbuf)) {
4490 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4494 if (S_ISDIR(psbuf->st_mode)) {
4501 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4503 /* check the mode isn't different, before changing it */
4504 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4506 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4507 fname, (unsigned int)dosmode ));
4509 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4510 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4511 fname, strerror(errno)));
4512 return map_nt_error_from_unix(errno);
4515 return NT_STATUS_OK;
4518 /****************************************************************************
4519 Deal with setting the size from any of the setfilepathinfo functions.
4520 ****************************************************************************/
4522 static NTSTATUS smb_set_file_size(connection_struct *conn,
4523 struct smb_request *req,
4526 SMB_STRUCT_STAT *psbuf,
4529 NTSTATUS status = NT_STATUS_OK;
4530 files_struct *new_fsp = NULL;
4532 if (!VALID_STAT(*psbuf)) {
4533 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4536 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4538 if (size == get_file_size(*psbuf)) {
4539 return NT_STATUS_OK;
4542 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4543 fname, (double)size ));
4545 if (fsp && fsp->fh->fd != -1) {
4546 /* Handle based call. */
4547 if (vfs_set_filelen(fsp, size) == -1) {
4548 return map_nt_error_from_unix(errno);
4550 return NT_STATUS_OK;
4553 status = open_file_ntcreate(conn, req, fname, psbuf,
4555 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4558 FILE_ATTRIBUTE_NORMAL,
4559 FORCE_OPLOCK_BREAK_TO_NONE,
4562 if (!NT_STATUS_IS_OK(status)) {
4563 /* NB. We check for open_was_deferred in the caller. */
4567 if (vfs_set_filelen(new_fsp, size) == -1) {
4568 status = map_nt_error_from_unix(errno);
4569 close_file(new_fsp,NORMAL_CLOSE);
4573 close_file(new_fsp,NORMAL_CLOSE);
4574 return NT_STATUS_OK;
4577 /****************************************************************************
4578 Deal with SMB_INFO_SET_EA.
4579 ****************************************************************************/
4581 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4587 struct ea_list *ea_list = NULL;
4588 TALLOC_CTX *ctx = NULL;
4589 NTSTATUS status = NT_STATUS_OK;
4591 if (total_data < 10) {
4593 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4594 length. They seem to have no effect. Bug #3212. JRA */
4596 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4597 /* We're done. We only get EA info in this call. */
4598 return NT_STATUS_OK;
4601 return NT_STATUS_INVALID_PARAMETER;
4604 if (IVAL(pdata,0) > total_data) {
4605 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4606 IVAL(pdata,0), (unsigned int)total_data));
4607 return NT_STATUS_INVALID_PARAMETER;
4610 ctx = talloc_init("SMB_INFO_SET_EA");
4612 return NT_STATUS_NO_MEMORY;
4614 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4616 talloc_destroy(ctx);
4617 return NT_STATUS_INVALID_PARAMETER;
4619 status = set_ea(conn, fsp, fname, ea_list);
4620 talloc_destroy(ctx);
4625 /****************************************************************************
4626 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4627 ****************************************************************************/
4629 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4634 SMB_STRUCT_STAT *psbuf)
4636 NTSTATUS status = NT_STATUS_OK;
4637 BOOL delete_on_close;
4640 if (total_data < 1) {
4641 return NT_STATUS_INVALID_PARAMETER;
4645 return NT_STATUS_INVALID_HANDLE;
4648 delete_on_close = (CVAL(pdata,0) ? True : False);
4649 dosmode = dos_mode(conn, fname, psbuf);
4651 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4652 "delete_on_close = %u\n",
4654 (unsigned int)dosmode,
4655 (unsigned int)delete_on_close ));
4657 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4659 if (!NT_STATUS_IS_OK(status)) {
4663 /* The set is across all open files on this dev/inode pair. */
4664 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4665 return NT_STATUS_ACCESS_DENIED;
4667 return NT_STATUS_OK;
4670 /****************************************************************************
4671 Deal with SMB_FILE_POSITION_INFORMATION.
4672 ****************************************************************************/
4674 static NTSTATUS smb_file_position_information(connection_struct *conn,
4679 SMB_BIG_UINT position_information;
4681 if (total_data < 8) {
4682 return NT_STATUS_INVALID_PARAMETER;
4686 /* Ignore on pathname based set. */
4687 return NT_STATUS_OK;
4690 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4691 #ifdef LARGE_SMB_OFF_T
4692 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4693 #else /* LARGE_SMB_OFF_T */
4694 if (IVAL(pdata,4) != 0) {
4695 /* more than 32 bits? */
4696 return NT_STATUS_INVALID_PARAMETER;
4698 #endif /* LARGE_SMB_OFF_T */
4700 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4701 fsp->fsp_name, (double)position_information ));
4702 fsp->fh->position_information = position_information;
4703 return NT_STATUS_OK;
4706 /****************************************************************************
4707 Deal with SMB_FILE_MODE_INFORMATION.
4708 ****************************************************************************/
4710 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4716 if (total_data < 4) {
4717 return NT_STATUS_INVALID_PARAMETER;
4719 mode = IVAL(pdata,0);
4720 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4721 return NT_STATUS_INVALID_PARAMETER;
4723 return NT_STATUS_OK;
4726 /****************************************************************************
4727 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4728 ****************************************************************************/
4730 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4736 pstring link_target;
4737 const char *newname = fname;
4738 NTSTATUS status = NT_STATUS_OK;
4740 /* Set a symbolic link. */
4741 /* Don't allow this if follow links is false. */
4743 if (total_data == 0) {
4744 return NT_STATUS_INVALID_PARAMETER;
4747 if (!lp_symlinks(SNUM(conn))) {
4748 return NT_STATUS_ACCESS_DENIED;
4751 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
4752 sizeof(link_target), total_data, STR_TERMINATE);
4754 /* !widelinks forces the target path to be within the share. */
4755 /* This means we can interpret the target as a pathname. */
4756 if (!lp_widelinks(SNUM(conn))) {
4758 char *last_dirp = NULL;
4760 if (*link_target == '/') {
4761 /* No absolute paths allowed. */
4762 return NT_STATUS_ACCESS_DENIED;
4764 pstrcpy(rel_name, newname);
4765 last_dirp = strrchr_m(rel_name, '/');
4767 last_dirp[1] = '\0';
4769 pstrcpy(rel_name, "./");
4771 pstrcat(rel_name, link_target);
4773 status = check_name(conn, rel_name);
4774 if (!NT_STATUS_IS_OK(status)) {
4779 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4780 newname, link_target ));
4782 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4783 return map_nt_error_from_unix(errno);
4786 return NT_STATUS_OK;
4789 /****************************************************************************
4790 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4791 ****************************************************************************/
4793 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4801 NTSTATUS status = NT_STATUS_OK;
4803 /* Set a hard link. */
4804 if (total_data == 0) {
4805 return NT_STATUS_INVALID_PARAMETER;
4808 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
4809 sizeof(oldname), total_data, STR_TERMINATE, &status);
4810 if (!NT_STATUS_IS_OK(status)) {
4814 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4815 if (!NT_STATUS_IS_OK(status)) {
4819 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4822 return hardlink_internals(conn, oldname, fname);
4825 /****************************************************************************
4826 Deal with SMB_FILE_RENAME_INFORMATION.
4827 ****************************************************************************/
4829 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4830 struct smb_request *req,
4843 BOOL dest_has_wcard = False;
4844 NTSTATUS status = NT_STATUS_OK;
4847 if (total_data < 13) {
4848 return NT_STATUS_INVALID_PARAMETER;
4851 overwrite = (CVAL(pdata,0) ? True : False);
4852 root_fid = IVAL(pdata,4);
4853 len = IVAL(pdata,8);
4855 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4856 return NT_STATUS_INVALID_PARAMETER;
4859 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
4860 sizeof(newname), len, 0, &status,
4862 if (!NT_STATUS_IS_OK(status)) {
4866 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4867 if (!NT_STATUS_IS_OK(status)) {
4871 /* Check the new name has no '/' characters. */
4872 if (strchr_m(newname, '/')) {
4873 return NT_STATUS_NOT_SUPPORTED;
4876 /* Create the base directory. */
4877 pstrcpy(base_name, fname);
4878 p = strrchr_m(base_name, '/');
4882 pstrcpy(base_name, "./");
4884 /* Append the new name. */
4885 pstrcat(base_name, newname);
4888 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4889 fsp->fnum, fsp->fsp_name, base_name ));
4890 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4892 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4894 status = rename_internals(conn, req, fname, base_name, 0,
4895 overwrite, False, dest_has_wcard);
4901 /****************************************************************************
4902 Deal with SMB_SET_POSIX_ACL.
4903 ****************************************************************************/
4905 #if defined(HAVE_POSIX_ACLS)
4906 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4911 SMB_STRUCT_STAT *psbuf)
4913 uint16 posix_acl_version;
4914 uint16 num_file_acls;
4915 uint16 num_def_acls;
4916 BOOL valid_file_acls = True;
4917 BOOL valid_def_acls = True;
4919 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4920 return NT_STATUS_INVALID_PARAMETER;
4922 posix_acl_version = SVAL(pdata,0);
4923 num_file_acls = SVAL(pdata,2);
4924 num_def_acls = SVAL(pdata,4);
4926 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4927 valid_file_acls = False;
4931 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4932 valid_def_acls = False;
4936 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4937 return NT_STATUS_INVALID_PARAMETER;
4940 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4941 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4942 return NT_STATUS_INVALID_PARAMETER;
4945 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4946 fname ? fname : fsp->fsp_name,
4947 (unsigned int)num_file_acls,
4948 (unsigned int)num_def_acls));
4950 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4951 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4952 return map_nt_error_from_unix(errno);
4955 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4956 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4957 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4958 return map_nt_error_from_unix(errno);
4960 return NT_STATUS_OK;
4964 /****************************************************************************
4965 Deal with SMB_SET_POSIX_LOCK.
4966 ****************************************************************************/
4968 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4976 SMB_BIG_UINT offset;
4978 BOOL blocking_lock = False;
4979 enum brl_type lock_type;
4980 NTSTATUS status = NT_STATUS_OK;
4982 if (fsp == NULL || fsp->fh->fd == -1) {
4983 return NT_STATUS_INVALID_HANDLE;
4986 if (total_data != POSIX_LOCK_DATA_SIZE) {
4987 return NT_STATUS_INVALID_PARAMETER;
4990 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4991 case POSIX_LOCK_TYPE_READ:
4992 lock_type = READ_LOCK;
4994 case POSIX_LOCK_TYPE_WRITE:
4995 /* Return the right POSIX-mappable error code for files opened read-only. */
4996 if (!fsp->can_write) {
4997 return NT_STATUS_INVALID_HANDLE;
4999 lock_type = WRITE_LOCK;
5001 case POSIX_LOCK_TYPE_UNLOCK:
5002 lock_type = UNLOCK_LOCK;
5005 return NT_STATUS_INVALID_PARAMETER;
5008 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5009 blocking_lock = False;
5010 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5011 blocking_lock = True;
5013 return NT_STATUS_INVALID_PARAMETER;
5016 if (!lp_blocking_locks(SNUM(conn))) {
5017 blocking_lock = False;
5020 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5021 #if defined(HAVE_LONGLONG)
5022 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5023 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5024 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5025 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5026 #else /* HAVE_LONGLONG */
5027 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5028 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5029 #endif /* HAVE_LONGLONG */
5031 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5032 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5034 (unsigned int)lock_type,
5035 (unsigned int)lock_pid,
5039 if (lock_type == UNLOCK_LOCK) {
5040 status = do_unlock(smbd_messaging_context(),
5047 uint32 block_smbpid;
5049 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5060 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5062 * A blocking lock was requested. Package up
5063 * this smb into a queued request and push it
5064 * onto the blocking lock queue.
5066 if(push_blocking_lock_request(br_lck,
5069 -1, /* infinite timeout. */
5077 TALLOC_FREE(br_lck);
5081 TALLOC_FREE(br_lck);
5087 /****************************************************************************
5088 Deal with SMB_INFO_STANDARD.
5089 ****************************************************************************/
5091 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5096 const SMB_STRUCT_STAT *psbuf)
5098 struct timespec ts[2];
5100 if (total_data < 12) {
5101 return NT_STATUS_INVALID_PARAMETER;
5105 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5107 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5109 DEBUG(10,("smb_set_info_standard: file %s\n",
5110 fname ? fname : fsp->fsp_name ));
5112 return smb_set_file_time(conn,
5119 /****************************************************************************
5120 Deal with SMB_SET_FILE_BASIC_INFO.
5121 ****************************************************************************/
5123 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5128 SMB_STRUCT_STAT *psbuf)
5130 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5131 struct timespec write_time;
5132 struct timespec changed_time;
5134 struct timespec ts[2];
5135 NTSTATUS status = NT_STATUS_OK;
5137 if (total_data < 36) {
5138 return NT_STATUS_INVALID_PARAMETER;
5141 /* Set the attributes */
5142 dosmode = IVAL(pdata,32);
5143 status = smb_set_file_dosmode(conn,
5147 if (!NT_STATUS_IS_OK(status)) {
5151 /* Ignore create time at offset pdata. */
5154 ts[0] = interpret_long_date(pdata+8);
5156 write_time = interpret_long_date(pdata+16);
5157 changed_time = interpret_long_date(pdata+24);
5160 ts[1] = timespec_min(&write_time, &changed_time);
5162 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5166 /* Prefer a defined time to an undefined one. */
5167 if (null_timespec(ts[1])) {
5168 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5171 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5172 fname ? fname : fsp->fsp_name ));
5174 return smb_set_file_time(conn,
5181 /****************************************************************************
5182 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5183 ****************************************************************************/
5185 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5186 struct smb_request *req,
5191 SMB_STRUCT_STAT *psbuf)
5193 SMB_BIG_UINT allocation_size = 0;
5194 NTSTATUS status = NT_STATUS_OK;
5195 files_struct *new_fsp = NULL;
5197 if (!VALID_STAT(*psbuf)) {
5198 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5201 if (total_data < 8) {
5202 return NT_STATUS_INVALID_PARAMETER;
5205 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5206 #ifdef LARGE_SMB_OFF_T
5207 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5208 #else /* LARGE_SMB_OFF_T */
5209 if (IVAL(pdata,4) != 0) {
5210 /* more than 32 bits? */
5211 return NT_STATUS_INVALID_PARAMETER;
5213 #endif /* LARGE_SMB_OFF_T */
5215 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5216 fname, (double)allocation_size ));
5218 if (allocation_size) {
5219 allocation_size = smb_roundup(conn, allocation_size);
5222 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5223 fname, (double)allocation_size ));
5225 if (fsp && fsp->fh->fd != -1) {
5226 /* Open file handle. */
5227 /* Only change if needed. */
5228 if (allocation_size != get_file_size(*psbuf)) {
5229 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5230 return map_nt_error_from_unix(errno);
5233 /* But always update the time. */
5234 if (null_timespec(fsp->pending_modtime)) {
5236 * This is equivalent to a write. Ensure it's seen immediately
5237 * if there are no pending writes.
5239 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5241 return NT_STATUS_OK;
5244 /* Pathname or stat or directory file. */
5246 status = open_file_ntcreate(conn, req, fname, psbuf,
5248 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5251 FILE_ATTRIBUTE_NORMAL,
5252 FORCE_OPLOCK_BREAK_TO_NONE,
5255 if (!NT_STATUS_IS_OK(status)) {
5256 /* NB. We check for open_was_deferred in the caller. */
5260 /* Only change if needed. */
5261 if (allocation_size != get_file_size(*psbuf)) {
5262 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5263 status = map_nt_error_from_unix(errno);
5264 close_file(new_fsp,NORMAL_CLOSE);
5269 /* Changing the allocation size should set the last mod time. */
5270 /* Don't need to call set_filetime as this will be flushed on
5273 fsp_set_pending_modtime(new_fsp, timespec_current());
5275 close_file(new_fsp,NORMAL_CLOSE);
5276 return NT_STATUS_OK;
5279 /****************************************************************************
5280 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5281 ****************************************************************************/
5283 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5284 struct smb_request *req,
5289 SMB_STRUCT_STAT *psbuf)
5293 if (total_data < 8) {
5294 return NT_STATUS_INVALID_PARAMETER;
5297 size = IVAL(pdata,0);
5298 #ifdef LARGE_SMB_OFF_T
5299 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5300 #else /* LARGE_SMB_OFF_T */
5301 if (IVAL(pdata,4) != 0) {
5302 /* more than 32 bits? */
5303 return NT_STATUS_INVALID_PARAMETER;
5305 #endif /* LARGE_SMB_OFF_T */
5306 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5307 "file %s to %.0f\n", fname, (double)size ));
5309 return smb_set_file_size(conn, req,
5316 /****************************************************************************
5317 Allow a UNIX info mknod.
5318 ****************************************************************************/
5320 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5324 SMB_STRUCT_STAT *psbuf)
5326 uint32 file_type = IVAL(pdata,56);
5327 #if defined(HAVE_MAKEDEV)
5328 uint32 dev_major = IVAL(pdata,60);
5329 uint32 dev_minor = IVAL(pdata,68);
5331 SMB_DEV_T dev = (SMB_DEV_T)0;
5332 uint32 raw_unixmode = IVAL(pdata,84);
5336 if (total_data < 100) {
5337 return NT_STATUS_INVALID_PARAMETER;
5340 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5341 if (!NT_STATUS_IS_OK(status)) {
5345 #if defined(HAVE_MAKEDEV)
5346 dev = makedev(dev_major, dev_minor);
5349 switch (file_type) {
5350 #if defined(S_IFIFO)
5351 case UNIX_TYPE_FIFO:
5352 unixmode |= S_IFIFO;
5355 #if defined(S_IFSOCK)
5356 case UNIX_TYPE_SOCKET:
5357 unixmode |= S_IFSOCK;
5360 #if defined(S_IFCHR)
5361 case UNIX_TYPE_CHARDEV:
5362 unixmode |= S_IFCHR;
5365 #if defined(S_IFBLK)
5366 case UNIX_TYPE_BLKDEV:
5367 unixmode |= S_IFBLK;
5371 return NT_STATUS_INVALID_PARAMETER;
5374 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5375 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5377 /* Ok - do the mknod. */
5378 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5379 return map_nt_error_from_unix(errno);
5382 /* If any of the other "set" calls fail we
5383 * don't want to end up with a half-constructed mknod.
5386 if (lp_inherit_perms(SNUM(conn))) {
5388 conn, parent_dirname(fname),
5392 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5393 status = map_nt_error_from_unix(errno);
5394 SMB_VFS_UNLINK(conn,fname);
5397 return NT_STATUS_OK;
5400 /****************************************************************************
5401 Deal with SMB_SET_FILE_UNIX_BASIC.
5402 ****************************************************************************/
5404 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5405 struct smb_request *req,
5410 SMB_STRUCT_STAT *psbuf)
5412 struct timespec ts[2];
5413 uint32 raw_unixmode;
5416 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5417 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5418 NTSTATUS status = NT_STATUS_OK;
5419 BOOL delete_on_fail = False;
5420 enum perm_type ptype;
5422 if (total_data < 100) {
5423 return NT_STATUS_INVALID_PARAMETER;
5426 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5427 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5428 size=IVAL(pdata,0); /* first 8 Bytes are size */
5429 #ifdef LARGE_SMB_OFF_T
5430 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5431 #else /* LARGE_SMB_OFF_T */
5432 if (IVAL(pdata,4) != 0) {
5433 /* more than 32 bits? */
5434 return NT_STATUS_INVALID_PARAMETER;
5436 #endif /* LARGE_SMB_OFF_T */
5439 ts[0] = interpret_long_date(pdata+24); /* access_time */
5440 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5441 set_owner = (uid_t)IVAL(pdata,40);
5442 set_grp = (gid_t)IVAL(pdata,48);
5443 raw_unixmode = IVAL(pdata,84);
5445 if (VALID_STAT(*psbuf)) {
5446 if (S_ISDIR(psbuf->st_mode)) {
5447 ptype = PERM_EXISTING_DIR;
5449 ptype = PERM_EXISTING_FILE;
5452 ptype = PERM_NEW_FILE;
5455 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5456 if (!NT_STATUS_IS_OK(status)) {
5460 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5461 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5462 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5464 if (!VALID_STAT(*psbuf)) {
5466 * The only valid use of this is to create character and block
5467 * devices, and named pipes. This is deprecated (IMHO) and
5468 * a new info level should be used for mknod. JRA.
5471 status = smb_unix_mknod(conn,
5476 if (!NT_STATUS_IS_OK(status)) {
5480 /* Ensure we don't try and change anything else. */
5481 raw_unixmode = SMB_MODE_NO_CHANGE;
5482 size = get_file_size(*psbuf);
5483 ts[0] = get_atimespec(psbuf);
5484 ts[1] = get_mtimespec(psbuf);
5486 * We continue here as we might want to change the
5489 delete_on_fail = True;
5493 /* Horrible backwards compatibility hack as an old server bug
5494 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5498 size = get_file_size(*psbuf);
5503 * Deal with the UNIX specific mode set.
5506 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5507 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5508 (unsigned int)unixmode, fname ));
5509 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5510 return map_nt_error_from_unix(errno);
5515 * Deal with the UNIX specific uid set.
5518 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5521 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5522 (unsigned int)set_owner, fname ));
5524 if (S_ISLNK(psbuf->st_mode)) {
5525 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5527 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5531 status = map_nt_error_from_unix(errno);
5532 if (delete_on_fail) {
5533 SMB_VFS_UNLINK(conn,fname);
5540 * Deal with the UNIX specific gid set.
5543 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5544 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5545 (unsigned int)set_owner, fname ));
5546 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5547 status = map_nt_error_from_unix(errno);
5548 if (delete_on_fail) {
5549 SMB_VFS_UNLINK(conn,fname);
5555 /* Deal with any size changes. */
5557 status = smb_set_file_size(conn, req,
5562 if (!NT_STATUS_IS_OK(status)) {
5566 /* Deal with any time changes. */
5568 return smb_set_file_time(conn,
5575 /****************************************************************************
5576 Deal with SMB_SET_FILE_UNIX_INFO2.
5577 ****************************************************************************/
5579 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5580 struct smb_request *req,
5585 SMB_STRUCT_STAT *psbuf)
5591 if (total_data < 116) {
5592 return NT_STATUS_INVALID_PARAMETER;
5595 /* Start by setting all the fields that are common between UNIX_BASIC
5598 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5600 if (!NT_STATUS_IS_OK(status)) {
5604 smb_fflags = IVAL(pdata, 108);
5605 smb_fmask = IVAL(pdata, 112);
5607 /* NB: We should only attempt to alter the file flags if the client
5608 * sends a non-zero mask.
5610 if (smb_fmask != 0) {
5611 int stat_fflags = 0;
5613 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5615 /* Client asked to alter a flag we don't understand. */
5616 return NT_STATUS_INVALID_PARAMETER;
5619 if (fsp && fsp->fh->fd != -1) {
5620 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5621 return NT_STATUS_NOT_SUPPORTED;
5623 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5624 return map_nt_error_from_unix(errno);
5629 /* XXX: need to add support for changing the create_time here. You
5630 * can do this for paths on Darwin with setattrlist(2). The right way
5631 * to hook this up is probably by extending the VFS utimes interface.
5634 return NT_STATUS_OK;
5637 /****************************************************************************
5638 Create a directory with POSIX semantics.
5639 ****************************************************************************/
5641 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5642 struct smb_request *req,
5646 SMB_STRUCT_STAT *psbuf,
5647 int *pdata_return_size)
5649 NTSTATUS status = NT_STATUS_OK;
5650 uint32 raw_unixmode = 0;
5651 uint32 mod_unixmode = 0;
5652 mode_t unixmode = (mode_t)0;
5653 files_struct *fsp = NULL;
5654 uint16 info_level_return = 0;
5656 char *pdata = *ppdata;
5658 if (total_data < 18) {
5659 return NT_STATUS_INVALID_PARAMETER;
5662 raw_unixmode = IVAL(pdata,8);
5663 /* Next 4 bytes are not yet defined. */
5665 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5666 if (!NT_STATUS_IS_OK(status)) {
5670 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5672 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5673 fname, (unsigned int)unixmode ));
5675 status = open_directory(conn, req,
5678 FILE_READ_ATTRIBUTES, /* Just a stat open */
5679 FILE_SHARE_NONE, /* Ignored for stat opens */
5686 if (NT_STATUS_IS_OK(status)) {
5687 close_file(fsp, NORMAL_CLOSE);
5690 info_level_return = SVAL(pdata,16);
5692 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5693 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5694 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5695 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5697 *pdata_return_size = 12;
5700 /* Realloc the data size */
5701 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5702 if (*ppdata == NULL) {
5703 *pdata_return_size = 0;
5704 return NT_STATUS_NO_MEMORY;
5708 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5709 SSVAL(pdata,2,0); /* No fnum. */
5710 SIVAL(pdata,4,info); /* Was directory created. */
5712 switch (info_level_return) {
5713 case SMB_QUERY_FILE_UNIX_BASIC:
5714 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5715 SSVAL(pdata,10,0); /* Padding. */
5716 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5718 case SMB_QUERY_FILE_UNIX_INFO2:
5719 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5720 SSVAL(pdata,10,0); /* Padding. */
5721 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5724 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5725 SSVAL(pdata,10,0); /* Padding. */
5732 /****************************************************************************
5733 Open/Create a file with POSIX semantics.
5734 ****************************************************************************/
5736 static NTSTATUS smb_posix_open(connection_struct *conn,
5737 struct smb_request *req,
5741 SMB_STRUCT_STAT *psbuf,
5742 int *pdata_return_size)
5744 BOOL extended_oplock_granted = False;
5745 char *pdata = *ppdata;
5747 uint32 wire_open_mode = 0;
5748 uint32 raw_unixmode = 0;
5749 uint32 mod_unixmode = 0;
5750 uint32 create_disp = 0;
5751 uint32 access_mask = 0;
5752 uint32 create_options = 0;
5753 NTSTATUS status = NT_STATUS_OK;
5754 mode_t unixmode = (mode_t)0;
5755 files_struct *fsp = NULL;
5756 int oplock_request = 0;
5758 uint16 info_level_return = 0;
5760 if (total_data < 18) {
5761 return NT_STATUS_INVALID_PARAMETER;
5764 flags = IVAL(pdata,0);
5765 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5766 if (oplock_request) {
5767 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5770 wire_open_mode = IVAL(pdata,4);
5772 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5773 return smb_posix_mkdir(conn, req,
5781 switch (wire_open_mode & SMB_ACCMODE) {
5783 access_mask = FILE_READ_DATA;
5786 access_mask = FILE_WRITE_DATA;
5789 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5792 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5793 (unsigned int)wire_open_mode ));
5794 return NT_STATUS_INVALID_PARAMETER;
5797 wire_open_mode &= ~SMB_ACCMODE;
5799 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5800 create_disp = FILE_CREATE;
5801 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5802 create_disp = FILE_OVERWRITE_IF;
5803 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5804 create_disp = FILE_OPEN_IF;
5806 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5807 (unsigned int)wire_open_mode ));
5808 return NT_STATUS_INVALID_PARAMETER;
5811 raw_unixmode = IVAL(pdata,8);
5812 /* Next 4 bytes are not yet defined. */
5814 status = unix_perms_from_wire(conn,
5817 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5820 if (!NT_STATUS_IS_OK(status)) {
5824 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5826 if (wire_open_mode & SMB_O_SYNC) {
5827 create_options |= FILE_WRITE_THROUGH;
5829 if (wire_open_mode & SMB_O_APPEND) {
5830 access_mask |= FILE_APPEND_DATA;
5832 if (wire_open_mode & SMB_O_DIRECT) {
5833 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5836 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5838 (unsigned int)wire_open_mode,
5839 (unsigned int)unixmode ));
5841 status = open_file_ntcreate(conn, req,
5845 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5847 0, /* no create options yet. */
5853 if (!NT_STATUS_IS_OK(status)) {
5857 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5858 extended_oplock_granted = True;
5861 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5862 extended_oplock_granted = True;
5865 info_level_return = SVAL(pdata,16);
5867 /* Allocate the correct return size. */
5869 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5870 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5871 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5872 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5874 *pdata_return_size = 12;
5877 /* Realloc the data size */
5878 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5879 if (*ppdata == NULL) {
5880 close_file(fsp,ERROR_CLOSE);
5881 *pdata_return_size = 0;
5882 return NT_STATUS_NO_MEMORY;
5886 if (extended_oplock_granted) {
5887 if (flags & REQUEST_BATCH_OPLOCK) {
5888 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5890 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5892 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5893 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5895 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5898 SSVAL(pdata,2,fsp->fnum);
5899 SIVAL(pdata,4,info); /* Was file created etc. */
5901 switch (info_level_return) {
5902 case SMB_QUERY_FILE_UNIX_BASIC:
5903 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5904 SSVAL(pdata,10,0); /* padding. */
5905 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5907 case SMB_QUERY_FILE_UNIX_INFO2:
5908 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5909 SSVAL(pdata,10,0); /* padding. */
5910 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5913 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5914 SSVAL(pdata,10,0); /* padding. */
5917 return NT_STATUS_OK;
5920 /****************************************************************************
5921 Delete a file with POSIX semantics.
5922 ****************************************************************************/
5924 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5925 struct smb_request *req,
5929 SMB_STRUCT_STAT *psbuf)
5931 NTSTATUS status = NT_STATUS_OK;
5932 files_struct *fsp = NULL;
5937 struct share_mode_lock *lck = NULL;
5939 if (total_data < 2) {
5940 return NT_STATUS_INVALID_PARAMETER;
5943 flags = SVAL(pdata,0);
5945 if (!VALID_STAT(*psbuf)) {
5946 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5949 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5950 !VALID_STAT_OF_DIR(*psbuf)) {
5951 return NT_STATUS_NOT_A_DIRECTORY;
5954 DEBUG(10,("smb_posix_unlink: %s %s\n",
5955 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5958 if (VALID_STAT_OF_DIR(*psbuf)) {
5959 status = open_directory(conn, req,
5963 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5966 FILE_FLAG_POSIX_SEMANTICS|0777,
5971 status = open_file_ntcreate(conn, req,
5975 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5978 FILE_FLAG_POSIX_SEMANTICS|0777,
5979 0, /* No oplock, but break existing ones. */
5984 if (!NT_STATUS_IS_OK(status)) {
5989 * Don't lie to client. If we can't really delete due to
5990 * non-POSIX opens return SHARING_VIOLATION.
5993 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5995 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5996 "lock for file %s\n", fsp->fsp_name));
5997 close_file(fsp, NORMAL_CLOSE);
5998 return NT_STATUS_INVALID_PARAMETER;
6002 * See if others still have the file open. If this is the case, then
6003 * don't delete. If all opens are POSIX delete we can set the delete
6004 * on close disposition.
6006 for (i=0; i<lck->num_share_modes; i++) {
6007 struct share_mode_entry *e = &lck->share_modes[i];
6008 if (is_valid_share_mode_entry(e)) {
6009 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6012 /* Fail with sharing violation. */
6013 close_file(fsp, NORMAL_CLOSE);
6015 return NT_STATUS_SHARING_VIOLATION;
6020 * Set the delete on close.
6022 status = smb_set_file_disposition_info(conn,
6029 if (!NT_STATUS_IS_OK(status)) {
6030 close_file(fsp, NORMAL_CLOSE);
6035 return close_file(fsp, NORMAL_CLOSE);
6038 /****************************************************************************
6039 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6040 ****************************************************************************/
6042 static int call_trans2setfilepathinfo(connection_struct *conn,
6043 struct smb_request *req,
6044 char *inbuf, char *outbuf, int length,
6046 unsigned int tran_call,
6047 char **pparams, int total_params, char **ppdata, int total_data,
6048 unsigned int max_data_bytes)
6050 char *params = *pparams;
6051 char *pdata = *ppdata;
6053 SMB_STRUCT_STAT sbuf;
6055 files_struct *fsp = NULL;
6056 NTSTATUS status = NT_STATUS_OK;
6057 int data_return_size = 0;
6060 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6065 if (tran_call == TRANSACT2_SETFILEINFO) {
6066 if (total_params < 4) {
6067 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6070 fsp = file_fsp(SVAL(params,0));
6071 info_level = SVAL(params,2);
6073 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
6075 * This is actually a SETFILEINFO on a directory
6076 * handle (returned from an NT SMB). NT5.0 seems
6077 * to do this call. JRA.
6079 pstrcpy(fname, fsp->fsp_name);
6080 if (INFO_LEVEL_IS_UNIX(info_level)) {
6081 /* Always do lstat for UNIX calls. */
6082 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6083 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6084 return UNIXERROR(ERRDOS,ERRbadpath);
6087 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6088 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6089 return UNIXERROR(ERRDOS,ERRbadpath);
6092 } else if (fsp && fsp->print_file) {
6094 * Doing a DELETE_ON_CLOSE should cancel a print job.
6096 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6097 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6099 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6102 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6105 return (UNIXERROR(ERRDOS,ERRbadpath));
6108 * Original code - this is an open file.
6110 CHECK_FSP(fsp,conn);
6112 pstrcpy(fname, fsp->fsp_name);
6114 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6115 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6116 return(UNIXERROR(ERRDOS,ERRbadfid));
6121 if (total_params < 7) {
6122 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6125 info_level = SVAL(params,0);
6126 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
6127 sizeof(fname), total_params - 6, STR_TERMINATE,
6129 if (!NT_STATUS_IS_OK(status)) {
6130 return ERROR_NT(status);
6133 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
6134 if (!NT_STATUS_IS_OK(status)) {
6135 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6136 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6138 return ERROR_NT(status);
6141 status = unix_convert(conn, fname, False, NULL, &sbuf);
6142 if (!NT_STATUS_IS_OK(status)) {
6143 return ERROR_NT(status);
6146 status = check_name(conn, fname);
6147 if (!NT_STATUS_IS_OK(status)) {
6148 return ERROR_NT(status);
6151 if (INFO_LEVEL_IS_UNIX(info_level)) {
6153 * For CIFS UNIX extensions the target name may not exist.
6156 /* Always do lstat for UNIX calls. */
6157 SMB_VFS_LSTAT(conn,fname,&sbuf);
6159 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6160 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6161 return UNIXERROR(ERRDOS,ERRbadpath);
6165 if (!CAN_WRITE(conn)) {
6166 return ERROR_DOS(ERRSRV,ERRaccess);
6169 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6170 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6173 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6174 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6176 /* Realloc the parameter size */
6177 *pparams = (char *)SMB_REALLOC(*pparams,2);
6178 if (*pparams == NULL) {
6179 return ERROR_NT(NT_STATUS_NO_MEMORY);
6185 if (fsp && !null_timespec(fsp->pending_modtime)) {
6186 /* the pending modtime overrides the current modtime */
6187 set_mtimespec(&sbuf, fsp->pending_modtime);
6190 switch (info_level) {
6192 case SMB_INFO_STANDARD:
6194 status = smb_set_info_standard(conn,
6203 case SMB_INFO_SET_EA:
6205 status = smb_info_set_ea(conn,
6213 case SMB_SET_FILE_BASIC_INFO:
6214 case SMB_FILE_BASIC_INFORMATION:
6216 status = smb_set_file_basic_info(conn,
6225 case SMB_FILE_ALLOCATION_INFORMATION:
6226 case SMB_SET_FILE_ALLOCATION_INFO:
6228 status = smb_set_file_allocation_info(conn, req,
6237 case SMB_FILE_END_OF_FILE_INFORMATION:
6238 case SMB_SET_FILE_END_OF_FILE_INFO:
6240 status = smb_set_file_end_of_file_info(conn, req,
6249 case SMB_FILE_DISPOSITION_INFORMATION:
6250 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6253 /* JRA - We used to just ignore this on a path ?
6254 * Shouldn't this be invalid level on a pathname
6257 if (tran_call != TRANSACT2_SETFILEINFO) {
6258 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6261 status = smb_set_file_disposition_info(conn,
6270 case SMB_FILE_POSITION_INFORMATION:
6272 status = smb_file_position_information(conn,
6279 /* From tridge Samba4 :
6280 * MODE_INFORMATION in setfileinfo (I have no
6281 * idea what "mode information" on a file is - it takes a value of 0,
6282 * 2, 4 or 6. What could it be?).
6285 case SMB_FILE_MODE_INFORMATION:
6287 status = smb_file_mode_information(conn,
6294 * CIFS UNIX extensions.
6297 case SMB_SET_FILE_UNIX_BASIC:
6299 status = smb_set_file_unix_basic(conn, req,
6308 case SMB_SET_FILE_UNIX_INFO2:
6310 status = smb_set_file_unix_info2(conn, req,
6319 case SMB_SET_FILE_UNIX_LINK:
6321 if (tran_call != TRANSACT2_SETPATHINFO) {
6322 /* We must have a pathname for this. */
6323 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6325 status = smb_set_file_unix_link(conn,
6333 case SMB_SET_FILE_UNIX_HLINK:
6335 if (tran_call != TRANSACT2_SETPATHINFO) {
6336 /* We must have a pathname for this. */
6337 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6339 status = smb_set_file_unix_hlink(conn,
6348 case SMB_FILE_RENAME_INFORMATION:
6350 status = smb_file_rename_information(conn, req,
6360 #if defined(HAVE_POSIX_ACLS)
6361 case SMB_SET_POSIX_ACL:
6363 status = smb_set_posix_acl(conn,
6373 case SMB_SET_POSIX_LOCK:
6375 if (tran_call != TRANSACT2_SETFILEINFO) {
6376 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6378 status = smb_set_posix_lock(conn,
6387 case SMB_POSIX_PATH_OPEN:
6389 if (tran_call != TRANSACT2_SETPATHINFO) {
6390 /* We must have a pathname for this. */
6391 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6394 status = smb_posix_open(conn, req,
6403 case SMB_POSIX_PATH_UNLINK:
6405 if (tran_call != TRANSACT2_SETPATHINFO) {
6406 /* We must have a pathname for this. */
6407 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6410 status = smb_posix_unlink(conn, req,
6419 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6423 if (!NT_STATUS_IS_OK(status)) {
6424 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6425 /* We have re-scheduled this call. */
6428 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6429 /* We have re-scheduled this call. */
6432 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6433 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6435 return ERROR_NT(status);
6439 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6444 /****************************************************************************
6445 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6446 ****************************************************************************/
6448 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6449 char **pparams, int total_params,
6450 char **ppdata, int total_data,
6451 unsigned int max_data_bytes)
6453 char *params = *pparams;
6454 char *pdata = *ppdata;
6456 SMB_STRUCT_STAT sbuf;
6457 NTSTATUS status = NT_STATUS_OK;
6458 struct ea_list *ea_list = NULL;
6460 if (!CAN_WRITE(conn)) {
6461 reply_doserror(req, ERRSRV, ERRaccess);
6465 if (total_params < 5) {
6466 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6470 srvstr_get_path(params, req->flags2, directory, ¶ms[4],
6471 sizeof(directory), total_params - 4, STR_TERMINATE,
6473 if (!NT_STATUS_IS_OK(status)) {
6474 reply_nterror(req, status);
6478 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6480 status = unix_convert(conn, directory, False, NULL, &sbuf);
6481 if (!NT_STATUS_IS_OK(status)) {
6482 reply_nterror(req, status);
6486 status = check_name(conn, directory);
6487 if (!NT_STATUS_IS_OK(status)) {
6488 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6489 reply_nterror(req, status);
6493 /* Any data in this call is an EA list. */
6494 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6495 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6500 * OS/2 workplace shell seems to send SET_EA requests of "null"
6501 * length (4 bytes containing IVAL 4).
6502 * They seem to have no effect. Bug #3212. JRA.
6505 if (total_data != 4) {
6506 if (total_data < 10) {
6507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6511 if (IVAL(pdata,0) > total_data) {
6512 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6513 IVAL(pdata,0), (unsigned int)total_data));
6514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6518 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6521 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6524 } else if (IVAL(pdata,0) != 4) {
6525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6529 status = create_directory(conn, directory);
6531 if (!NT_STATUS_IS_OK(status)) {
6532 reply_nterror(req, status);
6536 /* Try and set any given EA. */
6538 status = set_ea(conn, NULL, directory, ea_list);
6539 if (!NT_STATUS_IS_OK(status)) {
6540 reply_nterror(req, status);
6545 /* Realloc the parameter and data sizes */
6546 *pparams = (char *)SMB_REALLOC(*pparams,2);
6547 if(*pparams == NULL) {
6548 reply_nterror(req, NT_STATUS_NO_MEMORY);
6555 send_trans2_replies_new(req, params, 2, *ppdata, 0, max_data_bytes);
6560 /****************************************************************************
6561 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6562 We don't actually do this - we just send a null response.
6563 ****************************************************************************/
6565 static void call_trans2findnotifyfirst(connection_struct *conn,
6566 struct smb_request *req,
6567 char **pparams, int total_params,
6568 char **ppdata, int total_data,
6569 unsigned int max_data_bytes)
6571 static uint16 fnf_handle = 257;
6572 char *params = *pparams;
6575 if (total_params < 6) {
6576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6580 info_level = SVAL(params,4);
6581 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6583 switch (info_level) {
6588 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6592 /* Realloc the parameter and data sizes */
6593 *pparams = (char *)SMB_REALLOC(*pparams,6);
6594 if (*pparams == NULL) {
6595 reply_nterror(req, NT_STATUS_NO_MEMORY);
6600 SSVAL(params,0,fnf_handle);
6601 SSVAL(params,2,0); /* No changes */
6602 SSVAL(params,4,0); /* No EA errors */
6609 send_trans2_replies_new(req, params, 6, *ppdata, 0, max_data_bytes);
6614 /****************************************************************************
6615 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6616 changes). Currently this does nothing.
6617 ****************************************************************************/
6619 static void call_trans2findnotifynext(connection_struct *conn,
6620 struct smb_request *req,
6621 char **pparams, int total_params,
6622 char **ppdata, int total_data,
6623 unsigned int max_data_bytes)
6625 char *params = *pparams;
6627 DEBUG(3,("call_trans2findnotifynext\n"));
6629 /* Realloc the parameter and data sizes */
6630 *pparams = (char *)SMB_REALLOC(*pparams,4);
6631 if (*pparams == NULL) {
6632 reply_nterror(req, NT_STATUS_NO_MEMORY);
6637 SSVAL(params,0,0); /* No changes */
6638 SSVAL(params,2,0); /* No EA errors */
6640 send_trans2_replies_new(req, params, 4, *ppdata, 0, max_data_bytes);
6645 /****************************************************************************
6646 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6647 ****************************************************************************/
6649 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6650 char **pparams, int total_params, char **ppdata, int total_data,
6651 unsigned int max_data_bytes)
6653 char *params = *pparams;
6656 int max_referral_level;
6657 NTSTATUS status = NT_STATUS_OK;
6659 DEBUG(10,("call_trans2getdfsreferral\n"));
6661 if (total_params < 3) {
6662 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6665 max_referral_level = SVAL(params,0);
6667 if(!lp_host_msdfs())
6668 return ERROR_DOS(ERRDOS,ERRbadfunc);
6670 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2],
6671 sizeof(pathname), total_params - 2, STR_TERMINATE);
6672 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6673 return ERROR_NT(status);
6675 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6676 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6681 #define LMCAT_SPL 0x53
6682 #define LMFUNC_GETJOBID 0x60
6684 /****************************************************************************
6685 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6686 ****************************************************************************/
6688 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6689 char **pparams, int total_params, char **ppdata, int total_data,
6690 unsigned int max_data_bytes)
6692 char *pdata = *ppdata;
6693 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv15));
6695 /* check for an invalid fid before proceeding */
6698 return(ERROR_DOS(ERRDOS,ERRbadfid));
6700 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6701 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6702 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6703 if (*ppdata == NULL) {
6704 return ERROR_NT(NT_STATUS_NO_MEMORY);
6708 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6709 CAN ACCEPT THIS IN UNICODE. JRA. */
6711 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6712 srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata + 2,
6713 global_myname(), 15,
6714 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6715 srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata+18,
6716 lp_servicename(SNUM(conn)), 13,
6717 STR_ASCII|STR_TERMINATE); /* Service name */
6718 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6721 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6722 return ERROR_DOS(ERRSRV,ERRerror);
6726 /****************************************************************************
6727 Reply to a SMBfindclose (stop trans2 directory search).
6728 ****************************************************************************/
6730 int reply_findclose(connection_struct *conn,
6731 char *inbuf,char *outbuf,int length,int bufsize)
6734 int dptr_num=SVALS(inbuf,smb_vwv0);
6735 START_PROFILE(SMBfindclose);
6737 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6739 dptr_close(&dptr_num);
6741 outsize = set_message(inbuf, outbuf,0,0,False);
6743 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6745 END_PROFILE(SMBfindclose);
6749 /****************************************************************************
6750 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6751 ****************************************************************************/
6753 int reply_findnclose(connection_struct *conn,
6754 char *inbuf,char *outbuf,int length,int bufsize)
6758 START_PROFILE(SMBfindnclose);
6760 dptr_num = SVAL(inbuf,smb_vwv0);
6762 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6764 /* We never give out valid handles for a
6765 findnotifyfirst - so any dptr_num is ok here.
6768 outsize = set_message(inbuf, outbuf,0,0,False);
6770 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6772 END_PROFILE(SMBfindnclose);
6776 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6777 struct trans_state *state,
6778 char *inbuf, char *outbuf, int size, int bufsize)
6782 if (Protocol >= PROTOCOL_NT1) {
6783 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6786 /* Now we must call the relevant TRANS2 function */
6787 switch(state->call) {
6788 case TRANSACT2_OPEN:
6790 START_PROFILE(Trans2_open);
6791 call_trans2open(conn, req,
6792 &state->param, state->total_param,
6793 &state->data, state->total_data,
6794 state->max_data_return);
6795 END_PROFILE(Trans2_open);
6799 case TRANSACT2_FINDFIRST:
6801 START_PROFILE(Trans2_findfirst);
6802 call_trans2findfirst(conn, req,
6803 &state->param, state->total_param,
6804 &state->data, state->total_data,
6805 state->max_data_return);
6806 END_PROFILE(Trans2_findfirst);
6810 case TRANSACT2_FINDNEXT:
6812 START_PROFILE(Trans2_findnext);
6813 call_trans2findnext(conn, req,
6814 &state->param, state->total_param,
6815 &state->data, state->total_data,
6816 state->max_data_return);
6817 END_PROFILE(Trans2_findnext);
6821 case TRANSACT2_QFSINFO:
6823 START_PROFILE(Trans2_qfsinfo);
6824 outsize = call_trans2qfsinfo(
6825 conn, inbuf, outbuf, size, bufsize,
6826 &state->param, state->total_param,
6827 &state->data, state->total_data,
6828 state->max_data_return);
6829 END_PROFILE(Trans2_qfsinfo);
6833 case TRANSACT2_SETFSINFO:
6835 START_PROFILE(Trans2_setfsinfo);
6836 outsize = call_trans2setfsinfo(
6837 conn, inbuf, outbuf, size, bufsize,
6838 &state->param, state->total_param,
6839 &state->data, state->total_data,
6840 state->max_data_return);
6841 END_PROFILE(Trans2_setfsinfo);
6845 case TRANSACT2_QPATHINFO:
6846 case TRANSACT2_QFILEINFO:
6848 START_PROFILE(Trans2_qpathinfo);
6849 call_trans2qfilepathinfo(conn, req, state->call,
6850 &state->param, state->total_param,
6851 &state->data, state->total_data,
6852 state->max_data_return);
6853 END_PROFILE(Trans2_qpathinfo);
6857 case TRANSACT2_SETPATHINFO:
6858 case TRANSACT2_SETFILEINFO:
6860 START_PROFILE(Trans2_setpathinfo);
6861 outsize = call_trans2setfilepathinfo(
6862 conn, req, inbuf, outbuf, size, bufsize, state->call,
6863 &state->param, state->total_param,
6864 &state->data, state->total_data,
6865 state->max_data_return);
6866 END_PROFILE(Trans2_setpathinfo);
6870 case TRANSACT2_FINDNOTIFYFIRST:
6872 START_PROFILE(Trans2_findnotifyfirst);
6873 call_trans2findnotifyfirst(conn, req,
6874 &state->param, state->total_param,
6875 &state->data, state->total_data,
6876 state->max_data_return);
6877 END_PROFILE(Trans2_findnotifyfirst);
6881 case TRANSACT2_FINDNOTIFYNEXT:
6883 START_PROFILE(Trans2_findnotifynext);
6884 call_trans2findnotifynext(conn, req,
6885 &state->param, state->total_param,
6886 &state->data, state->total_data,
6887 state->max_data_return);
6888 END_PROFILE(Trans2_findnotifynext);
6892 case TRANSACT2_MKDIR:
6894 START_PROFILE(Trans2_mkdir);
6895 call_trans2mkdir(conn, req,
6896 &state->param, state->total_param,
6897 &state->data, state->total_data,
6898 state->max_data_return);
6899 END_PROFILE(Trans2_mkdir);
6903 case TRANSACT2_GET_DFS_REFERRAL:
6905 START_PROFILE(Trans2_get_dfs_referral);
6906 outsize = call_trans2getdfsreferral(
6907 conn, inbuf, outbuf, size, bufsize,
6908 &state->param, state->total_param,
6909 &state->data, state->total_data,
6910 state->max_data_return);
6911 END_PROFILE(Trans2_get_dfs_referral);
6915 case TRANSACT2_IOCTL:
6917 START_PROFILE(Trans2_ioctl);
6918 outsize = call_trans2ioctl(
6919 conn, inbuf, outbuf, size, bufsize,
6920 &state->param, state->total_param,
6921 &state->data, state->total_data,
6922 state->max_data_return);
6923 END_PROFILE(Trans2_ioctl);
6928 /* Error in request */
6929 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6930 outsize = ERROR_DOS(ERRSRV,ERRerror);
6936 /****************************************************************************
6937 Reply to a SMBtrans2.
6938 ****************************************************************************/
6940 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6941 int size, int bufsize)
6944 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6945 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6946 unsigned int psoff = SVAL(inbuf, smb_psoff);
6947 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6948 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6949 struct trans_state *state;
6952 START_PROFILE(SMBtrans2);
6954 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6955 if (!NT_STATUS_IS_OK(result)) {
6956 DEBUG(2, ("Got invalid trans2 request: %s\n",
6957 nt_errstr(result)));
6958 END_PROFILE(SMBtrans2);
6959 return ERROR_NT(result);
6962 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6963 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6964 && (tran_call != TRANSACT2_QFILEINFO)) {
6965 END_PROFILE(SMBtrans2);
6966 return ERROR_DOS(ERRSRV,ERRaccess);
6969 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6970 DEBUG(0, ("talloc failed\n"));
6971 END_PROFILE(SMBtrans2);
6972 return ERROR_NT(NT_STATUS_NO_MEMORY);
6975 state->cmd = SMBtrans2;
6977 state->mid = SVAL(inbuf, smb_mid);
6978 state->vuid = SVAL(inbuf, smb_uid);
6979 state->setup_count = SVAL(inbuf, smb_suwcnt);
6980 state->setup = NULL;
6981 state->total_param = SVAL(inbuf, smb_tpscnt);
6982 state->param = NULL;
6983 state->total_data = SVAL(inbuf, smb_tdscnt);
6985 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6986 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6987 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6988 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6989 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6991 state->call = tran_call;
6993 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6994 is so as a sanity check */
6995 if (state->setup_count != 1) {
6997 * Need to have rc=0 for ioctl to get job id for OS/2.
6998 * Network printing will fail if function is not successful.
6999 * Similar function in reply.c will be used if protocol
7000 * is LANMAN1.0 instead of LM1.2X002.
7001 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7002 * outbuf doesn't have to be set(only job id is used).
7004 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
7005 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
7006 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7007 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7009 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7010 DEBUG(2,("Transaction is %d\n",tran_call));
7012 END_PROFILE(SMBtrans2);
7013 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7017 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7020 if (state->total_data) {
7021 /* Can't use talloc here, the core routines do realloc on the
7022 * params and data. */
7023 state->data = (char *)SMB_MALLOC(state->total_data);
7024 if (state->data == NULL) {
7025 DEBUG(0,("reply_trans2: data malloc fail for %u "
7026 "bytes !\n", (unsigned int)state->total_data));
7028 END_PROFILE(SMBtrans2);
7029 return(ERROR_DOS(ERRDOS,ERRnomem));
7031 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7033 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
7034 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
7037 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
7040 if (state->total_param) {
7041 /* Can't use talloc here, the core routines do realloc on the
7042 * params and data. */
7043 state->param = (char *)SMB_MALLOC(state->total_param);
7044 if (state->param == NULL) {
7045 DEBUG(0,("reply_trans: param malloc fail for %u "
7046 "bytes !\n", (unsigned int)state->total_param));
7047 SAFE_FREE(state->data);
7049 END_PROFILE(SMBtrans2);
7050 return(ERROR_DOS(ERRDOS,ERRnomem));
7052 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7054 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
7055 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
7058 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
7061 state->received_data = dscnt;
7062 state->received_param = pscnt;
7064 if ((state->received_param == state->total_param) &&
7065 (state->received_data == state->total_data)) {
7067 struct smb_request *req;
7069 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
7070 END_PROFILE(SMBtrans2);
7071 return ERROR_NT(NT_STATUS_NO_MEMORY);
7074 init_smb_request(req, (uint8 *)inbuf);
7076 outsize = handle_trans2(conn, req, state, inbuf, outbuf,
7078 if (req->outbuf != NULL) {
7079 outsize = smb_len(req->outbuf) + 4;
7080 memcpy(outbuf, req->outbuf, outsize);
7083 SAFE_FREE(state->data);
7084 SAFE_FREE(state->param);
7086 END_PROFILE(SMBtrans2);
7090 DLIST_ADD(conn->pending_trans, state);
7092 /* We need to send an interim response then receive the rest
7093 of the parameter/data bytes */
7094 outsize = set_message(inbuf, outbuf,0,0,False);
7096 END_PROFILE(SMBtrans2);
7101 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7102 SAFE_FREE(state->data);
7103 SAFE_FREE(state->param);
7105 END_PROFILE(SMBtrans2);
7106 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7110 /****************************************************************************
7111 Reply to a SMBtranss2
7112 ****************************************************************************/
7114 int reply_transs2(connection_struct *conn,
7115 char *inbuf,char *outbuf,int size,int bufsize)
7118 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7119 struct trans_state *state;
7120 struct smb_request *req;
7122 START_PROFILE(SMBtranss2);
7126 for (state = conn->pending_trans; state != NULL;
7127 state = state->next) {
7128 if (state->mid == SVAL(inbuf,smb_mid)) {
7133 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7134 END_PROFILE(SMBtranss2);
7135 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7138 /* Revise state->total_param and state->total_data in case they have
7139 changed downwards */
7141 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
7142 state->total_param = SVAL(inbuf, smb_tpscnt);
7143 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
7144 state->total_data = SVAL(inbuf, smb_tdscnt);
7146 pcnt = SVAL(inbuf, smb_spscnt);
7147 poff = SVAL(inbuf, smb_spsoff);
7148 pdisp = SVAL(inbuf, smb_spsdisp);
7150 dcnt = SVAL(inbuf, smb_sdscnt);
7151 doff = SVAL(inbuf, smb_sdsoff);
7152 ddisp = SVAL(inbuf, smb_sdsdisp);
7154 state->received_param += pcnt;
7155 state->received_data += dcnt;
7157 if ((state->received_data > state->total_data) ||
7158 (state->received_param > state->total_param))
7162 if (pdisp+pcnt > state->total_param)
7164 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7166 if (pdisp > state->total_param)
7168 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
7169 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
7171 if (state->param + pdisp < state->param)
7174 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
7179 if (ddisp+dcnt > state->total_data)
7181 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7183 if (ddisp > state->total_data)
7185 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
7186 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
7188 if (state->data + ddisp < state->data)
7191 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
7195 if ((state->received_param < state->total_param) ||
7196 (state->received_data < state->total_data)) {
7197 END_PROFILE(SMBtranss2);
7201 /* construct_reply_common has done us the favor to pre-fill the
7202 * command field with SMBtranss2 which is wrong :-)
7204 SCVAL(outbuf,smb_com,SMBtrans2);
7206 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
7207 END_PROFILE(SMBtranss2);
7208 return ERROR_NT(NT_STATUS_NO_MEMORY);
7211 init_smb_request(req, (uint8 *)inbuf);
7213 outsize = handle_trans2(conn, req, state, inbuf, outbuf, size,
7215 if (req->outbuf != NULL) {
7216 outsize = smb_len(req->outbuf) + 4;
7217 memcpy(outbuf, req->outbuf, outsize);
7221 DLIST_REMOVE(conn->pending_trans, state);
7222 SAFE_FREE(state->data);
7223 SAFE_FREE(state->param);
7227 END_PROFILE(SMBtranss2);
7228 return(ERROR_DOS(ERRSRV,ERRnosupport));
7231 END_PROFILE(SMBtranss2);
7236 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7237 DLIST_REMOVE(conn->pending_trans, state);
7238 SAFE_FREE(state->data);
7239 SAFE_FREE(state->param);
7241 END_PROFILE(SMBtranss2);
7242 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);