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 int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2056 char **pparams, int total_params, char **ppdata, int total_data,
2057 unsigned int max_data_bytes)
2059 /* We must be careful here that we don't return more than the
2060 allowed number of data bytes. If this means returning fewer than
2061 maxentries then so be it. We assume that the redirector has
2062 enough room for the fixed number of parameter bytes it has
2064 char *params = *pparams;
2065 char *pdata = *ppdata;
2071 uint16 findnext_flags;
2072 BOOL close_after_request;
2074 BOOL requires_resume_key;
2076 BOOL mask_contains_wcard = False;
2077 pstring resume_name;
2083 int i, last_entry_off=0;
2084 BOOL finished = False;
2085 BOOL dont_descend = False;
2086 BOOL out_of_space = False;
2087 int space_remaining;
2088 TALLOC_CTX *ea_ctx = NULL;
2089 struct ea_list *ea_list = NULL;
2090 NTSTATUS ntstatus = NT_STATUS_OK;
2092 if (total_params < 13) {
2093 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2096 dptr_num = SVAL(params,0);
2097 maxentries = SVAL(params,2);
2098 info_level = SVAL(params,4);
2099 resume_key = IVAL(params,6);
2100 findnext_flags = SVAL(params,10);
2101 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2102 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2103 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2104 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2106 *mask = *directory = *resume_name = 0;
2108 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), resume_name,
2109 params+12, sizeof(resume_name),
2110 total_params - 12, STR_TERMINATE, &ntstatus,
2111 &mask_contains_wcard);
2112 if (!NT_STATUS_IS_OK(ntstatus)) {
2113 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2114 complain (it thinks we're asking for the directory above the shared
2115 path or an invalid name). Catch this as the resume name is only compared, never used in
2116 a file access. JRA. */
2117 srvstr_pull(inbuf, SVAL(inbuf,smb_flg2),
2118 resume_name, params+12,
2119 sizeof(resume_name), total_params - 12,
2122 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2123 return ERROR_NT(ntstatus);
2127 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2128 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2129 resume_key = %d resume name = %s continue=%d level = %d\n",
2130 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2131 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2134 /* W2K3 seems to treat zero as 1. */
2138 switch (info_level) {
2139 case SMB_FIND_INFO_STANDARD:
2140 case SMB_FIND_EA_SIZE:
2141 case SMB_FIND_EA_LIST:
2142 case SMB_FIND_FILE_DIRECTORY_INFO:
2143 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2144 case SMB_FIND_FILE_NAMES_INFO:
2145 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2146 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2147 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2149 case SMB_FIND_FILE_UNIX:
2150 case SMB_FIND_FILE_UNIX_INFO2:
2151 if (!lp_unix_extensions()) {
2152 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2156 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2159 if (info_level == SMB_FIND_EA_LIST) {
2162 if (total_data < 4) {
2163 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2166 ea_size = IVAL(pdata,0);
2167 if (ea_size != total_data) {
2168 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2169 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2170 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2173 if (!lp_ea_support(SNUM(conn))) {
2174 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2177 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2178 return ERROR_NT(NT_STATUS_NO_MEMORY);
2181 /* Pull out the list of names. */
2182 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2184 talloc_destroy(ea_ctx);
2185 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2189 *ppdata = (char *)SMB_REALLOC(
2190 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2191 if(*ppdata == NULL) {
2192 talloc_destroy(ea_ctx);
2193 return ERROR_NT(NT_STATUS_NO_MEMORY);
2197 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2199 /* Realloc the params space */
2200 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2201 if(*pparams == NULL ) {
2202 talloc_destroy(ea_ctx);
2203 return ERROR_NT(NT_STATUS_NO_MEMORY);
2208 /* Check that the dptr is valid */
2209 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2210 talloc_destroy(ea_ctx);
2211 return ERROR_DOS(ERRDOS,ERRnofiles);
2214 string_set(&conn->dirpath,dptr_path(dptr_num));
2216 /* Get the wildcard mask from the dptr */
2217 if((p = dptr_wcard(dptr_num))== NULL) {
2218 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2219 talloc_destroy(ea_ctx);
2220 return ERROR_DOS(ERRDOS,ERRnofiles);
2224 pstrcpy(directory,conn->dirpath);
2226 /* Get the attr mask from the dptr */
2227 dirtype = dptr_attr(dptr_num);
2229 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2230 dptr_num, mask, dirtype,
2232 dptr_TellDir(conn->dirptr)));
2234 /* We don't need to check for VOL here as this is returned by
2235 a different TRANS2 call. */
2237 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2238 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2239 dont_descend = True;
2242 space_remaining = max_data_bytes;
2243 out_of_space = False;
2246 * Seek to the correct position. We no longer use the resume key but
2247 * depend on the last file name instead.
2250 if(*resume_name && !continue_bit) {
2253 long current_pos = 0;
2255 * Remember, mangle_map is called by
2256 * get_lanman2_dir_entry(), so the resume name
2257 * could be mangled. Ensure we check the unmangled name.
2260 if (mangle_is_mangled(resume_name, conn->params)) {
2261 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2266 * Fix for NT redirector problem triggered by resume key indexes
2267 * changing between directory scans. We now return a resume key of 0
2268 * and instead look for the filename to continue from (also given
2269 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2270 * findfirst/findnext (as is usual) then the directory pointer
2271 * should already be at the correct place.
2274 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2275 } /* end if resume_name && !continue_bit */
2277 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2278 BOOL got_exact_match = False;
2280 /* this is a heuristic to avoid seeking the dirptr except when
2281 absolutely necessary. It allows for a filename of about 40 chars */
2282 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2283 out_of_space = True;
2286 finished = !get_lanman2_dir_entry(conn,
2287 SVAL(outbuf, smb_flg2),
2288 mask,dirtype,info_level,
2289 requires_resume_key,dont_descend,
2291 space_remaining, &out_of_space,
2293 &last_entry_off, ea_list, ea_ctx);
2296 if (finished && out_of_space)
2299 if (!finished && !out_of_space)
2303 * As an optimisation if we know we aren't looking
2304 * for a wildcard name (ie. the name matches the wildcard exactly)
2305 * then we can finish on any (first) match.
2306 * This speeds up large directory searches. JRA.
2312 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2315 talloc_destroy(ea_ctx);
2317 /* Check if we can close the dirptr */
2318 if(close_after_request || (finished && close_if_end)) {
2319 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2320 dptr_close(&dptr_num); /* This frees up the saved mask */
2323 /* Set up the return parameter block */
2324 SSVAL(params,0,numentries);
2325 SSVAL(params,2,finished);
2326 SSVAL(params,4,0); /* Never an EA error */
2327 SSVAL(params,6,last_entry_off);
2329 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2331 if ((! *directory) && dptr_path(dptr_num))
2332 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2334 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2335 smb_fn_name(CVAL(inbuf,smb_com)),
2336 mask, directory, dirtype, numentries ) );
2341 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2343 E_md4hash(lp_servicename(SNUM(conn)),objid);
2347 /****************************************************************************
2348 Reply to a TRANS2_QFSINFO (query filesystem info).
2349 ****************************************************************************/
2351 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2352 char **pparams, int total_params, char **ppdata, int total_data,
2353 unsigned int max_data_bytes)
2356 char *params = *pparams;
2360 const char *vname = volume_label(SNUM(conn));
2361 int snum = SNUM(conn);
2362 char *fstype = lp_fstype(SNUM(conn));
2365 if (total_params < 2) {
2366 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2369 info_level = SVAL(params,0);
2371 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2373 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2374 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2375 return ERROR_DOS(ERRSRV,ERRinvdevice);
2378 *ppdata = (char *)SMB_REALLOC(
2379 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2380 if (*ppdata == NULL ) {
2381 return ERROR_NT(NT_STATUS_NO_MEMORY);
2385 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2387 switch (info_level) {
2388 case SMB_INFO_ALLOCATION:
2390 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2392 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2393 return(UNIXERROR(ERRHRD,ERRgeneral));
2396 block_size = lp_block_size(snum);
2397 if (bsize < block_size) {
2398 SMB_BIG_UINT factor = block_size/bsize;
2403 if (bsize > block_size) {
2404 SMB_BIG_UINT factor = bsize/block_size;
2409 bytes_per_sector = 512;
2410 sectors_per_unit = bsize/bytes_per_sector;
2412 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2413 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2414 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2416 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2417 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2418 SIVAL(pdata,l1_cUnit,dsize);
2419 SIVAL(pdata,l1_cUnitAvail,dfree);
2420 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2424 case SMB_INFO_VOLUME:
2425 /* Return volume name */
2427 * Add volume serial number - hash of a combination of
2428 * the called hostname and the service name.
2430 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2432 * Win2k3 and previous mess this up by sending a name length
2433 * one byte short. I believe only older clients (OS/2 Win9x) use
2434 * this call so try fixing this by adding a terminating null to
2435 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2437 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2438 pdata+l2_vol_szVolLabel, vname,
2439 -1, STR_NOALIGN|STR_TERMINATE);
2440 SCVAL(pdata,l2_vol_cch,len);
2441 data_len = l2_vol_szVolLabel + len;
2442 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2443 (unsigned)st.st_ctime, len, vname));
2446 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2447 case SMB_FS_ATTRIBUTE_INFORMATION:
2450 #if defined(HAVE_SYS_QUOTAS)
2451 quota_flag = FILE_VOLUME_QUOTAS;
2454 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2455 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2456 FILE_SUPPORTS_OBJECT_IDS|
2457 FILE_UNICODE_ON_DISK|
2458 quota_flag); /* FS ATTRIBUTES */
2460 SIVAL(pdata,4,255); /* Max filename component length */
2461 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2462 and will think we can't do long filenames */
2463 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2464 pdata+12, fstype, -1, STR_UNICODE);
2466 data_len = 12 + len;
2469 case SMB_QUERY_FS_LABEL_INFO:
2470 case SMB_FS_LABEL_INFORMATION:
2471 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2472 pdata+4, vname, -1, 0);
2477 case SMB_QUERY_FS_VOLUME_INFO:
2478 case SMB_FS_VOLUME_INFORMATION:
2481 * Add volume serial number - hash of a combination of
2482 * the called hostname and the service name.
2484 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2485 (str_checksum(get_local_machine_name())<<16));
2487 /* Max label len is 32 characters. */
2488 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2489 pdata+18, vname, -1, STR_UNICODE);
2490 SIVAL(pdata,12,len);
2493 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2494 (int)strlen(vname),vname, lp_servicename(snum)));
2497 case SMB_QUERY_FS_SIZE_INFO:
2498 case SMB_FS_SIZE_INFORMATION:
2500 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2502 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2503 return(UNIXERROR(ERRHRD,ERRgeneral));
2505 block_size = lp_block_size(snum);
2506 if (bsize < block_size) {
2507 SMB_BIG_UINT factor = block_size/bsize;
2512 if (bsize > block_size) {
2513 SMB_BIG_UINT factor = bsize/block_size;
2518 bytes_per_sector = 512;
2519 sectors_per_unit = bsize/bytes_per_sector;
2520 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2521 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2522 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2523 SBIG_UINT(pdata,0,dsize);
2524 SBIG_UINT(pdata,8,dfree);
2525 SIVAL(pdata,16,sectors_per_unit);
2526 SIVAL(pdata,20,bytes_per_sector);
2530 case SMB_FS_FULL_SIZE_INFORMATION:
2532 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2534 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2535 return(UNIXERROR(ERRHRD,ERRgeneral));
2537 block_size = lp_block_size(snum);
2538 if (bsize < block_size) {
2539 SMB_BIG_UINT factor = block_size/bsize;
2544 if (bsize > block_size) {
2545 SMB_BIG_UINT factor = bsize/block_size;
2550 bytes_per_sector = 512;
2551 sectors_per_unit = bsize/bytes_per_sector;
2552 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2553 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2554 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2555 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2556 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2557 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2558 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2559 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2563 case SMB_QUERY_FS_DEVICE_INFO:
2564 case SMB_FS_DEVICE_INFORMATION:
2566 SIVAL(pdata,0,0); /* dev type */
2567 SIVAL(pdata,4,0); /* characteristics */
2570 #ifdef HAVE_SYS_QUOTAS
2571 case SMB_FS_QUOTA_INFORMATION:
2573 * what we have to send --metze:
2575 * Unknown1: 24 NULL bytes
2576 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2577 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2578 * Quota Flags: 2 byte :
2579 * Unknown3: 6 NULL bytes
2583 * details for Quota Flags:
2585 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2586 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2587 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2588 * 0x0001 Enable Quotas: enable quota for this fs
2592 /* we need to fake up a fsp here,
2593 * because its not send in this call
2596 SMB_NTQUOTA_STRUCT quotas;
2599 ZERO_STRUCT(quotas);
2605 if (current_user.ut.uid != 0) {
2606 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2607 lp_servicename(SNUM(conn)),conn->user));
2608 return ERROR_DOS(ERRDOS,ERRnoaccess);
2611 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2612 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2613 return ERROR_DOS(ERRSRV,ERRerror);
2618 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2620 /* Unknown1 24 NULL bytes*/
2621 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2622 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2623 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2625 /* Default Soft Quota 8 bytes */
2626 SBIG_UINT(pdata,24,quotas.softlim);
2628 /* Default Hard Quota 8 bytes */
2629 SBIG_UINT(pdata,32,quotas.hardlim);
2631 /* Quota flag 2 bytes */
2632 SSVAL(pdata,40,quotas.qflags);
2634 /* Unknown3 6 NULL bytes */
2640 #endif /* HAVE_SYS_QUOTAS */
2641 case SMB_FS_OBJECTID_INFORMATION:
2643 unsigned char objid[16];
2644 memcpy(pdata,create_volume_objectid(conn, objid),16);
2650 * Query the version and capabilities of the CIFS UNIX extensions
2654 case SMB_QUERY_CIFS_UNIX_INFO:
2655 if (!lp_unix_extensions()) {
2656 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2659 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2660 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2661 /* We have POSIX ACLs, pathname and locking capability. */
2662 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2663 CIFS_UNIX_POSIX_ACLS_CAP|
2664 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2665 CIFS_UNIX_FCNTL_LOCKS_CAP|
2666 CIFS_UNIX_EXTATTR_CAP|
2667 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2668 /* Ensure we don't do this on signed or sealed data. */
2669 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2673 case SMB_QUERY_POSIX_FS_INFO:
2676 vfs_statvfs_struct svfs;
2678 if (!lp_unix_extensions()) {
2679 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2682 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2686 SIVAL(pdata,0,svfs.OptimalTransferSize);
2687 SIVAL(pdata,4,svfs.BlockSize);
2688 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2689 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2690 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2691 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2692 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2693 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2694 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2696 } else if (rc == EOPNOTSUPP) {
2697 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2698 #endif /* EOPNOTSUPP */
2700 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2701 return ERROR_DOS(ERRSRV,ERRerror);
2706 case SMB_QUERY_POSIX_WHOAMI:
2712 if (!lp_unix_extensions()) {
2713 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2716 if (max_data_bytes < 40) {
2717 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2720 /* We ARE guest if global_sid_Builtin_Guests is
2721 * in our list of SIDs.
2723 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2724 current_user.nt_user_token)) {
2725 flags |= SMB_WHOAMI_GUEST;
2728 /* We are NOT guest if global_sid_Authenticated_Users
2729 * is in our list of SIDs.
2731 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2732 current_user.nt_user_token)) {
2733 flags &= ~SMB_WHOAMI_GUEST;
2736 /* NOTE: 8 bytes for UID/GID, irrespective of native
2737 * platform size. This matches
2738 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2740 data_len = 4 /* flags */
2747 + 4 /* pad/reserved */
2748 + (current_user.ut.ngroups * 8)
2750 + (current_user.nt_user_token->num_sids *
2754 SIVAL(pdata, 0, flags);
2755 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2756 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2757 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2760 if (data_len >= max_data_bytes) {
2761 /* Potential overflow, skip the GIDs and SIDs. */
2763 SIVAL(pdata, 24, 0); /* num_groups */
2764 SIVAL(pdata, 28, 0); /* num_sids */
2765 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2766 SIVAL(pdata, 36, 0); /* reserved */
2772 SIVAL(pdata, 24, current_user.ut.ngroups);
2774 current_user.nt_user_token->num_sids);
2776 /* We walk the SID list twice, but this call is fairly
2777 * infrequent, and I don't expect that it's performance
2778 * sensitive -- jpeach
2780 for (i = 0, sid_bytes = 0;
2781 i < current_user.nt_user_token->num_sids; ++i) {
2783 sid_size(¤t_user.nt_user_token->user_sids[i]);
2786 /* SID list byte count */
2787 SIVAL(pdata, 32, sid_bytes);
2789 /* 4 bytes pad/reserved - must be zero */
2790 SIVAL(pdata, 36, 0);
2794 for (i = 0; i < current_user.ut.ngroups; ++i) {
2795 SBIG_UINT(pdata, data_len,
2796 (SMB_BIG_UINT)current_user.ut.groups[i]);
2802 i < current_user.nt_user_token->num_sids; ++i) {
2804 sid_size(¤t_user.nt_user_token->user_sids[i]);
2806 sid_linearize(pdata + data_len, sid_len,
2807 ¤t_user.nt_user_token->user_sids[i]);
2808 data_len += sid_len;
2814 case SMB_MAC_QUERY_FS_INFO:
2816 * Thursby MAC extension... ONLY on NTFS filesystems
2817 * once we do streams then we don't need this
2819 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2821 SIVAL(pdata,84,0x100); /* Don't support mac... */
2826 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2830 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2832 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2837 /****************************************************************************
2838 Reply to a TRANS2_SETFSINFO (set filesystem info).
2839 ****************************************************************************/
2841 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2842 char **pparams, int total_params, char **ppdata, int total_data,
2843 unsigned int max_data_bytes)
2845 char *pdata = *ppdata;
2846 char *params = *pparams;
2850 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2853 if (total_params < 4) {
2854 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2859 info_level = SVAL(params,2);
2861 switch(info_level) {
2862 case SMB_SET_CIFS_UNIX_INFO:
2864 uint16 client_unix_major;
2865 uint16 client_unix_minor;
2866 uint32 client_unix_cap_low;
2867 uint32 client_unix_cap_high;
2869 if (!lp_unix_extensions()) {
2870 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2873 /* There should be 12 bytes of capabilities set. */
2874 if (total_data < 8) {
2875 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2877 client_unix_major = SVAL(pdata,0);
2878 client_unix_minor = SVAL(pdata,2);
2879 client_unix_cap_low = IVAL(pdata,4);
2880 client_unix_cap_high = IVAL(pdata,8);
2881 /* Just print these values for now. */
2882 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2883 cap_low = 0x%x, cap_high = 0x%x\n",
2884 (unsigned int)client_unix_major,
2885 (unsigned int)client_unix_minor,
2886 (unsigned int)client_unix_cap_low,
2887 (unsigned int)client_unix_cap_high ));
2889 /* Here is where we must switch to posix pathname processing... */
2890 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2891 lp_set_posix_pathnames();
2892 mangle_change_to_posix();
2895 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2896 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2897 /* Client that knows how to do posix locks,
2898 * but not posix open/mkdir operations. Set a
2899 * default type for read/write checks. */
2901 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2906 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2909 size_t param_len = 0;
2910 size_t data_len = total_data;
2912 if (!lp_unix_extensions()) {
2913 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2916 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2918 status = srv_request_encryption_setup(conn,
2919 (unsigned char **)ppdata,
2921 (unsigned char **)pparams,
2925 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2926 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2927 } else if (!NT_STATUS_IS_OK(status)) {
2928 return ERROR_NT(status);
2931 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2933 if (NT_STATUS_IS_OK(status)) {
2934 /* Server-side transport encryption is now *on*. */
2935 status = srv_encryption_start(conn);
2936 if (!NT_STATUS_IS_OK(status)) {
2937 exit_server_cleanly("Failure in setting up encrypted transport");
2942 case SMB_FS_QUOTA_INFORMATION:
2944 files_struct *fsp = NULL;
2945 SMB_NTQUOTA_STRUCT quotas;
2947 ZERO_STRUCT(quotas);
2950 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2951 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2952 lp_servicename(SNUM(conn)),conn->user));
2953 return ERROR_DOS(ERRSRV,ERRaccess);
2956 /* note: normaly there're 48 bytes,
2957 * but we didn't use the last 6 bytes for now
2960 fsp = file_fsp(SVAL(params,0));
2961 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2962 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2963 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2966 if (total_data < 42) {
2967 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2969 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2972 /* unknown_1 24 NULL bytes in pdata*/
2974 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2975 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2976 #ifdef LARGE_SMB_OFF_T
2977 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2978 #else /* LARGE_SMB_OFF_T */
2979 if ((IVAL(pdata,28) != 0)&&
2980 ((quotas.softlim != 0xFFFFFFFF)||
2981 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2982 /* more than 32 bits? */
2983 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2985 #endif /* LARGE_SMB_OFF_T */
2987 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2988 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2989 #ifdef LARGE_SMB_OFF_T
2990 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2991 #else /* LARGE_SMB_OFF_T */
2992 if ((IVAL(pdata,36) != 0)&&
2993 ((quotas.hardlim != 0xFFFFFFFF)||
2994 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2995 /* more than 32 bits? */
2996 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2998 #endif /* LARGE_SMB_OFF_T */
3000 /* quota_flags 2 bytes **/
3001 quotas.qflags = SVAL(pdata,40);
3003 /* unknown_2 6 NULL bytes follow*/
3005 /* now set the quotas */
3006 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3007 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3008 return ERROR_DOS(ERRSRV,ERRerror);
3014 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3016 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3021 * sending this reply works fine,
3022 * but I'm not sure it's the same
3023 * like windows do...
3026 outsize = set_message(inbuf, outbuf,10,0,True);
3031 #if defined(HAVE_POSIX_ACLS)
3032 /****************************************************************************
3033 Utility function to count the number of entries in a POSIX acl.
3034 ****************************************************************************/
3036 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3038 unsigned int ace_count = 0;
3039 int entry_id = SMB_ACL_FIRST_ENTRY;
3040 SMB_ACL_ENTRY_T entry;
3042 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3044 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3045 entry_id = SMB_ACL_NEXT_ENTRY;
3052 /****************************************************************************
3053 Utility function to marshall a POSIX acl into wire format.
3054 ****************************************************************************/
3056 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3058 int entry_id = SMB_ACL_FIRST_ENTRY;
3059 SMB_ACL_ENTRY_T entry;
3061 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3062 SMB_ACL_TAG_T tagtype;
3063 SMB_ACL_PERMSET_T permset;
3064 unsigned char perms = 0;
3065 unsigned int own_grp;
3068 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3069 entry_id = SMB_ACL_NEXT_ENTRY;
3072 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3073 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3077 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3078 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3082 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3083 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3084 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3086 SCVAL(pdata,1,perms);
3089 case SMB_ACL_USER_OBJ:
3090 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3091 own_grp = (unsigned int)pst->st_uid;
3092 SIVAL(pdata,2,own_grp);
3097 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3099 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3102 own_grp = (unsigned int)*puid;
3103 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3104 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3105 SIVAL(pdata,2,own_grp);
3109 case SMB_ACL_GROUP_OBJ:
3110 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3111 own_grp = (unsigned int)pst->st_gid;
3112 SIVAL(pdata,2,own_grp);
3117 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3119 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3122 own_grp = (unsigned int)*pgid;
3123 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3124 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3125 SIVAL(pdata,2,own_grp);
3130 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3131 SIVAL(pdata,2,0xFFFFFFFF);
3132 SIVAL(pdata,6,0xFFFFFFFF);
3135 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3136 SIVAL(pdata,2,0xFFFFFFFF);
3137 SIVAL(pdata,6,0xFFFFFFFF);
3140 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3143 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3150 /****************************************************************************
3151 Store the FILE_UNIX_BASIC info.
3152 ****************************************************************************/
3154 static char *store_file_unix_basic(connection_struct *conn,
3157 const SMB_STRUCT_STAT *psbuf)
3159 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3160 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3162 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3165 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3168 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3169 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3170 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3173 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3177 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3181 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3184 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3188 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3192 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3195 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3199 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3206 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3207 * the chflags(2) (or equivalent) flags.
3209 * XXX: this really should be behind the VFS interface. To do this, we would
3210 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3211 * Each VFS module could then implement it's own mapping as appropriate for the
3212 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3214 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3218 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3222 { UF_IMMUTABLE, EXT_IMMUTABLE },
3226 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3230 { UF_HIDDEN, EXT_HIDDEN },
3233 /* Do not remove. We need to guarantee that this array has at least one
3234 * entry to build on HP-UX.
3240 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3241 uint32 *smb_fflags, uint32 *smb_fmask)
3243 #ifdef HAVE_STAT_ST_FLAGS
3246 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3247 *smb_fmask |= info2_flags_map[i].smb_fflag;
3248 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3249 *smb_fflags |= info2_flags_map[i].smb_fflag;
3252 #endif /* HAVE_STAT_ST_FLAGS */
3255 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3256 const uint32 smb_fflags,
3257 const uint32 smb_fmask,
3260 #ifdef HAVE_STAT_ST_FLAGS
3261 uint32 max_fmask = 0;
3264 *stat_fflags = psbuf->st_flags;
3266 /* For each flags requested in smb_fmask, check the state of the
3267 * corresponding flag in smb_fflags and set or clear the matching
3271 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3272 max_fmask |= info2_flags_map[i].smb_fflag;
3273 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3274 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3275 *stat_fflags |= info2_flags_map[i].stat_fflag;
3277 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3282 /* If smb_fmask is asking to set any bits that are not supported by
3283 * our flag mappings, we should fail.
3285 if ((smb_fmask & max_fmask) != smb_fmask) {
3292 #endif /* HAVE_STAT_ST_FLAGS */
3296 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3297 * of file flags and birth (create) time.
3299 static char *store_file_unix_basic_info2(connection_struct *conn,
3302 const SMB_STRUCT_STAT *psbuf)
3304 uint32 file_flags = 0;
3305 uint32 flags_mask = 0;
3307 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3309 /* Create (birth) time 64 bit */
3310 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3313 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3314 SIVAL(pdata, 0, file_flags); /* flags */
3315 SIVAL(pdata, 4, flags_mask); /* mask */
3321 /****************************************************************************
3322 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3323 ****************************************************************************/
3325 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3326 unsigned int tran_call,
3327 char **pparams, int total_params, char **ppdata, int total_data,
3328 unsigned int max_data_bytes)
3330 char *params = *pparams;
3331 char *pdata = *ppdata;
3332 unsigned int data_size = 0;
3333 unsigned int param_size = 2;
3335 smb_np_struct *p_pipe = NULL;
3338 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3341 if (total_params < 4) {
3342 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3345 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3346 if (p_pipe == NULL) {
3347 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3350 info_level = SVAL(params,2);
3352 *pparams = (char *)SMB_REALLOC(*pparams,2);
3353 if (*pparams == NULL) {
3354 return ERROR_NT(NT_STATUS_NO_MEMORY);
3358 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3359 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3360 if (*ppdata == NULL ) {
3361 return ERROR_NT(NT_STATUS_NO_MEMORY);
3365 switch (info_level) {
3366 case SMB_FILE_STANDARD_INFORMATION:
3368 SOFF_T(pdata,0,4096LL);
3375 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3378 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3383 /****************************************************************************
3384 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3385 file name or file id).
3386 ****************************************************************************/
3388 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3389 unsigned int tran_call,
3390 char **pparams, int total_params, char **ppdata, int total_data,
3391 unsigned int max_data_bytes)
3393 char *params = *pparams;
3394 char *pdata = *ppdata;
3398 SMB_OFF_T file_size=0;
3399 SMB_BIG_UINT allocation_size=0;
3400 unsigned int data_size = 0;
3401 unsigned int param_size = 2;
3402 SMB_STRUCT_STAT sbuf;
3403 pstring fname, dos_fname;
3408 BOOL delete_pending = False;
3410 time_t create_time, mtime, atime;
3411 struct timespec create_time_ts, mtime_ts, atime_ts;
3412 files_struct *fsp = NULL;
3413 struct file_id fileid;
3414 TALLOC_CTX *data_ctx = NULL;
3415 struct ea_list *ea_list = NULL;
3416 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3417 char *lock_data = NULL;
3420 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3424 if (tran_call == TRANSACT2_QFILEINFO) {
3425 if (total_params < 4) {
3426 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3430 return call_trans2qpipeinfo(conn,
3443 fsp = file_fsp(SVAL(params,0));
3444 info_level = SVAL(params,2);
3446 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3448 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3449 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3452 if(fsp && (fsp->fake_file_handle)) {
3454 * This is actually for the QUOTA_FAKE_FILE --metze
3457 pstrcpy(fname, fsp->fsp_name);
3458 /* We know this name is ok, it's already passed the checks. */
3460 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3462 * This is actually a QFILEINFO on a directory
3463 * handle (returned from an NT SMB). NT5.0 seems
3464 * to do this call. JRA.
3466 /* We know this name is ok, it's already passed the checks. */
3467 pstrcpy(fname, fsp->fsp_name);
3469 if (INFO_LEVEL_IS_UNIX(info_level)) {
3470 /* Always do lstat for UNIX calls. */
3471 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3472 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3473 return UNIXERROR(ERRDOS,ERRbadpath);
3475 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3476 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3477 return UNIXERROR(ERRDOS,ERRbadpath);
3480 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3481 delete_pending = get_delete_on_close_flag(fileid);
3484 * Original code - this is an open file.
3486 CHECK_FSP(fsp,conn);
3488 pstrcpy(fname, fsp->fsp_name);
3489 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3490 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3491 return(UNIXERROR(ERRDOS,ERRbadfid));
3493 pos = fsp->fh->position_information;
3494 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3495 delete_pending = get_delete_on_close_flag(fileid);
3496 access_mask = fsp->access_mask;
3499 NTSTATUS status = NT_STATUS_OK;
3502 if (total_params < 7) {
3503 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3506 info_level = SVAL(params,0);
3508 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3510 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3511 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3514 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
3515 sizeof(fname), total_params - 6,
3516 STR_TERMINATE, &status);
3517 if (!NT_STATUS_IS_OK(status)) {
3518 return ERROR_NT(status);
3521 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3522 if (!NT_STATUS_IS_OK(status)) {
3523 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3524 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3526 return ERROR_NT(status);
3529 status = unix_convert(conn, fname, False, NULL, &sbuf);
3530 if (!NT_STATUS_IS_OK(status)) {
3531 return ERROR_NT(status);
3533 status = check_name(conn, fname);
3534 if (!NT_STATUS_IS_OK(status)) {
3535 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3536 return ERROR_NT(status);
3539 if (INFO_LEVEL_IS_UNIX(info_level)) {
3540 /* Always do lstat for UNIX calls. */
3541 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3542 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3543 return UNIXERROR(ERRDOS,ERRbadpath);
3545 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3546 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3547 return UNIXERROR(ERRDOS,ERRbadpath);
3550 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3551 delete_pending = get_delete_on_close_flag(fileid);
3552 if (delete_pending) {
3553 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3557 nlink = sbuf.st_nlink;
3559 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3560 /* NTFS does not seem to count ".." */
3564 if ((nlink > 0) && delete_pending) {
3568 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3569 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3572 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3573 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3575 p = strrchr_m(fname,'/');
3581 mode = dos_mode(conn,fname,&sbuf);
3583 mode = FILE_ATTRIBUTE_NORMAL;
3585 fullpathname = fname;
3587 file_size = get_file_size(sbuf);
3589 /* Pull out any data sent here before we realloc. */
3590 switch (info_level) {
3591 case SMB_INFO_QUERY_EAS_FROM_LIST:
3593 /* Pull any EA list from the data portion. */
3596 if (total_data < 4) {
3597 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3599 ea_size = IVAL(pdata,0);
3601 if (total_data > 0 && ea_size != total_data) {
3602 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3603 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3604 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3607 if (!lp_ea_support(SNUM(conn))) {
3608 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3611 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3612 return ERROR_NT(NT_STATUS_NO_MEMORY);
3615 /* Pull out the list of names. */
3616 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3618 talloc_destroy(data_ctx);
3619 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3624 case SMB_QUERY_POSIX_LOCK:
3626 if (fsp == NULL || fsp->fh->fd == -1) {
3627 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3630 if (total_data != POSIX_LOCK_DATA_SIZE) {
3631 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3634 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3635 return ERROR_NT(NT_STATUS_NO_MEMORY);
3638 /* Copy the lock range data. */
3639 lock_data = (char *)TALLOC_MEMDUP(
3640 data_ctx, pdata, total_data);
3642 talloc_destroy(data_ctx);
3643 return ERROR_NT(NT_STATUS_NO_MEMORY);
3650 *pparams = (char *)SMB_REALLOC(*pparams,2);
3651 if (*pparams == NULL) {
3652 talloc_destroy(data_ctx);
3653 return ERROR_NT(NT_STATUS_NO_MEMORY);
3657 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3658 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3659 if (*ppdata == NULL ) {
3660 talloc_destroy(data_ctx);
3661 return ERROR_NT(NT_STATUS_NO_MEMORY);
3665 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3666 mtime_ts = get_mtimespec(&sbuf);
3667 atime_ts = get_atimespec(&sbuf);
3669 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3672 if (!null_timespec(fsp->pending_modtime)) {
3673 /* the pending modtime overrides the current modtime */
3674 mtime_ts = fsp->pending_modtime;
3678 /* Do we have this path open ? */
3679 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3680 fsp1 = file_find_di_first(fileid);
3681 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3682 /* the pending modtime overrides the current modtime */
3683 mtime_ts = fsp1->pending_modtime;
3685 if (fsp1 && fsp1->initial_allocation_size) {
3686 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3690 if (lp_dos_filetime_resolution(SNUM(conn))) {
3691 dos_filetime_timespec(&create_time_ts);
3692 dos_filetime_timespec(&mtime_ts);
3693 dos_filetime_timespec(&atime_ts);
3696 create_time = convert_timespec_to_time_t(create_time_ts);
3697 mtime = convert_timespec_to_time_t(mtime_ts);
3698 atime = convert_timespec_to_time_t(atime_ts);
3700 /* NT expects the name to be in an exact form of the *full*
3701 filename. See the trans2 torture test */
3702 if (strequal(base_name,".")) {
3703 pstrcpy(dos_fname, "\\");
3705 pstr_sprintf(dos_fname, "\\%s", fname);
3706 string_replace(dos_fname, '/', '\\');
3709 switch (info_level) {
3710 case SMB_INFO_STANDARD:
3711 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3713 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3714 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3715 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3716 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3717 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3718 SSVAL(pdata,l1_attrFile,mode);
3721 case SMB_INFO_QUERY_EA_SIZE:
3723 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3724 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3726 srv_put_dos_date2(pdata,0,create_time);
3727 srv_put_dos_date2(pdata,4,atime);
3728 srv_put_dos_date2(pdata,8,mtime); /* write time */
3729 SIVAL(pdata,12,(uint32)file_size);
3730 SIVAL(pdata,16,(uint32)allocation_size);
3731 SSVAL(pdata,20,mode);
3732 SIVAL(pdata,22,ea_size);
3736 case SMB_INFO_IS_NAME_VALID:
3737 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3738 if (tran_call == TRANSACT2_QFILEINFO) {
3739 /* os/2 needs this ? really ?*/
3740 return ERROR_DOS(ERRDOS,ERRbadfunc);
3746 case SMB_INFO_QUERY_EAS_FROM_LIST:
3748 size_t total_ea_len = 0;
3749 struct ea_list *ea_file_list = NULL;
3751 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3753 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3754 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3756 if (!ea_list || (total_ea_len > data_size)) {
3757 talloc_destroy(data_ctx);
3759 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3763 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3764 talloc_destroy(data_ctx);
3768 case SMB_INFO_QUERY_ALL_EAS:
3770 /* We have data_size bytes to put EA's into. */
3771 size_t total_ea_len = 0;
3773 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3775 data_ctx = talloc_init("ea_ctx");
3777 return ERROR_NT(NT_STATUS_NO_MEMORY);
3780 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3781 if (!ea_list || (total_ea_len > data_size)) {
3782 talloc_destroy(data_ctx);
3784 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3788 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3789 talloc_destroy(data_ctx);
3793 case SMB_FILE_BASIC_INFORMATION:
3794 case SMB_QUERY_FILE_BASIC_INFO:
3796 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3797 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3798 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3800 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3804 put_long_date_timespec(pdata,create_time_ts);
3805 put_long_date_timespec(pdata+8,atime_ts);
3806 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3807 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3808 SIVAL(pdata,32,mode);
3810 DEBUG(5,("SMB_QFBI - "));
3811 DEBUG(5,("create: %s ", ctime(&create_time)));
3812 DEBUG(5,("access: %s ", ctime(&atime)));
3813 DEBUG(5,("write: %s ", ctime(&mtime)));
3814 DEBUG(5,("change: %s ", ctime(&mtime)));
3815 DEBUG(5,("mode: %x\n", mode));
3818 case SMB_FILE_STANDARD_INFORMATION:
3819 case SMB_QUERY_FILE_STANDARD_INFO:
3821 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3823 SOFF_T(pdata,0,allocation_size);
3824 SOFF_T(pdata,8,file_size);
3825 SIVAL(pdata,16,nlink);
3826 SCVAL(pdata,20,delete_pending?1:0);
3827 SCVAL(pdata,21,(mode&aDIR)?1:0);
3828 SSVAL(pdata,22,0); /* Padding. */
3831 case SMB_FILE_EA_INFORMATION:
3832 case SMB_QUERY_FILE_EA_INFO:
3834 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3835 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3837 SIVAL(pdata,0,ea_size);
3841 /* Get the 8.3 name - used if NT SMB was negotiated. */
3842 case SMB_QUERY_FILE_ALT_NAME_INFO:
3843 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3847 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3848 pstrcpy(short_name,base_name);
3849 /* Mangle if not already 8.3 */
3850 if(!mangle_is_8_3(short_name, True, conn->params)) {
3851 mangle_map(short_name,True,True,conn->params);
3853 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
3854 pdata+4, short_name, -1,
3856 data_size = 4 + len;
3861 case SMB_QUERY_FILE_NAME_INFO:
3863 this must be *exactly* right for ACLs on mapped drives to work
3865 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
3866 pdata+4, dos_fname, -1, STR_UNICODE);
3867 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3868 data_size = 4 + len;
3872 case SMB_FILE_ALLOCATION_INFORMATION:
3873 case SMB_QUERY_FILE_ALLOCATION_INFO:
3874 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3876 SOFF_T(pdata,0,allocation_size);
3879 case SMB_FILE_END_OF_FILE_INFORMATION:
3880 case SMB_QUERY_FILE_END_OF_FILEINFO:
3881 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3883 SOFF_T(pdata,0,file_size);
3886 case SMB_QUERY_FILE_ALL_INFO:
3887 case SMB_FILE_ALL_INFORMATION:
3889 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3890 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3891 put_long_date_timespec(pdata,create_time_ts);
3892 put_long_date_timespec(pdata+8,atime_ts);
3893 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3894 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3895 SIVAL(pdata,32,mode);
3896 SIVAL(pdata,36,0); /* padding. */
3898 SOFF_T(pdata,0,allocation_size);
3899 SOFF_T(pdata,8,file_size);
3900 SIVAL(pdata,16,nlink);
3901 SCVAL(pdata,20,delete_pending);
3902 SCVAL(pdata,21,(mode&aDIR)?1:0);
3905 SIVAL(pdata,0,ea_size);
3906 pdata += 4; /* EA info */
3907 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
3908 pdata+4, dos_fname, -1, STR_UNICODE);
3911 data_size = PTR_DIFF(pdata,(*ppdata));
3914 case SMB_FILE_INTERNAL_INFORMATION:
3915 /* This should be an index number - looks like
3918 I think this causes us to fail the IFSKIT
3919 BasicFileInformationTest. -tpot */
3921 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3922 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3923 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3927 case SMB_FILE_ACCESS_INFORMATION:
3928 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3929 SIVAL(pdata,0,access_mask);
3933 case SMB_FILE_NAME_INFORMATION:
3934 /* Pathname with leading '\'. */
3937 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3938 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3939 SIVAL(pdata,0,byte_len);
3940 data_size = 4 + byte_len;
3944 case SMB_FILE_DISPOSITION_INFORMATION:
3945 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3947 SCVAL(pdata,0,delete_pending);
3950 case SMB_FILE_POSITION_INFORMATION:
3951 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3953 SOFF_T(pdata,0,pos);
3956 case SMB_FILE_MODE_INFORMATION:
3957 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3958 SIVAL(pdata,0,mode);
3962 case SMB_FILE_ALIGNMENT_INFORMATION:
3963 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3964 SIVAL(pdata,0,0); /* No alignment needed. */
3970 * NT4 server just returns "invalid query" to this - if we try to answer
3971 * it then NTws gets a BSOD! (tridge).
3972 * W2K seems to want this. JRA.
3974 case SMB_QUERY_FILE_STREAM_INFO:
3976 case SMB_FILE_STREAM_INFORMATION:
3977 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3981 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3982 SIVAL(pdata,0,0); /* ??? */
3983 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3984 SOFF_T(pdata,8,file_size);
3985 SOFF_T(pdata,16,allocation_size);
3986 data_size = 24 + byte_len;
3990 case SMB_QUERY_COMPRESSION_INFO:
3991 case SMB_FILE_COMPRESSION_INFORMATION:
3992 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3993 SOFF_T(pdata,0,file_size);
3994 SIVAL(pdata,8,0); /* ??? */
3995 SIVAL(pdata,12,0); /* ??? */
3999 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4000 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4001 put_long_date_timespec(pdata,create_time_ts);
4002 put_long_date_timespec(pdata+8,atime_ts);
4003 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4004 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4005 SOFF_T(pdata,32,allocation_size);
4006 SOFF_T(pdata,40,file_size);
4007 SIVAL(pdata,48,mode);
4008 SIVAL(pdata,52,0); /* ??? */
4012 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4013 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4014 SIVAL(pdata,0,mode);
4020 * CIFS UNIX Extensions.
4023 case SMB_QUERY_FILE_UNIX_BASIC:
4025 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4026 data_size = PTR_DIFF(pdata,(*ppdata));
4030 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4032 for (i=0; i<100; i++)
4033 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4039 case SMB_QUERY_FILE_UNIX_INFO2:
4041 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4042 data_size = PTR_DIFF(pdata,(*ppdata));
4046 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4048 for (i=0; i<100; i++)
4049 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4055 case SMB_QUERY_FILE_UNIX_LINK:
4059 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4061 if(!S_ISLNK(sbuf.st_mode))
4062 return(UNIXERROR(ERRSRV,ERRbadlink));
4064 return(UNIXERROR(ERRDOS,ERRbadlink));
4066 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
4068 return(UNIXERROR(ERRDOS,ERRnoaccess));
4070 len = srvstr_push(outbuf,
4071 SVAL(outbuf, smb_flg2),
4075 data_size = PTR_DIFF(pdata,(*ppdata));
4080 #if defined(HAVE_POSIX_ACLS)
4081 case SMB_QUERY_POSIX_ACL:
4083 SMB_ACL_T file_acl = NULL;
4084 SMB_ACL_T def_acl = NULL;
4085 uint16 num_file_acls = 0;
4086 uint16 num_def_acls = 0;
4088 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4089 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4091 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4094 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4095 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4097 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
4100 if (S_ISDIR(sbuf.st_mode)) {
4101 if (fsp && fsp->is_directory) {
4102 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4104 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4106 def_acl = free_empty_sys_acl(conn, def_acl);
4109 num_file_acls = count_acl_entries(conn, file_acl);
4110 num_def_acls = count_acl_entries(conn, def_acl);
4112 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4113 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4115 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4116 SMB_POSIX_ACL_HEADER_SIZE) ));
4118 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4121 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4123 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4126 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4127 SSVAL(pdata,2,num_file_acls);
4128 SSVAL(pdata,4,num_def_acls);
4129 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4131 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4134 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4136 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4138 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4140 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4143 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4145 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4149 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4152 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4154 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4160 case SMB_QUERY_POSIX_LOCK:
4162 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4164 SMB_BIG_UINT offset;
4166 enum brl_type lock_type;
4168 if (total_data != POSIX_LOCK_DATA_SIZE) {
4169 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4172 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4173 case POSIX_LOCK_TYPE_READ:
4174 lock_type = READ_LOCK;
4176 case POSIX_LOCK_TYPE_WRITE:
4177 lock_type = WRITE_LOCK;
4179 case POSIX_LOCK_TYPE_UNLOCK:
4181 /* There's no point in asking for an unlock... */
4182 talloc_destroy(data_ctx);
4183 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4186 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4187 #if defined(HAVE_LONGLONG)
4188 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4189 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4190 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4191 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4192 #else /* HAVE_LONGLONG */
4193 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4194 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4195 #endif /* HAVE_LONGLONG */
4197 status = query_lock(fsp,
4204 if (ERROR_WAS_LOCK_DENIED(status)) {
4205 /* Here we need to report who has it locked... */
4206 data_size = POSIX_LOCK_DATA_SIZE;
4208 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4209 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4210 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4211 #if defined(HAVE_LONGLONG)
4212 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4213 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4214 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4215 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4216 #else /* HAVE_LONGLONG */
4217 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4218 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4219 #endif /* HAVE_LONGLONG */
4221 } else if (NT_STATUS_IS_OK(status)) {
4222 /* For success we just return a copy of what we sent
4223 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4224 data_size = POSIX_LOCK_DATA_SIZE;
4225 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4226 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4228 return ERROR_NT(status);
4234 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4237 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4242 /****************************************************************************
4243 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4245 ****************************************************************************/
4247 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4249 SMB_STRUCT_STAT sbuf1, sbuf2;
4250 pstring last_component_oldname;
4251 pstring last_component_newname;
4252 NTSTATUS status = NT_STATUS_OK;
4257 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4258 if (!NT_STATUS_IS_OK(status)) {
4262 status = check_name(conn, oldname);
4263 if (!NT_STATUS_IS_OK(status)) {
4267 /* source must already exist. */
4268 if (!VALID_STAT(sbuf1)) {
4269 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4272 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4273 if (!NT_STATUS_IS_OK(status)) {
4277 status = check_name(conn, newname);
4278 if (!NT_STATUS_IS_OK(status)) {
4282 /* Disallow if newname already exists. */
4283 if (VALID_STAT(sbuf2)) {
4284 return NT_STATUS_OBJECT_NAME_COLLISION;
4287 /* No links from a directory. */
4288 if (S_ISDIR(sbuf1.st_mode)) {
4289 return NT_STATUS_FILE_IS_A_DIRECTORY;
4292 /* Ensure this is within the share. */
4293 status = check_reduced_name(conn, oldname);
4294 if (!NT_STATUS_IS_OK(status)) {
4298 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4300 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4301 status = map_nt_error_from_unix(errno);
4302 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4303 nt_errstr(status), newname, oldname));
4309 /****************************************************************************
4310 Deal with setting the time from any of the setfilepathinfo functions.
4311 ****************************************************************************/
4313 static NTSTATUS smb_set_file_time(connection_struct *conn,
4316 const SMB_STRUCT_STAT *psbuf,
4317 struct timespec ts[2])
4320 FILE_NOTIFY_CHANGE_LAST_ACCESS
4321 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4324 if (!VALID_STAT(*psbuf)) {
4325 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4328 /* get some defaults (no modifications) if any info is zero or -1. */
4329 if (null_timespec(ts[0])) {
4330 ts[0] = get_atimespec(psbuf);
4331 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4334 if (null_timespec(ts[1])) {
4335 ts[1] = get_mtimespec(psbuf);
4336 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4339 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4340 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4343 * Try and set the times of this file if
4344 * they are different from the current values.
4348 struct timespec mts = get_mtimespec(psbuf);
4349 struct timespec ats = get_atimespec(psbuf);
4350 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4351 return NT_STATUS_OK;
4357 * This was a setfileinfo on an open file.
4358 * NT does this a lot. We also need to
4359 * set the time here, as it can be read by
4360 * FindFirst/FindNext and with the patch for bug #2045
4361 * in smbd/fileio.c it ensures that this timestamp is
4362 * kept sticky even after a write. We save the request
4363 * away and will set it on file close and after a write. JRA.
4366 if (!null_timespec(ts[1])) {
4367 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4368 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4369 fsp_set_pending_modtime(fsp, ts[1]);
4373 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4375 if(file_ntimes(conn, fname, ts)!=0) {
4376 return map_nt_error_from_unix(errno);
4379 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4381 return NT_STATUS_OK;
4384 /****************************************************************************
4385 Deal with setting the dosmode from any of the setfilepathinfo functions.
4386 ****************************************************************************/
4388 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4390 SMB_STRUCT_STAT *psbuf,
4393 if (!VALID_STAT(*psbuf)) {
4394 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4398 if (S_ISDIR(psbuf->st_mode)) {
4405 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4407 /* check the mode isn't different, before changing it */
4408 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4410 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4411 fname, (unsigned int)dosmode ));
4413 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4414 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4415 fname, strerror(errno)));
4416 return map_nt_error_from_unix(errno);
4419 return NT_STATUS_OK;
4422 /****************************************************************************
4423 Deal with setting the size from any of the setfilepathinfo functions.
4424 ****************************************************************************/
4426 static NTSTATUS smb_set_file_size(connection_struct *conn,
4427 struct smb_request *req,
4430 SMB_STRUCT_STAT *psbuf,
4433 NTSTATUS status = NT_STATUS_OK;
4434 files_struct *new_fsp = NULL;
4436 if (!VALID_STAT(*psbuf)) {
4437 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4440 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4442 if (size == get_file_size(*psbuf)) {
4443 return NT_STATUS_OK;
4446 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4447 fname, (double)size ));
4449 if (fsp && fsp->fh->fd != -1) {
4450 /* Handle based call. */
4451 if (vfs_set_filelen(fsp, size) == -1) {
4452 return map_nt_error_from_unix(errno);
4454 return NT_STATUS_OK;
4457 status = open_file_ntcreate(conn, req, fname, psbuf,
4459 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4462 FILE_ATTRIBUTE_NORMAL,
4463 FORCE_OPLOCK_BREAK_TO_NONE,
4466 if (!NT_STATUS_IS_OK(status)) {
4467 /* NB. We check for open_was_deferred in the caller. */
4471 if (vfs_set_filelen(new_fsp, size) == -1) {
4472 status = map_nt_error_from_unix(errno);
4473 close_file(new_fsp,NORMAL_CLOSE);
4477 close_file(new_fsp,NORMAL_CLOSE);
4478 return NT_STATUS_OK;
4481 /****************************************************************************
4482 Deal with SMB_INFO_SET_EA.
4483 ****************************************************************************/
4485 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4491 struct ea_list *ea_list = NULL;
4492 TALLOC_CTX *ctx = NULL;
4493 NTSTATUS status = NT_STATUS_OK;
4495 if (total_data < 10) {
4497 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4498 length. They seem to have no effect. Bug #3212. JRA */
4500 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4501 /* We're done. We only get EA info in this call. */
4502 return NT_STATUS_OK;
4505 return NT_STATUS_INVALID_PARAMETER;
4508 if (IVAL(pdata,0) > total_data) {
4509 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4510 IVAL(pdata,0), (unsigned int)total_data));
4511 return NT_STATUS_INVALID_PARAMETER;
4514 ctx = talloc_init("SMB_INFO_SET_EA");
4516 return NT_STATUS_NO_MEMORY;
4518 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4520 talloc_destroy(ctx);
4521 return NT_STATUS_INVALID_PARAMETER;
4523 status = set_ea(conn, fsp, fname, ea_list);
4524 talloc_destroy(ctx);
4529 /****************************************************************************
4530 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4531 ****************************************************************************/
4533 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4538 SMB_STRUCT_STAT *psbuf)
4540 NTSTATUS status = NT_STATUS_OK;
4541 BOOL delete_on_close;
4544 if (total_data < 1) {
4545 return NT_STATUS_INVALID_PARAMETER;
4549 return NT_STATUS_INVALID_HANDLE;
4552 delete_on_close = (CVAL(pdata,0) ? True : False);
4553 dosmode = dos_mode(conn, fname, psbuf);
4555 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4556 "delete_on_close = %u\n",
4558 (unsigned int)dosmode,
4559 (unsigned int)delete_on_close ));
4561 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4563 if (!NT_STATUS_IS_OK(status)) {
4567 /* The set is across all open files on this dev/inode pair. */
4568 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4569 return NT_STATUS_ACCESS_DENIED;
4571 return NT_STATUS_OK;
4574 /****************************************************************************
4575 Deal with SMB_FILE_POSITION_INFORMATION.
4576 ****************************************************************************/
4578 static NTSTATUS smb_file_position_information(connection_struct *conn,
4583 SMB_BIG_UINT position_information;
4585 if (total_data < 8) {
4586 return NT_STATUS_INVALID_PARAMETER;
4590 /* Ignore on pathname based set. */
4591 return NT_STATUS_OK;
4594 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4595 #ifdef LARGE_SMB_OFF_T
4596 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4597 #else /* LARGE_SMB_OFF_T */
4598 if (IVAL(pdata,4) != 0) {
4599 /* more than 32 bits? */
4600 return NT_STATUS_INVALID_PARAMETER;
4602 #endif /* LARGE_SMB_OFF_T */
4604 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4605 fsp->fsp_name, (double)position_information ));
4606 fsp->fh->position_information = position_information;
4607 return NT_STATUS_OK;
4610 /****************************************************************************
4611 Deal with SMB_FILE_MODE_INFORMATION.
4612 ****************************************************************************/
4614 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4620 if (total_data < 4) {
4621 return NT_STATUS_INVALID_PARAMETER;
4623 mode = IVAL(pdata,0);
4624 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4625 return NT_STATUS_INVALID_PARAMETER;
4627 return NT_STATUS_OK;
4630 /****************************************************************************
4631 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4632 ****************************************************************************/
4634 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4640 pstring link_target;
4641 const char *newname = fname;
4642 NTSTATUS status = NT_STATUS_OK;
4644 /* Set a symbolic link. */
4645 /* Don't allow this if follow links is false. */
4647 if (total_data == 0) {
4648 return NT_STATUS_INVALID_PARAMETER;
4651 if (!lp_symlinks(SNUM(conn))) {
4652 return NT_STATUS_ACCESS_DENIED;
4655 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
4656 sizeof(link_target), total_data, STR_TERMINATE);
4658 /* !widelinks forces the target path to be within the share. */
4659 /* This means we can interpret the target as a pathname. */
4660 if (!lp_widelinks(SNUM(conn))) {
4662 char *last_dirp = NULL;
4664 if (*link_target == '/') {
4665 /* No absolute paths allowed. */
4666 return NT_STATUS_ACCESS_DENIED;
4668 pstrcpy(rel_name, newname);
4669 last_dirp = strrchr_m(rel_name, '/');
4671 last_dirp[1] = '\0';
4673 pstrcpy(rel_name, "./");
4675 pstrcat(rel_name, link_target);
4677 status = check_name(conn, rel_name);
4678 if (!NT_STATUS_IS_OK(status)) {
4683 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4684 newname, link_target ));
4686 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4687 return map_nt_error_from_unix(errno);
4690 return NT_STATUS_OK;
4693 /****************************************************************************
4694 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4695 ****************************************************************************/
4697 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4705 NTSTATUS status = NT_STATUS_OK;
4707 /* Set a hard link. */
4708 if (total_data == 0) {
4709 return NT_STATUS_INVALID_PARAMETER;
4712 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
4713 sizeof(oldname), total_data, STR_TERMINATE, &status);
4714 if (!NT_STATUS_IS_OK(status)) {
4718 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4719 if (!NT_STATUS_IS_OK(status)) {
4723 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4726 return hardlink_internals(conn, oldname, fname);
4729 /****************************************************************************
4730 Deal with SMB_FILE_RENAME_INFORMATION.
4731 ****************************************************************************/
4733 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4734 struct smb_request *req,
4747 BOOL dest_has_wcard = False;
4748 NTSTATUS status = NT_STATUS_OK;
4751 if (total_data < 13) {
4752 return NT_STATUS_INVALID_PARAMETER;
4755 overwrite = (CVAL(pdata,0) ? True : False);
4756 root_fid = IVAL(pdata,4);
4757 len = IVAL(pdata,8);
4759 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4760 return NT_STATUS_INVALID_PARAMETER;
4763 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
4764 sizeof(newname), len, 0, &status,
4766 if (!NT_STATUS_IS_OK(status)) {
4770 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4771 if (!NT_STATUS_IS_OK(status)) {
4775 /* Check the new name has no '/' characters. */
4776 if (strchr_m(newname, '/')) {
4777 return NT_STATUS_NOT_SUPPORTED;
4780 /* Create the base directory. */
4781 pstrcpy(base_name, fname);
4782 p = strrchr_m(base_name, '/');
4786 pstrcpy(base_name, "./");
4788 /* Append the new name. */
4789 pstrcat(base_name, newname);
4792 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4793 fsp->fnum, fsp->fsp_name, base_name ));
4794 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4796 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4798 status = rename_internals(conn, req, fname, base_name, 0,
4799 overwrite, False, dest_has_wcard);
4805 /****************************************************************************
4806 Deal with SMB_SET_POSIX_ACL.
4807 ****************************************************************************/
4809 #if defined(HAVE_POSIX_ACLS)
4810 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4815 SMB_STRUCT_STAT *psbuf)
4817 uint16 posix_acl_version;
4818 uint16 num_file_acls;
4819 uint16 num_def_acls;
4820 BOOL valid_file_acls = True;
4821 BOOL valid_def_acls = True;
4823 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4824 return NT_STATUS_INVALID_PARAMETER;
4826 posix_acl_version = SVAL(pdata,0);
4827 num_file_acls = SVAL(pdata,2);
4828 num_def_acls = SVAL(pdata,4);
4830 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4831 valid_file_acls = False;
4835 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4836 valid_def_acls = False;
4840 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4841 return NT_STATUS_INVALID_PARAMETER;
4844 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4845 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4846 return NT_STATUS_INVALID_PARAMETER;
4849 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4850 fname ? fname : fsp->fsp_name,
4851 (unsigned int)num_file_acls,
4852 (unsigned int)num_def_acls));
4854 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4855 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4856 return map_nt_error_from_unix(errno);
4859 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4860 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4861 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4862 return map_nt_error_from_unix(errno);
4864 return NT_STATUS_OK;
4868 /****************************************************************************
4869 Deal with SMB_SET_POSIX_LOCK.
4870 ****************************************************************************/
4872 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4880 SMB_BIG_UINT offset;
4882 BOOL blocking_lock = False;
4883 enum brl_type lock_type;
4884 NTSTATUS status = NT_STATUS_OK;
4886 if (fsp == NULL || fsp->fh->fd == -1) {
4887 return NT_STATUS_INVALID_HANDLE;
4890 if (total_data != POSIX_LOCK_DATA_SIZE) {
4891 return NT_STATUS_INVALID_PARAMETER;
4894 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4895 case POSIX_LOCK_TYPE_READ:
4896 lock_type = READ_LOCK;
4898 case POSIX_LOCK_TYPE_WRITE:
4899 /* Return the right POSIX-mappable error code for files opened read-only. */
4900 if (!fsp->can_write) {
4901 return NT_STATUS_INVALID_HANDLE;
4903 lock_type = WRITE_LOCK;
4905 case POSIX_LOCK_TYPE_UNLOCK:
4906 lock_type = UNLOCK_LOCK;
4909 return NT_STATUS_INVALID_PARAMETER;
4912 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4913 blocking_lock = False;
4914 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4915 blocking_lock = True;
4917 return NT_STATUS_INVALID_PARAMETER;
4920 if (!lp_blocking_locks(SNUM(conn))) {
4921 blocking_lock = False;
4924 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4925 #if defined(HAVE_LONGLONG)
4926 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4927 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4928 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4929 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4930 #else /* HAVE_LONGLONG */
4931 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4932 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4933 #endif /* HAVE_LONGLONG */
4935 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4936 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4938 (unsigned int)lock_type,
4939 (unsigned int)lock_pid,
4943 if (lock_type == UNLOCK_LOCK) {
4944 status = do_unlock(smbd_messaging_context(),
4951 uint32 block_smbpid;
4953 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4964 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4966 * A blocking lock was requested. Package up
4967 * this smb into a queued request and push it
4968 * onto the blocking lock queue.
4970 if(push_blocking_lock_request(br_lck,
4973 -1, /* infinite timeout. */
4981 TALLOC_FREE(br_lck);
4985 TALLOC_FREE(br_lck);
4991 /****************************************************************************
4992 Deal with SMB_INFO_STANDARD.
4993 ****************************************************************************/
4995 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5000 const SMB_STRUCT_STAT *psbuf)
5002 struct timespec ts[2];
5004 if (total_data < 12) {
5005 return NT_STATUS_INVALID_PARAMETER;
5009 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5011 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5013 DEBUG(10,("smb_set_info_standard: file %s\n",
5014 fname ? fname : fsp->fsp_name ));
5016 return smb_set_file_time(conn,
5023 /****************************************************************************
5024 Deal with SMB_SET_FILE_BASIC_INFO.
5025 ****************************************************************************/
5027 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5032 SMB_STRUCT_STAT *psbuf)
5034 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5035 struct timespec write_time;
5036 struct timespec changed_time;
5038 struct timespec ts[2];
5039 NTSTATUS status = NT_STATUS_OK;
5041 if (total_data < 36) {
5042 return NT_STATUS_INVALID_PARAMETER;
5045 /* Set the attributes */
5046 dosmode = IVAL(pdata,32);
5047 status = smb_set_file_dosmode(conn,
5051 if (!NT_STATUS_IS_OK(status)) {
5055 /* Ignore create time at offset pdata. */
5058 ts[0] = interpret_long_date(pdata+8);
5060 write_time = interpret_long_date(pdata+16);
5061 changed_time = interpret_long_date(pdata+24);
5064 ts[1] = timespec_min(&write_time, &changed_time);
5066 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5070 /* Prefer a defined time to an undefined one. */
5071 if (null_timespec(ts[1])) {
5072 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5075 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5076 fname ? fname : fsp->fsp_name ));
5078 return smb_set_file_time(conn,
5085 /****************************************************************************
5086 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5087 ****************************************************************************/
5089 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5090 struct smb_request *req,
5095 SMB_STRUCT_STAT *psbuf)
5097 SMB_BIG_UINT allocation_size = 0;
5098 NTSTATUS status = NT_STATUS_OK;
5099 files_struct *new_fsp = NULL;
5101 if (!VALID_STAT(*psbuf)) {
5102 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5105 if (total_data < 8) {
5106 return NT_STATUS_INVALID_PARAMETER;
5109 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5110 #ifdef LARGE_SMB_OFF_T
5111 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5112 #else /* LARGE_SMB_OFF_T */
5113 if (IVAL(pdata,4) != 0) {
5114 /* more than 32 bits? */
5115 return NT_STATUS_INVALID_PARAMETER;
5117 #endif /* LARGE_SMB_OFF_T */
5119 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5120 fname, (double)allocation_size ));
5122 if (allocation_size) {
5123 allocation_size = smb_roundup(conn, allocation_size);
5126 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5127 fname, (double)allocation_size ));
5129 if (fsp && fsp->fh->fd != -1) {
5130 /* Open file handle. */
5131 /* Only change if needed. */
5132 if (allocation_size != get_file_size(*psbuf)) {
5133 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5134 return map_nt_error_from_unix(errno);
5137 /* But always update the time. */
5138 if (null_timespec(fsp->pending_modtime)) {
5140 * This is equivalent to a write. Ensure it's seen immediately
5141 * if there are no pending writes.
5143 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5145 return NT_STATUS_OK;
5148 /* Pathname or stat or directory file. */
5150 status = open_file_ntcreate(conn, req, fname, psbuf,
5152 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5155 FILE_ATTRIBUTE_NORMAL,
5156 FORCE_OPLOCK_BREAK_TO_NONE,
5159 if (!NT_STATUS_IS_OK(status)) {
5160 /* NB. We check for open_was_deferred in the caller. */
5164 /* Only change if needed. */
5165 if (allocation_size != get_file_size(*psbuf)) {
5166 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5167 status = map_nt_error_from_unix(errno);
5168 close_file(new_fsp,NORMAL_CLOSE);
5173 /* Changing the allocation size should set the last mod time. */
5174 /* Don't need to call set_filetime as this will be flushed on
5177 fsp_set_pending_modtime(new_fsp, timespec_current());
5179 close_file(new_fsp,NORMAL_CLOSE);
5180 return NT_STATUS_OK;
5183 /****************************************************************************
5184 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5185 ****************************************************************************/
5187 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5188 struct smb_request *req,
5193 SMB_STRUCT_STAT *psbuf)
5197 if (total_data < 8) {
5198 return NT_STATUS_INVALID_PARAMETER;
5201 size = IVAL(pdata,0);
5202 #ifdef LARGE_SMB_OFF_T
5203 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5204 #else /* LARGE_SMB_OFF_T */
5205 if (IVAL(pdata,4) != 0) {
5206 /* more than 32 bits? */
5207 return NT_STATUS_INVALID_PARAMETER;
5209 #endif /* LARGE_SMB_OFF_T */
5210 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5211 "file %s to %.0f\n", fname, (double)size ));
5213 return smb_set_file_size(conn, req,
5220 /****************************************************************************
5221 Allow a UNIX info mknod.
5222 ****************************************************************************/
5224 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5228 SMB_STRUCT_STAT *psbuf)
5230 uint32 file_type = IVAL(pdata,56);
5231 #if defined(HAVE_MAKEDEV)
5232 uint32 dev_major = IVAL(pdata,60);
5233 uint32 dev_minor = IVAL(pdata,68);
5235 SMB_DEV_T dev = (SMB_DEV_T)0;
5236 uint32 raw_unixmode = IVAL(pdata,84);
5240 if (total_data < 100) {
5241 return NT_STATUS_INVALID_PARAMETER;
5244 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5245 if (!NT_STATUS_IS_OK(status)) {
5249 #if defined(HAVE_MAKEDEV)
5250 dev = makedev(dev_major, dev_minor);
5253 switch (file_type) {
5254 #if defined(S_IFIFO)
5255 case UNIX_TYPE_FIFO:
5256 unixmode |= S_IFIFO;
5259 #if defined(S_IFSOCK)
5260 case UNIX_TYPE_SOCKET:
5261 unixmode |= S_IFSOCK;
5264 #if defined(S_IFCHR)
5265 case UNIX_TYPE_CHARDEV:
5266 unixmode |= S_IFCHR;
5269 #if defined(S_IFBLK)
5270 case UNIX_TYPE_BLKDEV:
5271 unixmode |= S_IFBLK;
5275 return NT_STATUS_INVALID_PARAMETER;
5278 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5279 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5281 /* Ok - do the mknod. */
5282 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5283 return map_nt_error_from_unix(errno);
5286 /* If any of the other "set" calls fail we
5287 * don't want to end up with a half-constructed mknod.
5290 if (lp_inherit_perms(SNUM(conn))) {
5292 conn, parent_dirname(fname),
5296 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5297 status = map_nt_error_from_unix(errno);
5298 SMB_VFS_UNLINK(conn,fname);
5301 return NT_STATUS_OK;
5304 /****************************************************************************
5305 Deal with SMB_SET_FILE_UNIX_BASIC.
5306 ****************************************************************************/
5308 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5309 struct smb_request *req,
5314 SMB_STRUCT_STAT *psbuf)
5316 struct timespec ts[2];
5317 uint32 raw_unixmode;
5320 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5321 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5322 NTSTATUS status = NT_STATUS_OK;
5323 BOOL delete_on_fail = False;
5324 enum perm_type ptype;
5326 if (total_data < 100) {
5327 return NT_STATUS_INVALID_PARAMETER;
5330 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5331 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5332 size=IVAL(pdata,0); /* first 8 Bytes are size */
5333 #ifdef LARGE_SMB_OFF_T
5334 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5335 #else /* LARGE_SMB_OFF_T */
5336 if (IVAL(pdata,4) != 0) {
5337 /* more than 32 bits? */
5338 return NT_STATUS_INVALID_PARAMETER;
5340 #endif /* LARGE_SMB_OFF_T */
5343 ts[0] = interpret_long_date(pdata+24); /* access_time */
5344 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5345 set_owner = (uid_t)IVAL(pdata,40);
5346 set_grp = (gid_t)IVAL(pdata,48);
5347 raw_unixmode = IVAL(pdata,84);
5349 if (VALID_STAT(*psbuf)) {
5350 if (S_ISDIR(psbuf->st_mode)) {
5351 ptype = PERM_EXISTING_DIR;
5353 ptype = PERM_EXISTING_FILE;
5356 ptype = PERM_NEW_FILE;
5359 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5360 if (!NT_STATUS_IS_OK(status)) {
5364 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5365 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5366 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5368 if (!VALID_STAT(*psbuf)) {
5370 * The only valid use of this is to create character and block
5371 * devices, and named pipes. This is deprecated (IMHO) and
5372 * a new info level should be used for mknod. JRA.
5375 status = smb_unix_mknod(conn,
5380 if (!NT_STATUS_IS_OK(status)) {
5384 /* Ensure we don't try and change anything else. */
5385 raw_unixmode = SMB_MODE_NO_CHANGE;
5386 size = get_file_size(*psbuf);
5387 ts[0] = get_atimespec(psbuf);
5388 ts[1] = get_mtimespec(psbuf);
5390 * We continue here as we might want to change the
5393 delete_on_fail = True;
5397 /* Horrible backwards compatibility hack as an old server bug
5398 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5402 size = get_file_size(*psbuf);
5407 * Deal with the UNIX specific mode set.
5410 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5411 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5412 (unsigned int)unixmode, fname ));
5413 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5414 return map_nt_error_from_unix(errno);
5419 * Deal with the UNIX specific uid set.
5422 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5425 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5426 (unsigned int)set_owner, fname ));
5428 if (S_ISLNK(psbuf->st_mode)) {
5429 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5431 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5435 status = map_nt_error_from_unix(errno);
5436 if (delete_on_fail) {
5437 SMB_VFS_UNLINK(conn,fname);
5444 * Deal with the UNIX specific gid set.
5447 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5448 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5449 (unsigned int)set_owner, fname ));
5450 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5451 status = map_nt_error_from_unix(errno);
5452 if (delete_on_fail) {
5453 SMB_VFS_UNLINK(conn,fname);
5459 /* Deal with any size changes. */
5461 status = smb_set_file_size(conn, req,
5466 if (!NT_STATUS_IS_OK(status)) {
5470 /* Deal with any time changes. */
5472 return smb_set_file_time(conn,
5479 /****************************************************************************
5480 Deal with SMB_SET_FILE_UNIX_INFO2.
5481 ****************************************************************************/
5483 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5484 struct smb_request *req,
5489 SMB_STRUCT_STAT *psbuf)
5495 if (total_data < 116) {
5496 return NT_STATUS_INVALID_PARAMETER;
5499 /* Start by setting all the fields that are common between UNIX_BASIC
5502 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5504 if (!NT_STATUS_IS_OK(status)) {
5508 smb_fflags = IVAL(pdata, 108);
5509 smb_fmask = IVAL(pdata, 112);
5511 /* NB: We should only attempt to alter the file flags if the client
5512 * sends a non-zero mask.
5514 if (smb_fmask != 0) {
5515 int stat_fflags = 0;
5517 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5519 /* Client asked to alter a flag we don't understand. */
5520 return NT_STATUS_INVALID_PARAMETER;
5523 if (fsp && fsp->fh->fd != -1) {
5524 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5525 return NT_STATUS_NOT_SUPPORTED;
5527 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5528 return map_nt_error_from_unix(errno);
5533 /* XXX: need to add support for changing the create_time here. You
5534 * can do this for paths on Darwin with setattrlist(2). The right way
5535 * to hook this up is probably by extending the VFS utimes interface.
5538 return NT_STATUS_OK;
5541 /****************************************************************************
5542 Create a directory with POSIX semantics.
5543 ****************************************************************************/
5545 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5546 struct smb_request *req,
5550 SMB_STRUCT_STAT *psbuf,
5551 int *pdata_return_size)
5553 NTSTATUS status = NT_STATUS_OK;
5554 uint32 raw_unixmode = 0;
5555 uint32 mod_unixmode = 0;
5556 mode_t unixmode = (mode_t)0;
5557 files_struct *fsp = NULL;
5558 uint16 info_level_return = 0;
5560 char *pdata = *ppdata;
5562 if (total_data < 18) {
5563 return NT_STATUS_INVALID_PARAMETER;
5566 raw_unixmode = IVAL(pdata,8);
5567 /* Next 4 bytes are not yet defined. */
5569 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5570 if (!NT_STATUS_IS_OK(status)) {
5574 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5576 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5577 fname, (unsigned int)unixmode ));
5579 status = open_directory(conn, req,
5582 FILE_READ_ATTRIBUTES, /* Just a stat open */
5583 FILE_SHARE_NONE, /* Ignored for stat opens */
5590 if (NT_STATUS_IS_OK(status)) {
5591 close_file(fsp, NORMAL_CLOSE);
5594 info_level_return = SVAL(pdata,16);
5596 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5597 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5598 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5599 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5601 *pdata_return_size = 12;
5604 /* Realloc the data size */
5605 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5606 if (*ppdata == NULL) {
5607 *pdata_return_size = 0;
5608 return NT_STATUS_NO_MEMORY;
5612 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5613 SSVAL(pdata,2,0); /* No fnum. */
5614 SIVAL(pdata,4,info); /* Was directory created. */
5616 switch (info_level_return) {
5617 case SMB_QUERY_FILE_UNIX_BASIC:
5618 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5619 SSVAL(pdata,10,0); /* Padding. */
5620 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5622 case SMB_QUERY_FILE_UNIX_INFO2:
5623 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5624 SSVAL(pdata,10,0); /* Padding. */
5625 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5628 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5629 SSVAL(pdata,10,0); /* Padding. */
5636 /****************************************************************************
5637 Open/Create a file with POSIX semantics.
5638 ****************************************************************************/
5640 static NTSTATUS smb_posix_open(connection_struct *conn,
5641 struct smb_request *req,
5645 SMB_STRUCT_STAT *psbuf,
5646 int *pdata_return_size)
5648 BOOL extended_oplock_granted = False;
5649 char *pdata = *ppdata;
5651 uint32 wire_open_mode = 0;
5652 uint32 raw_unixmode = 0;
5653 uint32 mod_unixmode = 0;
5654 uint32 create_disp = 0;
5655 uint32 access_mask = 0;
5656 uint32 create_options = 0;
5657 NTSTATUS status = NT_STATUS_OK;
5658 mode_t unixmode = (mode_t)0;
5659 files_struct *fsp = NULL;
5660 int oplock_request = 0;
5662 uint16 info_level_return = 0;
5664 if (total_data < 18) {
5665 return NT_STATUS_INVALID_PARAMETER;
5668 flags = IVAL(pdata,0);
5669 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5670 if (oplock_request) {
5671 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5674 wire_open_mode = IVAL(pdata,4);
5676 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5677 return smb_posix_mkdir(conn, req,
5685 switch (wire_open_mode & SMB_ACCMODE) {
5687 access_mask = FILE_READ_DATA;
5690 access_mask = FILE_WRITE_DATA;
5693 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5696 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5697 (unsigned int)wire_open_mode ));
5698 return NT_STATUS_INVALID_PARAMETER;
5701 wire_open_mode &= ~SMB_ACCMODE;
5703 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5704 create_disp = FILE_CREATE;
5705 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5706 create_disp = FILE_OVERWRITE_IF;
5707 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5708 create_disp = FILE_OPEN_IF;
5710 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5711 (unsigned int)wire_open_mode ));
5712 return NT_STATUS_INVALID_PARAMETER;
5715 raw_unixmode = IVAL(pdata,8);
5716 /* Next 4 bytes are not yet defined. */
5718 status = unix_perms_from_wire(conn,
5721 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5724 if (!NT_STATUS_IS_OK(status)) {
5728 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5730 if (wire_open_mode & SMB_O_SYNC) {
5731 create_options |= FILE_WRITE_THROUGH;
5733 if (wire_open_mode & SMB_O_APPEND) {
5734 access_mask |= FILE_APPEND_DATA;
5736 if (wire_open_mode & SMB_O_DIRECT) {
5737 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5740 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5742 (unsigned int)wire_open_mode,
5743 (unsigned int)unixmode ));
5745 status = open_file_ntcreate(conn, req,
5749 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5751 0, /* no create options yet. */
5757 if (!NT_STATUS_IS_OK(status)) {
5761 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5762 extended_oplock_granted = True;
5765 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5766 extended_oplock_granted = True;
5769 info_level_return = SVAL(pdata,16);
5771 /* Allocate the correct return size. */
5773 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5774 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5775 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5776 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5778 *pdata_return_size = 12;
5781 /* Realloc the data size */
5782 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5783 if (*ppdata == NULL) {
5784 close_file(fsp,ERROR_CLOSE);
5785 *pdata_return_size = 0;
5786 return NT_STATUS_NO_MEMORY;
5790 if (extended_oplock_granted) {
5791 if (flags & REQUEST_BATCH_OPLOCK) {
5792 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5794 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5796 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5797 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5799 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5802 SSVAL(pdata,2,fsp->fnum);
5803 SIVAL(pdata,4,info); /* Was file created etc. */
5805 switch (info_level_return) {
5806 case SMB_QUERY_FILE_UNIX_BASIC:
5807 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5808 SSVAL(pdata,10,0); /* padding. */
5809 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5811 case SMB_QUERY_FILE_UNIX_INFO2:
5812 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5813 SSVAL(pdata,10,0); /* padding. */
5814 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5817 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5818 SSVAL(pdata,10,0); /* padding. */
5821 return NT_STATUS_OK;
5824 /****************************************************************************
5825 Delete a file with POSIX semantics.
5826 ****************************************************************************/
5828 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5829 struct smb_request *req,
5833 SMB_STRUCT_STAT *psbuf)
5835 NTSTATUS status = NT_STATUS_OK;
5836 files_struct *fsp = NULL;
5841 struct share_mode_lock *lck = NULL;
5843 if (total_data < 2) {
5844 return NT_STATUS_INVALID_PARAMETER;
5847 flags = SVAL(pdata,0);
5849 if (!VALID_STAT(*psbuf)) {
5850 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5853 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5854 !VALID_STAT_OF_DIR(*psbuf)) {
5855 return NT_STATUS_NOT_A_DIRECTORY;
5858 DEBUG(10,("smb_posix_unlink: %s %s\n",
5859 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5862 if (VALID_STAT_OF_DIR(*psbuf)) {
5863 status = open_directory(conn, req,
5867 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5870 FILE_FLAG_POSIX_SEMANTICS|0777,
5875 status = open_file_ntcreate(conn, req,
5879 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5882 FILE_FLAG_POSIX_SEMANTICS|0777,
5883 0, /* No oplock, but break existing ones. */
5888 if (!NT_STATUS_IS_OK(status)) {
5893 * Don't lie to client. If we can't really delete due to
5894 * non-POSIX opens return SHARING_VIOLATION.
5897 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5899 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5900 "lock for file %s\n", fsp->fsp_name));
5901 close_file(fsp, NORMAL_CLOSE);
5902 return NT_STATUS_INVALID_PARAMETER;
5906 * See if others still have the file open. If this is the case, then
5907 * don't delete. If all opens are POSIX delete we can set the delete
5908 * on close disposition.
5910 for (i=0; i<lck->num_share_modes; i++) {
5911 struct share_mode_entry *e = &lck->share_modes[i];
5912 if (is_valid_share_mode_entry(e)) {
5913 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5916 /* Fail with sharing violation. */
5917 close_file(fsp, NORMAL_CLOSE);
5919 return NT_STATUS_SHARING_VIOLATION;
5924 * Set the delete on close.
5926 status = smb_set_file_disposition_info(conn,
5933 if (!NT_STATUS_IS_OK(status)) {
5934 close_file(fsp, NORMAL_CLOSE);
5939 return close_file(fsp, NORMAL_CLOSE);
5942 /****************************************************************************
5943 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5944 ****************************************************************************/
5946 static int call_trans2setfilepathinfo(connection_struct *conn,
5947 struct smb_request *req,
5948 char *inbuf, char *outbuf, int length,
5950 unsigned int tran_call,
5951 char **pparams, int total_params, char **ppdata, int total_data,
5952 unsigned int max_data_bytes)
5954 char *params = *pparams;
5955 char *pdata = *ppdata;
5957 SMB_STRUCT_STAT sbuf;
5959 files_struct *fsp = NULL;
5960 NTSTATUS status = NT_STATUS_OK;
5961 int data_return_size = 0;
5964 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5969 if (tran_call == TRANSACT2_SETFILEINFO) {
5970 if (total_params < 4) {
5971 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5974 fsp = file_fsp(SVAL(params,0));
5975 info_level = SVAL(params,2);
5977 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5979 * This is actually a SETFILEINFO on a directory
5980 * handle (returned from an NT SMB). NT5.0 seems
5981 * to do this call. JRA.
5983 pstrcpy(fname, fsp->fsp_name);
5984 if (INFO_LEVEL_IS_UNIX(info_level)) {
5985 /* Always do lstat for UNIX calls. */
5986 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5987 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5988 return UNIXERROR(ERRDOS,ERRbadpath);
5991 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5992 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5993 return UNIXERROR(ERRDOS,ERRbadpath);
5996 } else if (fsp && fsp->print_file) {
5998 * Doing a DELETE_ON_CLOSE should cancel a print job.
6000 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6001 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6003 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6006 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6009 return (UNIXERROR(ERRDOS,ERRbadpath));
6012 * Original code - this is an open file.
6014 CHECK_FSP(fsp,conn);
6016 pstrcpy(fname, fsp->fsp_name);
6018 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6019 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6020 return(UNIXERROR(ERRDOS,ERRbadfid));
6025 if (total_params < 7) {
6026 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6029 info_level = SVAL(params,0);
6030 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
6031 sizeof(fname), total_params - 6, STR_TERMINATE,
6033 if (!NT_STATUS_IS_OK(status)) {
6034 return ERROR_NT(status);
6037 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
6038 if (!NT_STATUS_IS_OK(status)) {
6039 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6040 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6042 return ERROR_NT(status);
6045 status = unix_convert(conn, fname, False, NULL, &sbuf);
6046 if (!NT_STATUS_IS_OK(status)) {
6047 return ERROR_NT(status);
6050 status = check_name(conn, fname);
6051 if (!NT_STATUS_IS_OK(status)) {
6052 return ERROR_NT(status);
6055 if (INFO_LEVEL_IS_UNIX(info_level)) {
6057 * For CIFS UNIX extensions the target name may not exist.
6060 /* Always do lstat for UNIX calls. */
6061 SMB_VFS_LSTAT(conn,fname,&sbuf);
6063 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6064 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6065 return UNIXERROR(ERRDOS,ERRbadpath);
6069 if (!CAN_WRITE(conn)) {
6070 return ERROR_DOS(ERRSRV,ERRaccess);
6073 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6074 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6077 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6078 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6080 /* Realloc the parameter size */
6081 *pparams = (char *)SMB_REALLOC(*pparams,2);
6082 if (*pparams == NULL) {
6083 return ERROR_NT(NT_STATUS_NO_MEMORY);
6089 if (fsp && !null_timespec(fsp->pending_modtime)) {
6090 /* the pending modtime overrides the current modtime */
6091 set_mtimespec(&sbuf, fsp->pending_modtime);
6094 switch (info_level) {
6096 case SMB_INFO_STANDARD:
6098 status = smb_set_info_standard(conn,
6107 case SMB_INFO_SET_EA:
6109 status = smb_info_set_ea(conn,
6117 case SMB_SET_FILE_BASIC_INFO:
6118 case SMB_FILE_BASIC_INFORMATION:
6120 status = smb_set_file_basic_info(conn,
6129 case SMB_FILE_ALLOCATION_INFORMATION:
6130 case SMB_SET_FILE_ALLOCATION_INFO:
6132 status = smb_set_file_allocation_info(conn, req,
6141 case SMB_FILE_END_OF_FILE_INFORMATION:
6142 case SMB_SET_FILE_END_OF_FILE_INFO:
6144 status = smb_set_file_end_of_file_info(conn, req,
6153 case SMB_FILE_DISPOSITION_INFORMATION:
6154 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6157 /* JRA - We used to just ignore this on a path ?
6158 * Shouldn't this be invalid level on a pathname
6161 if (tran_call != TRANSACT2_SETFILEINFO) {
6162 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6165 status = smb_set_file_disposition_info(conn,
6174 case SMB_FILE_POSITION_INFORMATION:
6176 status = smb_file_position_information(conn,
6183 /* From tridge Samba4 :
6184 * MODE_INFORMATION in setfileinfo (I have no
6185 * idea what "mode information" on a file is - it takes a value of 0,
6186 * 2, 4 or 6. What could it be?).
6189 case SMB_FILE_MODE_INFORMATION:
6191 status = smb_file_mode_information(conn,
6198 * CIFS UNIX extensions.
6201 case SMB_SET_FILE_UNIX_BASIC:
6203 status = smb_set_file_unix_basic(conn, req,
6212 case SMB_SET_FILE_UNIX_INFO2:
6214 status = smb_set_file_unix_info2(conn, req,
6223 case SMB_SET_FILE_UNIX_LINK:
6225 if (tran_call != TRANSACT2_SETPATHINFO) {
6226 /* We must have a pathname for this. */
6227 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6229 status = smb_set_file_unix_link(conn,
6237 case SMB_SET_FILE_UNIX_HLINK:
6239 if (tran_call != TRANSACT2_SETPATHINFO) {
6240 /* We must have a pathname for this. */
6241 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6243 status = smb_set_file_unix_hlink(conn,
6252 case SMB_FILE_RENAME_INFORMATION:
6254 status = smb_file_rename_information(conn, req,
6264 #if defined(HAVE_POSIX_ACLS)
6265 case SMB_SET_POSIX_ACL:
6267 status = smb_set_posix_acl(conn,
6277 case SMB_SET_POSIX_LOCK:
6279 if (tran_call != TRANSACT2_SETFILEINFO) {
6280 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6282 status = smb_set_posix_lock(conn,
6291 case SMB_POSIX_PATH_OPEN:
6293 if (tran_call != TRANSACT2_SETPATHINFO) {
6294 /* We must have a pathname for this. */
6295 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6298 status = smb_posix_open(conn, req,
6307 case SMB_POSIX_PATH_UNLINK:
6309 if (tran_call != TRANSACT2_SETPATHINFO) {
6310 /* We must have a pathname for this. */
6311 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6314 status = smb_posix_unlink(conn, req,
6323 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6327 if (!NT_STATUS_IS_OK(status)) {
6328 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6329 /* We have re-scheduled this call. */
6332 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6333 /* We have re-scheduled this call. */
6336 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6337 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6339 return ERROR_NT(status);
6343 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6348 /****************************************************************************
6349 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6350 ****************************************************************************/
6352 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6353 char **pparams, int total_params, char **ppdata, int total_data,
6354 unsigned int max_data_bytes)
6356 char *params = *pparams;
6357 char *pdata = *ppdata;
6359 SMB_STRUCT_STAT sbuf;
6360 NTSTATUS status = NT_STATUS_OK;
6361 struct ea_list *ea_list = NULL;
6363 if (!CAN_WRITE(conn))
6364 return ERROR_DOS(ERRSRV,ERRaccess);
6366 if (total_params < 5) {
6367 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6370 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, ¶ms[4],
6371 sizeof(directory), total_params - 4, STR_TERMINATE,
6373 if (!NT_STATUS_IS_OK(status)) {
6374 return ERROR_NT(status);
6377 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6379 status = unix_convert(conn, directory, False, NULL, &sbuf);
6380 if (!NT_STATUS_IS_OK(status)) {
6381 return ERROR_NT(status);
6384 status = check_name(conn, directory);
6385 if (!NT_STATUS_IS_OK(status)) {
6386 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6387 return ERROR_NT(status);
6390 /* Any data in this call is an EA list. */
6391 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6392 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6396 * OS/2 workplace shell seems to send SET_EA requests of "null"
6397 * length (4 bytes containing IVAL 4).
6398 * They seem to have no effect. Bug #3212. JRA.
6401 if (total_data != 4) {
6402 if (total_data < 10) {
6403 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6406 if (IVAL(pdata,0) > total_data) {
6407 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6408 IVAL(pdata,0), (unsigned int)total_data));
6409 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6412 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6415 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6417 } else if (IVAL(pdata,0) != 4) {
6418 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6421 status = create_directory(conn, directory);
6423 if (!NT_STATUS_IS_OK(status)) {
6424 return ERROR_NT(status);
6427 /* Try and set any given EA. */
6429 status = set_ea(conn, NULL, directory, ea_list);
6430 if (!NT_STATUS_IS_OK(status)) {
6431 return ERROR_NT(status);
6435 /* Realloc the parameter and data sizes */
6436 *pparams = (char *)SMB_REALLOC(*pparams,2);
6437 if(*pparams == NULL) {
6438 return ERROR_NT(NT_STATUS_NO_MEMORY);
6444 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6449 /****************************************************************************
6450 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6451 We don't actually do this - we just send a null response.
6452 ****************************************************************************/
6454 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6455 char **pparams, int total_params, char **ppdata, int total_data,
6456 unsigned int max_data_bytes)
6458 static uint16 fnf_handle = 257;
6459 char *params = *pparams;
6462 if (total_params < 6) {
6463 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6466 info_level = SVAL(params,4);
6467 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6469 switch (info_level) {
6474 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6477 /* Realloc the parameter and data sizes */
6478 *pparams = (char *)SMB_REALLOC(*pparams,6);
6479 if (*pparams == NULL) {
6480 return ERROR_NT(NT_STATUS_NO_MEMORY);
6484 SSVAL(params,0,fnf_handle);
6485 SSVAL(params,2,0); /* No changes */
6486 SSVAL(params,4,0); /* No EA errors */
6493 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6498 /****************************************************************************
6499 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6500 changes). Currently this does nothing.
6501 ****************************************************************************/
6503 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6504 char **pparams, int total_params, char **ppdata, int total_data,
6505 unsigned int max_data_bytes)
6507 char *params = *pparams;
6509 DEBUG(3,("call_trans2findnotifynext\n"));
6511 /* Realloc the parameter and data sizes */
6512 *pparams = (char *)SMB_REALLOC(*pparams,4);
6513 if (*pparams == NULL) {
6514 return ERROR_NT(NT_STATUS_NO_MEMORY);
6518 SSVAL(params,0,0); /* No changes */
6519 SSVAL(params,2,0); /* No EA errors */
6521 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6526 /****************************************************************************
6527 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6528 ****************************************************************************/
6530 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6531 char **pparams, int total_params, char **ppdata, int total_data,
6532 unsigned int max_data_bytes)
6534 char *params = *pparams;
6537 int max_referral_level;
6538 NTSTATUS status = NT_STATUS_OK;
6540 DEBUG(10,("call_trans2getdfsreferral\n"));
6542 if (total_params < 3) {
6543 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6546 max_referral_level = SVAL(params,0);
6548 if(!lp_host_msdfs())
6549 return ERROR_DOS(ERRDOS,ERRbadfunc);
6551 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2],
6552 sizeof(pathname), total_params - 2, STR_TERMINATE);
6553 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6554 return ERROR_NT(status);
6556 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6557 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6562 #define LMCAT_SPL 0x53
6563 #define LMFUNC_GETJOBID 0x60
6565 /****************************************************************************
6566 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6567 ****************************************************************************/
6569 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6570 char **pparams, int total_params, char **ppdata, int total_data,
6571 unsigned int max_data_bytes)
6573 char *pdata = *ppdata;
6574 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv15));
6576 /* check for an invalid fid before proceeding */
6579 return(ERROR_DOS(ERRDOS,ERRbadfid));
6581 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6582 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6583 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6584 if (*ppdata == NULL) {
6585 return ERROR_NT(NT_STATUS_NO_MEMORY);
6589 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6590 CAN ACCEPT THIS IN UNICODE. JRA. */
6592 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6593 srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata + 2,
6594 global_myname(), 15,
6595 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6596 srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata+18,
6597 lp_servicename(SNUM(conn)), 13,
6598 STR_ASCII|STR_TERMINATE); /* Service name */
6599 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6602 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6603 return ERROR_DOS(ERRSRV,ERRerror);
6607 /****************************************************************************
6608 Reply to a SMBfindclose (stop trans2 directory search).
6609 ****************************************************************************/
6611 int reply_findclose(connection_struct *conn,
6612 char *inbuf,char *outbuf,int length,int bufsize)
6615 int dptr_num=SVALS(inbuf,smb_vwv0);
6616 START_PROFILE(SMBfindclose);
6618 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6620 dptr_close(&dptr_num);
6622 outsize = set_message(inbuf, outbuf,0,0,False);
6624 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6626 END_PROFILE(SMBfindclose);
6630 /****************************************************************************
6631 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6632 ****************************************************************************/
6634 int reply_findnclose(connection_struct *conn,
6635 char *inbuf,char *outbuf,int length,int bufsize)
6639 START_PROFILE(SMBfindnclose);
6641 dptr_num = SVAL(inbuf,smb_vwv0);
6643 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6645 /* We never give out valid handles for a
6646 findnotifyfirst - so any dptr_num is ok here.
6649 outsize = set_message(inbuf, outbuf,0,0,False);
6651 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6653 END_PROFILE(SMBfindnclose);
6657 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6658 struct trans_state *state,
6659 char *inbuf, char *outbuf, int size, int bufsize)
6663 if (Protocol >= PROTOCOL_NT1) {
6664 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6667 /* Now we must call the relevant TRANS2 function */
6668 switch(state->call) {
6669 case TRANSACT2_OPEN:
6671 START_PROFILE(Trans2_open);
6672 call_trans2open(conn, req,
6673 &state->param, state->total_param,
6674 &state->data, state->total_data,
6675 state->max_data_return);
6676 END_PROFILE(Trans2_open);
6680 case TRANSACT2_FINDFIRST:
6682 START_PROFILE(Trans2_findfirst);
6683 call_trans2findfirst(conn, req,
6684 &state->param, state->total_param,
6685 &state->data, state->total_data,
6686 state->max_data_return);
6687 END_PROFILE(Trans2_findfirst);
6691 case TRANSACT2_FINDNEXT:
6693 START_PROFILE(Trans2_findnext);
6694 outsize = call_trans2findnext(
6695 conn, inbuf, outbuf, size, bufsize,
6696 &state->param, state->total_param,
6697 &state->data, state->total_data,
6698 state->max_data_return);
6699 END_PROFILE(Trans2_findnext);
6703 case TRANSACT2_QFSINFO:
6705 START_PROFILE(Trans2_qfsinfo);
6706 outsize = call_trans2qfsinfo(
6707 conn, inbuf, outbuf, size, bufsize,
6708 &state->param, state->total_param,
6709 &state->data, state->total_data,
6710 state->max_data_return);
6711 END_PROFILE(Trans2_qfsinfo);
6715 case TRANSACT2_SETFSINFO:
6717 START_PROFILE(Trans2_setfsinfo);
6718 outsize = call_trans2setfsinfo(
6719 conn, inbuf, outbuf, size, bufsize,
6720 &state->param, state->total_param,
6721 &state->data, state->total_data,
6722 state->max_data_return);
6723 END_PROFILE(Trans2_setfsinfo);
6727 case TRANSACT2_QPATHINFO:
6728 case TRANSACT2_QFILEINFO:
6730 START_PROFILE(Trans2_qpathinfo);
6731 outsize = call_trans2qfilepathinfo(
6732 conn, inbuf, outbuf, size, bufsize, state->call,
6733 &state->param, state->total_param,
6734 &state->data, state->total_data,
6735 state->max_data_return);
6736 END_PROFILE(Trans2_qpathinfo);
6740 case TRANSACT2_SETPATHINFO:
6741 case TRANSACT2_SETFILEINFO:
6743 START_PROFILE(Trans2_setpathinfo);
6744 outsize = call_trans2setfilepathinfo(
6745 conn, req, inbuf, outbuf, size, bufsize, state->call,
6746 &state->param, state->total_param,
6747 &state->data, state->total_data,
6748 state->max_data_return);
6749 END_PROFILE(Trans2_setpathinfo);
6753 case TRANSACT2_FINDNOTIFYFIRST:
6755 START_PROFILE(Trans2_findnotifyfirst);
6756 outsize = call_trans2findnotifyfirst(
6757 conn, inbuf, outbuf, size, bufsize,
6758 &state->param, state->total_param,
6759 &state->data, state->total_data,
6760 state->max_data_return);
6761 END_PROFILE(Trans2_findnotifyfirst);
6765 case TRANSACT2_FINDNOTIFYNEXT:
6767 START_PROFILE(Trans2_findnotifynext);
6768 outsize = call_trans2findnotifynext(
6769 conn, inbuf, outbuf, size, bufsize,
6770 &state->param, state->total_param,
6771 &state->data, state->total_data,
6772 state->max_data_return);
6773 END_PROFILE(Trans2_findnotifynext);
6777 case TRANSACT2_MKDIR:
6779 START_PROFILE(Trans2_mkdir);
6780 outsize = call_trans2mkdir(
6781 conn, inbuf, outbuf, size, bufsize,
6782 &state->param, state->total_param,
6783 &state->data, state->total_data,
6784 state->max_data_return);
6785 END_PROFILE(Trans2_mkdir);
6789 case TRANSACT2_GET_DFS_REFERRAL:
6791 START_PROFILE(Trans2_get_dfs_referral);
6792 outsize = call_trans2getdfsreferral(
6793 conn, inbuf, outbuf, size, bufsize,
6794 &state->param, state->total_param,
6795 &state->data, state->total_data,
6796 state->max_data_return);
6797 END_PROFILE(Trans2_get_dfs_referral);
6801 case TRANSACT2_IOCTL:
6803 START_PROFILE(Trans2_ioctl);
6804 outsize = call_trans2ioctl(
6805 conn, inbuf, outbuf, size, bufsize,
6806 &state->param, state->total_param,
6807 &state->data, state->total_data,
6808 state->max_data_return);
6809 END_PROFILE(Trans2_ioctl);
6814 /* Error in request */
6815 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6816 outsize = ERROR_DOS(ERRSRV,ERRerror);
6822 /****************************************************************************
6823 Reply to a SMBtrans2.
6824 ****************************************************************************/
6826 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6827 int size, int bufsize)
6830 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6831 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6832 unsigned int psoff = SVAL(inbuf, smb_psoff);
6833 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6834 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6835 struct trans_state *state;
6838 START_PROFILE(SMBtrans2);
6840 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6841 if (!NT_STATUS_IS_OK(result)) {
6842 DEBUG(2, ("Got invalid trans2 request: %s\n",
6843 nt_errstr(result)));
6844 END_PROFILE(SMBtrans2);
6845 return ERROR_NT(result);
6848 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6849 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6850 && (tran_call != TRANSACT2_QFILEINFO)) {
6851 END_PROFILE(SMBtrans2);
6852 return ERROR_DOS(ERRSRV,ERRaccess);
6855 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6856 DEBUG(0, ("talloc failed\n"));
6857 END_PROFILE(SMBtrans2);
6858 return ERROR_NT(NT_STATUS_NO_MEMORY);
6861 state->cmd = SMBtrans2;
6863 state->mid = SVAL(inbuf, smb_mid);
6864 state->vuid = SVAL(inbuf, smb_uid);
6865 state->setup_count = SVAL(inbuf, smb_suwcnt);
6866 state->setup = NULL;
6867 state->total_param = SVAL(inbuf, smb_tpscnt);
6868 state->param = NULL;
6869 state->total_data = SVAL(inbuf, smb_tdscnt);
6871 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6872 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6873 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6874 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6875 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6877 state->call = tran_call;
6879 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6880 is so as a sanity check */
6881 if (state->setup_count != 1) {
6883 * Need to have rc=0 for ioctl to get job id for OS/2.
6884 * Network printing will fail if function is not successful.
6885 * Similar function in reply.c will be used if protocol
6886 * is LANMAN1.0 instead of LM1.2X002.
6887 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6888 * outbuf doesn't have to be set(only job id is used).
6890 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6891 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6892 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6893 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6895 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6896 DEBUG(2,("Transaction is %d\n",tran_call));
6898 END_PROFILE(SMBtrans2);
6899 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6903 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6906 if (state->total_data) {
6907 /* Can't use talloc here, the core routines do realloc on the
6908 * params and data. */
6909 state->data = (char *)SMB_MALLOC(state->total_data);
6910 if (state->data == NULL) {
6911 DEBUG(0,("reply_trans2: data malloc fail for %u "
6912 "bytes !\n", (unsigned int)state->total_data));
6914 END_PROFILE(SMBtrans2);
6915 return(ERROR_DOS(ERRDOS,ERRnomem));
6917 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6919 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6920 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6923 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6926 if (state->total_param) {
6927 /* Can't use talloc here, the core routines do realloc on the
6928 * params and data. */
6929 state->param = (char *)SMB_MALLOC(state->total_param);
6930 if (state->param == NULL) {
6931 DEBUG(0,("reply_trans: param malloc fail for %u "
6932 "bytes !\n", (unsigned int)state->total_param));
6933 SAFE_FREE(state->data);
6935 END_PROFILE(SMBtrans2);
6936 return(ERROR_DOS(ERRDOS,ERRnomem));
6938 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6940 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6941 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6944 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6947 state->received_data = dscnt;
6948 state->received_param = pscnt;
6950 if ((state->received_param == state->total_param) &&
6951 (state->received_data == state->total_data)) {
6953 struct smb_request *req;
6955 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
6956 END_PROFILE(SMBtrans2);
6957 return ERROR_NT(NT_STATUS_NO_MEMORY);
6960 init_smb_request(req, (uint8 *)inbuf);
6962 outsize = handle_trans2(conn, req, state, inbuf, outbuf,
6964 if (req->outbuf != NULL) {
6965 outsize = smb_len(req->outbuf) + 4;
6966 memcpy(outbuf, req->outbuf, outsize);
6969 SAFE_FREE(state->data);
6970 SAFE_FREE(state->param);
6972 END_PROFILE(SMBtrans2);
6976 DLIST_ADD(conn->pending_trans, state);
6978 /* We need to send an interim response then receive the rest
6979 of the parameter/data bytes */
6980 outsize = set_message(inbuf, outbuf,0,0,False);
6982 END_PROFILE(SMBtrans2);
6987 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6988 SAFE_FREE(state->data);
6989 SAFE_FREE(state->param);
6991 END_PROFILE(SMBtrans2);
6992 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6996 /****************************************************************************
6997 Reply to a SMBtranss2
6998 ****************************************************************************/
7000 int reply_transs2(connection_struct *conn,
7001 char *inbuf,char *outbuf,int size,int bufsize)
7004 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7005 struct trans_state *state;
7006 struct smb_request *req;
7008 START_PROFILE(SMBtranss2);
7012 for (state = conn->pending_trans; state != NULL;
7013 state = state->next) {
7014 if (state->mid == SVAL(inbuf,smb_mid)) {
7019 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7020 END_PROFILE(SMBtranss2);
7021 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7024 /* Revise state->total_param and state->total_data in case they have
7025 changed downwards */
7027 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
7028 state->total_param = SVAL(inbuf, smb_tpscnt);
7029 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
7030 state->total_data = SVAL(inbuf, smb_tdscnt);
7032 pcnt = SVAL(inbuf, smb_spscnt);
7033 poff = SVAL(inbuf, smb_spsoff);
7034 pdisp = SVAL(inbuf, smb_spsdisp);
7036 dcnt = SVAL(inbuf, smb_sdscnt);
7037 doff = SVAL(inbuf, smb_sdsoff);
7038 ddisp = SVAL(inbuf, smb_sdsdisp);
7040 state->received_param += pcnt;
7041 state->received_data += dcnt;
7043 if ((state->received_data > state->total_data) ||
7044 (state->received_param > state->total_param))
7048 if (pdisp+pcnt > state->total_param)
7050 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7052 if (pdisp > state->total_param)
7054 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
7055 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
7057 if (state->param + pdisp < state->param)
7060 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
7065 if (ddisp+dcnt > state->total_data)
7067 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7069 if (ddisp > state->total_data)
7071 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
7072 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
7074 if (state->data + ddisp < state->data)
7077 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
7081 if ((state->received_param < state->total_param) ||
7082 (state->received_data < state->total_data)) {
7083 END_PROFILE(SMBtranss2);
7087 /* construct_reply_common has done us the favor to pre-fill the
7088 * command field with SMBtranss2 which is wrong :-)
7090 SCVAL(outbuf,smb_com,SMBtrans2);
7092 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
7093 END_PROFILE(SMBtranss2);
7094 return ERROR_NT(NT_STATUS_NO_MEMORY);
7097 init_smb_request(req, (uint8 *)inbuf);
7099 outsize = handle_trans2(conn, req, state, inbuf, outbuf, size,
7101 if (req->outbuf != NULL) {
7102 outsize = smb_len(req->outbuf) + 4;
7103 memcpy(outbuf, req->outbuf, outsize);
7107 DLIST_REMOVE(conn->pending_trans, state);
7108 SAFE_FREE(state->data);
7109 SAFE_FREE(state->param);
7113 END_PROFILE(SMBtranss2);
7114 return(ERROR_DOS(ERRSRV,ERRnosupport));
7117 END_PROFILE(SMBtranss2);
7122 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7123 DLIST_REMOVE(conn->pending_trans, state);
7124 SAFE_FREE(state->data);
7125 SAFE_FREE(state->param);
7127 END_PROFILE(SMBtranss2);
7128 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);