2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 static char *store_file_unix_basic(connection_struct *conn,
40 const SMB_STRUCT_STAT *psbuf);
42 static char *store_file_unix_basic_info2(connection_struct *conn,
45 const SMB_STRUCT_STAT *psbuf);
47 /********************************************************************
48 Roundup a value to the nearest allocation roundup size boundary.
49 Only do this for Windows clients.
50 ********************************************************************/
52 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
54 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
56 /* Only roundup for Windows clients. */
57 enum remote_arch_types ra_type = get_remote_arch();
58 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
59 val = SMB_ROUNDUP(val,rval);
64 /********************************************************************
65 Given a stat buffer return the allocated size on disk, taking into
67 ********************************************************************/
69 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
73 if(S_ISDIR(sbuf->st_mode)) {
77 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
78 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
83 if (fsp && fsp->initial_allocation_size)
84 ret = MAX(ret,fsp->initial_allocation_size);
86 return smb_roundup(conn, ret);
89 /****************************************************************************
90 Utility functions for dealing with extended attributes.
91 ****************************************************************************/
93 /****************************************************************************
94 Refuse to allow clients to overwrite our private xattrs.
95 ****************************************************************************/
97 static BOOL samba_private_attr_name(const char *unix_ea_name)
99 static const char *prohibited_ea_names[] = {
100 SAMBA_POSIX_INHERITANCE_EA_NAME,
101 SAMBA_XATTR_DOS_ATTRIB,
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
114 /****************************************************************************
115 Get one EA value. Fill in a struct ea_struct.
116 ****************************************************************************/
118 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
119 const char *fname, char *ea_name, struct ea_struct *pea)
121 /* Get the value of this xattr. Max size is 64k. */
122 size_t attr_size = 256;
128 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 if (fsp && fsp->fh->fd != -1) {
134 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
139 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
148 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
149 dump_data(10, (uint8 *)val, sizeret);
152 if (strnequal(ea_name, "user.", 5)) {
153 pea->name = &ea_name[5];
157 pea->value.data = (unsigned char *)val;
158 pea->value.length = (size_t)sizeret;
162 /****************************************************************************
163 Return a linked list of the total EA's. Plus the total size
164 ****************************************************************************/
166 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
167 const char *fname, size_t *pea_total_len)
169 /* Get a list of all xattrs. Max namesize is 64k. */
170 size_t ea_namelist_size = 1024;
175 struct ea_list *ea_list_head = NULL;
179 if (!lp_ea_support(SNUM(conn))) {
183 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
184 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
190 if (fsp && fsp->fh->fd != -1) {
191 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
196 if (sizeret == -1 && errno == ERANGE) {
197 ea_namelist_size *= 2;
206 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
209 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
210 struct ea_list *listp;
212 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
215 listp = TALLOC_P(mem_ctx, struct ea_list);
219 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
225 push_ascii_fstring(dos_ea_name, listp->ea.name);
226 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
227 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
228 (unsigned int)*pea_total_len, dos_ea_name,
229 (unsigned int)listp->ea.value.length ));
231 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
233 /* Add on 4 for total length. */
234 if (*pea_total_len) {
239 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
243 /****************************************************************************
244 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246 ****************************************************************************/
248 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
249 connection_struct *conn, struct ea_list *ea_list)
251 unsigned int ret_data_size = 4;
254 SMB_ASSERT(total_data_size >= 4);
256 if (!lp_ea_support(SNUM(conn))) {
261 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
264 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
265 dos_namelen = strlen(dos_ea_name);
266 if (dos_namelen > 255 || dos_namelen == 0) {
269 if (ea_list->ea.value.length > 65535) {
272 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
276 /* We know we have room. */
277 SCVAL(p,0,ea_list->ea.flags);
278 SCVAL(p,1,dos_namelen);
279 SSVAL(p,2,ea_list->ea.value.length);
280 fstrcpy(p+4, dos_ea_name);
281 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
283 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
284 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
287 ret_data_size = PTR_DIFF(p, pdata);
288 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
289 SIVAL(pdata,0,ret_data_size);
290 return ret_data_size;
293 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
295 size_t total_ea_len = 0;
296 TALLOC_CTX *mem_ctx = NULL;
298 if (!lp_ea_support(SNUM(conn))) {
301 mem_ctx = talloc_init("estimate_ea_size");
302 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
303 talloc_destroy(mem_ctx);
307 /****************************************************************************
308 Ensure the EA name is case insensitive by matching any existing EA name.
309 ****************************************************************************/
311 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
314 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
315 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
317 for (; ea_list; ea_list = ea_list->next) {
318 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
319 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
320 &unix_ea_name[5], ea_list->ea.name));
321 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
325 talloc_destroy(mem_ctx);
328 /****************************************************************************
329 Set or delete an extended attribute.
330 ****************************************************************************/
332 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
334 if (!lp_ea_support(SNUM(conn))) {
335 return NT_STATUS_EAS_NOT_SUPPORTED;
338 for (;ea_list; ea_list = ea_list->next) {
340 fstring unix_ea_name;
342 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
343 fstrcat(unix_ea_name, ea_list->ea.name);
345 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
347 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
349 if (samba_private_attr_name(unix_ea_name)) {
350 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
351 return NT_STATUS_ACCESS_DENIED;
354 if (ea_list->ea.value.length == 0) {
355 /* Remove the attribute. */
356 if (fsp && (fsp->fh->fd != -1)) {
357 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
358 unix_ea_name, fsp->fsp_name));
359 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
362 unix_ea_name, fname));
363 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 /* Removing a non existent attribute always succeeds. */
367 if (ret == -1 && errno == ENOATTR) {
368 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
374 if (fsp && (fsp->fh->fd != -1)) {
375 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
376 unix_ea_name, fsp->fsp_name));
377 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
378 ea_list->ea.value.data, ea_list->ea.value.length, 0);
380 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
381 unix_ea_name, fname));
382 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
383 ea_list->ea.value.data, ea_list->ea.value.length, 0);
389 if (errno == ENOTSUP) {
390 return NT_STATUS_EAS_NOT_SUPPORTED;
393 return map_nt_error_from_unix(errno);
399 /****************************************************************************
400 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
401 ****************************************************************************/
403 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
405 struct ea_list *ea_list_head = NULL;
408 while (offset + 2 < data_size) {
409 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
410 unsigned int namelen = CVAL(pdata,offset);
412 offset++; /* Go past the namelen byte. */
414 /* integer wrap paranioa. */
415 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
416 (offset > data_size) || (namelen > data_size) ||
417 (offset + namelen >= data_size)) {
420 /* Ensure the name is null terminated. */
421 if (pdata[offset + namelen] != '\0') {
424 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
429 offset += (namelen + 1); /* Go past the name + terminating zero. */
430 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
431 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
437 /****************************************************************************
438 Read one EA list entry from the buffer.
439 ****************************************************************************/
441 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
443 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 unsigned int namelen;
455 eal->ea.flags = CVAL(pdata,0);
456 namelen = CVAL(pdata,1);
457 val_len = SVAL(pdata,2);
459 if (4 + namelen + 1 + val_len > data_size) {
463 /* Ensure the name is null terminated. */
464 if (pdata[namelen + 4] != '\0') {
467 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
472 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
473 if (!eal->ea.value.data) {
477 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
479 /* Ensure we're null terminated just in case we print the value. */
480 eal->ea.value.data[val_len] = '\0';
481 /* But don't count the null. */
482 eal->ea.value.length--;
485 *pbytes_used = 4 + namelen + 1 + val_len;
488 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
489 dump_data(10, eal->ea.value.data, eal->ea.value.length);
494 /****************************************************************************
495 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
496 ****************************************************************************/
498 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
500 struct ea_list *ea_list_head = NULL;
502 size_t bytes_used = 0;
504 while (offset < data_size) {
505 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
511 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
512 offset += bytes_used;
518 /****************************************************************************
519 Count the total EA size needed.
520 ****************************************************************************/
522 static size_t ea_list_size(struct ea_list *ealist)
525 struct ea_list *listp;
528 for (listp = ealist; listp; listp = listp->next) {
529 push_ascii_fstring(dos_ea_name, listp->ea.name);
530 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
532 /* Add on 4 for total length. */
540 /****************************************************************************
541 Return a union of EA's from a file list and a list of names.
542 The TALLOC context for the two lists *MUST* be identical as we steal
543 memory from one list to add to another. JRA.
544 ****************************************************************************/
546 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
548 struct ea_list *nlistp, *flistp;
550 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
551 for (flistp = file_list; flistp; flistp = flistp->next) {
552 if (strequal(nlistp->ea.name, flistp->ea.name)) {
558 /* Copy the data from this entry. */
559 nlistp->ea.flags = flistp->ea.flags;
560 nlistp->ea.value = flistp->ea.value;
563 nlistp->ea.flags = 0;
564 ZERO_STRUCT(nlistp->ea.value);
568 *total_ea_len = ea_list_size(name_list);
572 /****************************************************************************
573 Send the required number of replies back.
574 We assume all fields other than the data fields are
575 set correctly for the type of call.
576 HACK ! Always assumes smb_setup field is zero.
577 ****************************************************************************/
579 int send_trans2_replies(const char *inbuf,
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(inbuf,outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(inbuf, outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
738 static void send_trans2_replies_new(struct smb_request *req,
745 char *inbuf, *outbuf;
748 if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) {
749 reply_nterror(req, NT_STATUS_NO_MEMORY);
753 reply_post_legacy(req, send_trans2_replies(
754 inbuf, outbuf, bufsize,
760 /****************************************************************************
761 Reply to a TRANSACT2_OPEN.
762 ****************************************************************************/
764 static void call_trans2open(connection_struct *conn,
765 struct smb_request *req,
766 char **pparams, int total_params,
767 char **ppdata, int total_data,
768 unsigned int max_data_bytes)
770 char *params = *pparams;
771 char *pdata = *ppdata;
776 BOOL return_additional_info;
787 SMB_STRUCT_STAT sbuf;
790 struct ea_list *ea_list = NULL;
795 uint32 create_disposition;
796 uint32 create_options = 0;
799 * Ensure we have enough parameters to perform the operation.
802 if (total_params < 29) {
803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
807 flags = SVAL(params, 0);
808 deny_mode = SVAL(params, 2);
809 open_attr = SVAL(params,6);
810 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
811 if (oplock_request) {
812 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
816 return_additional_info = BITSETW(params,0);
817 open_sattr = SVAL(params, 4);
818 open_time = make_unix_date3(params+8);
820 open_ofun = SVAL(params,12);
821 open_size = IVAL(params,14);
825 reply_doserror(req, ERRSRV, ERRaccess);
829 srvstr_get_path(params, req->flags2, fname, pname,
830 sizeof(fname), total_params - 28, STR_TERMINATE,
832 if (!NT_STATUS_IS_OK(status)) {
833 reply_nterror(req, status);
837 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
838 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
839 (unsigned int)open_ofun, open_size));
841 /* XXXX we need to handle passed times, sattr and flags */
843 status = unix_convert(conn, fname, False, NULL, &sbuf);
844 if (!NT_STATUS_IS_OK(status)) {
845 reply_nterror(req, status);
849 status = check_name(conn, fname);
850 if (!NT_STATUS_IS_OK(status)) {
851 reply_nterror(req, status);
855 if (open_ofun == 0) {
856 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
860 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
865 reply_doserror(req, ERRDOS, ERRbadaccess);
869 /* Any data in this call is an EA list. */
870 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
871 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
875 if (total_data != 4) {
876 if (total_data < 10) {
877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
881 if (IVAL(pdata,0) > total_data) {
882 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
883 IVAL(pdata,0), (unsigned int)total_data));
884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
888 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
894 } else if (IVAL(pdata,0) != 4) {
895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
899 status = open_file_ntcreate(conn, req, fname, &sbuf,
908 if (!NT_STATUS_IS_OK(status)) {
909 if (open_was_deferred(req->mid)) {
910 /* We have re-scheduled this call. */
913 reply_nterror(req, status);
917 size = get_file_size(sbuf);
918 fattr = dos_mode(conn,fname,&sbuf);
919 mtime = sbuf.st_mtime;
922 close_file(fsp,ERROR_CLOSE);
923 reply_doserror(req, ERRDOS,ERRnoaccess);
927 /* Save the requested allocation size. */
928 /* Allocate space for the file if a size hint is supplied */
929 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
930 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
931 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
932 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
933 if (fsp->is_directory) {
934 close_file(fsp,ERROR_CLOSE);
935 /* Can't set allocation size on a directory. */
936 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
939 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
940 close_file(fsp,ERROR_CLOSE);
941 reply_nterror(req, NT_STATUS_DISK_FULL);
945 /* Adjust size here to return the right size in the reply.
946 Windows does it this way. */
947 size = fsp->initial_allocation_size;
949 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
953 if (ea_list && smb_action == FILE_WAS_CREATED) {
954 status = set_ea(conn, fsp, fname, ea_list);
955 if (!NT_STATUS_IS_OK(status)) {
956 close_file(fsp,ERROR_CLOSE);
957 reply_nterror(req, status);
962 /* Realloc the size of parameters and data we will return */
963 *pparams = (char *)SMB_REALLOC(*pparams, 30);
964 if(*pparams == NULL ) {
965 reply_nterror(req, NT_STATUS_NO_MEMORY);
970 SSVAL(params,0,fsp->fnum);
971 SSVAL(params,2,fattr);
972 srv_put_dos_date2(params,4, mtime);
973 SIVAL(params,8, (uint32)size);
974 SSVAL(params,12,deny_mode);
975 SSVAL(params,14,0); /* open_type - file or directory. */
976 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
978 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
979 smb_action |= EXTENDED_OPLOCK_GRANTED;
982 SSVAL(params,18,smb_action);
985 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
987 SIVAL(params,20,inode);
988 SSVAL(params,24,0); /* Padding. */
990 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
991 SIVAL(params, 26, ea_size);
993 SIVAL(params, 26, 0);
996 /* Send the required number of replies */
997 send_trans2_replies_new(req, params, 30, *ppdata, 0, max_data_bytes);
1000 /*********************************************************
1001 Routine to check if a given string matches exactly.
1002 as a special case a mask of "." does NOT match. That
1003 is required for correct wildcard semantics
1004 Case can be significant or not.
1005 **********************************************************/
1007 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
1009 if (mask[0] == '.' && mask[1] == 0)
1011 if (conn->case_sensitive)
1012 return strcmp(str,mask)==0;
1013 if (StrCaseCmp(str,mask) != 0) {
1016 if (dptr_has_wild(conn->dirptr)) {
1022 /****************************************************************************
1023 Return the filetype for UNIX extensions.
1024 ****************************************************************************/
1026 static uint32 unix_filetype(mode_t mode)
1029 return UNIX_TYPE_FILE;
1030 else if(S_ISDIR(mode))
1031 return UNIX_TYPE_DIR;
1033 else if(S_ISLNK(mode))
1034 return UNIX_TYPE_SYMLINK;
1037 else if(S_ISCHR(mode))
1038 return UNIX_TYPE_CHARDEV;
1041 else if(S_ISBLK(mode))
1042 return UNIX_TYPE_BLKDEV;
1045 else if(S_ISFIFO(mode))
1046 return UNIX_TYPE_FIFO;
1049 else if(S_ISSOCK(mode))
1050 return UNIX_TYPE_SOCKET;
1053 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1054 return UNIX_TYPE_UNKNOWN;
1057 /****************************************************************************
1058 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1059 ****************************************************************************/
1061 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1063 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1064 SMB_STRUCT_STAT *psbuf,
1066 enum perm_type ptype,
1071 if (perms == SMB_MODE_NO_CHANGE) {
1072 if (!VALID_STAT(*psbuf)) {
1073 return NT_STATUS_INVALID_PARAMETER;
1075 *ret_perms = psbuf->st_mode;
1076 return NT_STATUS_OK;
1080 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1081 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1082 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1083 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1084 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1085 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1086 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1087 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1088 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1090 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1093 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1096 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1101 /* Apply mode mask */
1102 ret &= lp_create_mask(SNUM(conn));
1103 /* Add in force bits */
1104 ret |= lp_force_create_mode(SNUM(conn));
1107 ret &= lp_dir_mask(SNUM(conn));
1108 /* Add in force bits */
1109 ret |= lp_force_dir_mode(SNUM(conn));
1111 case PERM_EXISTING_FILE:
1112 /* Apply mode mask */
1113 ret &= lp_security_mask(SNUM(conn));
1114 /* Add in force bits */
1115 ret |= lp_force_security_mode(SNUM(conn));
1117 case PERM_EXISTING_DIR:
1118 /* Apply mode mask */
1119 ret &= lp_dir_security_mask(SNUM(conn));
1120 /* Add in force bits */
1121 ret |= lp_force_dir_security_mode(SNUM(conn));
1126 return NT_STATUS_OK;
1129 /****************************************************************************
1130 Get a level dependent lanman2 dir entry.
1131 ****************************************************************************/
1133 static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
1134 char *path_mask,uint32 dirtype,int info_level,
1135 int requires_resume_key,
1136 BOOL dont_descend,char **ppdata,
1137 char *base_data, char *end_data,
1138 int space_remaining,
1139 BOOL *out_of_space, BOOL *got_exact_match,
1140 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1144 SMB_STRUCT_STAT sbuf;
1148 char *p, *q, *pdata = *ppdata;
1152 SMB_OFF_T file_size = 0;
1153 SMB_BIG_UINT allocation_size = 0;
1155 struct timespec mdate_ts, adate_ts, create_date_ts;
1156 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1158 char *last_entry_ptr;
1160 uint32 nt_extmode; /* Used for NT connections instead of mode */
1161 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1162 BOOL check_mangled_names = lp_manglednames(conn->params);
1165 *out_of_space = False;
1166 *got_exact_match = False;
1168 ZERO_STRUCT(mdate_ts);
1169 ZERO_STRUCT(adate_ts);
1170 ZERO_STRUCT(create_date_ts);
1175 p = strrchr_m(path_mask,'/');
1178 pstrcpy(mask,"*.*");
1182 pstrcpy(mask, path_mask);
1187 BOOL ms_dfs_link = False;
1189 /* Needed if we run out of space */
1190 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1191 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1194 * Due to bugs in NT client redirectors we are not using
1195 * resume keys any more - set them to zero.
1196 * Check out the related comments in findfirst/findnext.
1202 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1203 (long)conn->dirptr,curr_dirpos));
1210 * fname may get mangled, dname is never mangled.
1211 * Whenever we're accessing the filesystem we use
1212 * pathreal which is composed from dname.
1215 pstrcpy(fname,dname);
1217 /* This will mangle fname if it's an illegal name. */
1218 mangle_map(fname,False,True,conn->params);
1220 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1221 got_match = mask_match(fname, mask, conn->case_sensitive);
1224 if(!got_match && check_mangled_names &&
1225 !mangle_is_8_3(fname, False, conn->params)) {
1226 pstring mangled_name;
1229 * It turns out that NT matches wildcards against
1230 * both long *and* short names. This may explain some
1231 * of the wildcard wierdness from old DOS clients
1232 * that some people have been seeing.... JRA.
1235 pstrcpy(mangled_name, fname);
1237 /* Force the mangling into 8.3. */
1238 mangle_map( mangled_name, True, False, conn->params);
1239 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1240 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1245 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1246 if (dont_descend && !isdots) {
1250 pstrcpy(pathreal,conn->dirpath);
1252 pstrcat(pathreal,"/");
1254 pstrcat(pathreal,dname);
1256 if (INFO_LEVEL_IS_UNIX(info_level)) {
1257 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1258 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1259 pathreal,strerror(errno)));
1262 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1263 pstring link_target;
1265 /* Needed to show the msdfs symlinks as
1268 if(lp_host_msdfs() &&
1269 lp_msdfs_root(SNUM(conn)) &&
1270 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1271 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1274 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1278 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1279 pathreal,strerror(errno)));
1285 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1287 mode = dos_mode(conn,pathreal,&sbuf);
1290 if (!dir_check_ftype(conn,mode,dirtype)) {
1291 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1295 if (!(mode & aDIR)) {
1296 file_size = get_file_size(sbuf);
1298 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1300 mdate_ts = get_mtimespec(&sbuf);
1301 adate_ts = get_atimespec(&sbuf);
1302 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1304 if (lp_dos_filetime_resolution(SNUM(conn))) {
1305 dos_filetime_timespec(&create_date_ts);
1306 dos_filetime_timespec(&mdate_ts);
1307 dos_filetime_timespec(&adate_ts);
1310 create_date = convert_timespec_to_time_t(create_date_ts);
1311 mdate = convert_timespec_to_time_t(mdate_ts);
1312 adate = convert_timespec_to_time_t(adate_ts);
1314 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1318 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1325 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1327 switch (info_level) {
1328 case SMB_FIND_INFO_STANDARD:
1329 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1330 if(requires_resume_key) {
1334 srv_put_dos_date2(p,0,create_date);
1335 srv_put_dos_date2(p,4,adate);
1336 srv_put_dos_date2(p,8,mdate);
1337 SIVAL(p,12,(uint32)file_size);
1338 SIVAL(p,16,(uint32)allocation_size);
1342 p += align_string(pdata, p, 0);
1343 len = srvstr_push(base_data, flags2, p,
1344 fname, PTR_DIFF(end_data, p),
1346 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1348 SCVAL(nameptr, -1, len - 2);
1350 SCVAL(nameptr, -1, 0);
1354 SCVAL(nameptr, -1, len - 1);
1356 SCVAL(nameptr, -1, 0);
1362 case SMB_FIND_EA_SIZE:
1363 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1364 if(requires_resume_key) {
1368 srv_put_dos_date2(p,0,create_date);
1369 srv_put_dos_date2(p,4,adate);
1370 srv_put_dos_date2(p,8,mdate);
1371 SIVAL(p,12,(uint32)file_size);
1372 SIVAL(p,16,(uint32)allocation_size);
1375 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1376 SIVAL(p,22,ea_size); /* Extended attributes */
1380 len = srvstr_push(base_data, flags2,
1381 p, fname, PTR_DIFF(end_data, p),
1382 STR_TERMINATE | STR_NOALIGN);
1383 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1396 SCVAL(nameptr,0,len);
1398 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1401 case SMB_FIND_EA_LIST:
1403 struct ea_list *file_list = NULL;
1406 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1410 if(requires_resume_key) {
1414 srv_put_dos_date2(p,0,create_date);
1415 srv_put_dos_date2(p,4,adate);
1416 srv_put_dos_date2(p,8,mdate);
1417 SIVAL(p,12,(uint32)file_size);
1418 SIVAL(p,16,(uint32)allocation_size);
1420 p += 22; /* p now points to the EA area. */
1422 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1423 name_list = ea_list_union(name_list, file_list, &ea_len);
1425 /* We need to determine if this entry will fit in the space available. */
1426 /* Max string size is 255 bytes. */
1427 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1428 /* Move the dirptr back to prev_dirpos */
1429 dptr_SeekDir(conn->dirptr, prev_dirpos);
1430 *out_of_space = True;
1431 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1432 return False; /* Not finished - just out of space */
1435 /* Push the ea_data followed by the name. */
1436 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1438 len = srvstr_push(base_data, flags2,
1439 p + 1, fname, PTR_DIFF(end_data, p),
1440 STR_TERMINATE | STR_NOALIGN);
1441 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1454 SCVAL(nameptr,0,len);
1456 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1460 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1461 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1462 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1464 SIVAL(p,0,reskey); p += 4;
1465 put_long_date_timespec(p,create_date_ts); p += 8;
1466 put_long_date_timespec(p,adate_ts); p += 8;
1467 put_long_date_timespec(p,mdate_ts); p += 8;
1468 put_long_date_timespec(p,mdate_ts); p += 8;
1469 SOFF_T(p,0,file_size); p += 8;
1470 SOFF_T(p,0,allocation_size); p += 8;
1471 SIVAL(p,0,nt_extmode); p += 4;
1472 q = p; p += 4; /* q is placeholder for name length. */
1474 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1475 SIVAL(p,0,ea_size); /* Extended attributes */
1478 /* Clear the short name buffer. This is
1479 * IMPORTANT as not doing so will trigger
1480 * a Win2k client bug. JRA.
1482 if (!was_8_3 && check_mangled_names) {
1483 pstring mangled_name;
1484 pstrcpy(mangled_name, fname);
1485 mangle_map(mangled_name,True,True,
1487 mangled_name[12] = 0;
1488 len = srvstr_push(base_data, flags2,
1489 p+2, mangled_name, 24,
1490 STR_UPPER|STR_UNICODE);
1492 memset(p + 2 + len,'\0',24 - len);
1499 len = srvstr_push(base_data, flags2, p,
1500 fname, PTR_DIFF(end_data, p),
1501 STR_TERMINATE_ASCII);
1504 SIVAL(p,0,0); /* Ensure any padding is null. */
1505 len = PTR_DIFF(p, pdata);
1506 len = (len + 3) & ~3;
1511 case SMB_FIND_FILE_DIRECTORY_INFO:
1512 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1514 SIVAL(p,0,reskey); p += 4;
1515 put_long_date_timespec(p,create_date_ts); p += 8;
1516 put_long_date_timespec(p,adate_ts); p += 8;
1517 put_long_date_timespec(p,mdate_ts); p += 8;
1518 put_long_date_timespec(p,mdate_ts); p += 8;
1519 SOFF_T(p,0,file_size); p += 8;
1520 SOFF_T(p,0,allocation_size); p += 8;
1521 SIVAL(p,0,nt_extmode); p += 4;
1522 len = srvstr_push(base_data, flags2,
1523 p + 4, fname, PTR_DIFF(end_data, p),
1524 STR_TERMINATE_ASCII);
1527 SIVAL(p,0,0); /* Ensure any padding is null. */
1528 len = PTR_DIFF(p, pdata);
1529 len = (len + 3) & ~3;
1534 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1535 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1537 SIVAL(p,0,reskey); p += 4;
1538 put_long_date_timespec(p,create_date_ts); p += 8;
1539 put_long_date_timespec(p,adate_ts); p += 8;
1540 put_long_date_timespec(p,mdate_ts); p += 8;
1541 put_long_date_timespec(p,mdate_ts); p += 8;
1542 SOFF_T(p,0,file_size); p += 8;
1543 SOFF_T(p,0,allocation_size); p += 8;
1544 SIVAL(p,0,nt_extmode); p += 4;
1545 q = p; p += 4; /* q is placeholder for name length. */
1547 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1548 SIVAL(p,0,ea_size); /* Extended attributes */
1551 len = srvstr_push(base_data, flags2, p,
1552 fname, PTR_DIFF(end_data, p),
1553 STR_TERMINATE_ASCII);
1557 SIVAL(p,0,0); /* Ensure any padding is null. */
1558 len = PTR_DIFF(p, pdata);
1559 len = (len + 3) & ~3;
1564 case SMB_FIND_FILE_NAMES_INFO:
1565 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1567 SIVAL(p,0,reskey); p += 4;
1569 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1570 acl on a dir (tridge) */
1571 len = srvstr_push(base_data, flags2, p,
1572 fname, PTR_DIFF(end_data, p),
1573 STR_TERMINATE_ASCII);
1576 SIVAL(p,0,0); /* Ensure any padding is null. */
1577 len = PTR_DIFF(p, pdata);
1578 len = (len + 3) & ~3;
1583 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1584 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1586 SIVAL(p,0,reskey); p += 4;
1587 put_long_date_timespec(p,create_date_ts); p += 8;
1588 put_long_date_timespec(p,adate_ts); p += 8;
1589 put_long_date_timespec(p,mdate_ts); p += 8;
1590 put_long_date_timespec(p,mdate_ts); p += 8;
1591 SOFF_T(p,0,file_size); p += 8;
1592 SOFF_T(p,0,allocation_size); p += 8;
1593 SIVAL(p,0,nt_extmode); p += 4;
1594 q = p; p += 4; /* q is placeholder for name length. */
1596 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1597 SIVAL(p,0,ea_size); /* Extended attributes */
1600 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1601 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1602 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1603 len = srvstr_push(base_data, flags2, p,
1604 fname, PTR_DIFF(end_data, p),
1605 STR_TERMINATE_ASCII);
1608 SIVAL(p,0,0); /* Ensure any padding is null. */
1609 len = PTR_DIFF(p, pdata);
1610 len = (len + 3) & ~3;
1615 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1616 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1617 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1619 SIVAL(p,0,reskey); p += 4;
1620 put_long_date_timespec(p,create_date_ts); p += 8;
1621 put_long_date_timespec(p,adate_ts); p += 8;
1622 put_long_date_timespec(p,mdate_ts); p += 8;
1623 put_long_date_timespec(p,mdate_ts); p += 8;
1624 SOFF_T(p,0,file_size); p += 8;
1625 SOFF_T(p,0,allocation_size); p += 8;
1626 SIVAL(p,0,nt_extmode); p += 4;
1627 q = p; p += 4; /* q is placeholder for name length */
1629 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1630 SIVAL(p,0,ea_size); /* Extended attributes */
1633 /* Clear the short name buffer. This is
1634 * IMPORTANT as not doing so will trigger
1635 * a Win2k client bug. JRA.
1637 if (!was_8_3 && check_mangled_names) {
1638 pstring mangled_name;
1639 pstrcpy(mangled_name, fname);
1640 mangle_map(mangled_name,True,True,
1642 mangled_name[12] = 0;
1643 len = srvstr_push(base_data, flags2,
1644 p+2, mangled_name, 24,
1645 STR_UPPER|STR_UNICODE);
1648 memset(p + 2 + len,'\0',24 - len);
1655 SSVAL(p,0,0); p += 2; /* Reserved ? */
1656 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1657 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1658 len = srvstr_push(base_data, flags2, p,
1659 fname, PTR_DIFF(end_data, p),
1660 STR_TERMINATE_ASCII);
1663 SIVAL(p,0,0); /* Ensure any padding is null. */
1664 len = PTR_DIFF(p, pdata);
1665 len = (len + 3) & ~3;
1670 /* CIFS UNIX Extension. */
1672 case SMB_FIND_FILE_UNIX:
1673 case SMB_FIND_FILE_UNIX_INFO2:
1675 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1677 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1679 if (info_level == SMB_FIND_FILE_UNIX) {
1680 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1681 p = store_file_unix_basic(conn, p,
1683 len = srvstr_push(base_data, flags2, p,
1684 fname, PTR_DIFF(end_data, p),
1687 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1688 p = store_file_unix_basic_info2(conn, p,
1692 len = srvstr_push(base_data, flags2, p, fname,
1693 PTR_DIFF(end_data, p), 0);
1694 SIVAL(nameptr, 0, len);
1698 SIVAL(p,0,0); /* Ensure any padding is null. */
1700 len = PTR_DIFF(p, pdata);
1701 len = (len + 3) & ~3;
1702 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1704 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1713 if (PTR_DIFF(p,pdata) > space_remaining) {
1714 /* Move the dirptr back to prev_dirpos */
1715 dptr_SeekDir(conn->dirptr, prev_dirpos);
1716 *out_of_space = True;
1717 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1718 return False; /* Not finished - just out of space */
1721 /* Setup the last entry pointer, as an offset from base_data */
1722 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1723 /* Advance the data pointer to the next slot */
1729 /****************************************************************************
1730 Reply to a TRANS2_FINDFIRST.
1731 ****************************************************************************/
1733 static void call_trans2findfirst(connection_struct *conn,
1734 struct smb_request *req,
1735 char **pparams, int total_params,
1736 char **ppdata, int total_data,
1737 unsigned int max_data_bytes)
1739 /* We must be careful here that we don't return more than the
1740 allowed number of data bytes. If this means returning fewer than
1741 maxentries then so be it. We assume that the redirector has
1742 enough room for the fixed number of parameter bytes it has
1744 char *params = *pparams;
1745 char *pdata = *ppdata;
1749 uint16 findfirst_flags;
1750 BOOL close_after_first;
1752 BOOL requires_resume_key;
1757 int last_entry_off=0;
1761 BOOL finished = False;
1762 BOOL dont_descend = False;
1763 BOOL out_of_space = False;
1764 int space_remaining;
1765 BOOL mask_contains_wcard = False;
1766 SMB_STRUCT_STAT sbuf;
1767 TALLOC_CTX *ea_ctx = NULL;
1768 struct ea_list *ea_list = NULL;
1769 NTSTATUS ntstatus = NT_STATUS_OK;
1771 if (total_params < 13) {
1772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1776 dirtype = SVAL(params,0);
1777 maxentries = SVAL(params,2);
1778 findfirst_flags = SVAL(params,4);
1779 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1780 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1781 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1782 info_level = SVAL(params,6);
1784 *directory = *mask = 0;
1786 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1787 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1788 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1789 info_level, max_data_bytes));
1792 /* W2K3 seems to treat zero as 1. */
1796 switch (info_level) {
1797 case SMB_FIND_INFO_STANDARD:
1798 case SMB_FIND_EA_SIZE:
1799 case SMB_FIND_EA_LIST:
1800 case SMB_FIND_FILE_DIRECTORY_INFO:
1801 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1802 case SMB_FIND_FILE_NAMES_INFO:
1803 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1804 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1805 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1807 case SMB_FIND_FILE_UNIX:
1808 case SMB_FIND_FILE_UNIX_INFO2:
1809 if (!lp_unix_extensions()) {
1810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1815 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1819 srvstr_get_path_wcard(params, req->flags2, directory,
1820 params+12, sizeof(directory), total_params - 12,
1821 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1822 if (!NT_STATUS_IS_OK(ntstatus)) {
1823 reply_nterror(req, ntstatus);
1827 ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1828 if (!NT_STATUS_IS_OK(ntstatus)) {
1829 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1830 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1831 ERRSRV, ERRbadpath);
1834 reply_nterror(req, ntstatus);
1838 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1839 if (!NT_STATUS_IS_OK(ntstatus)) {
1840 reply_nterror(req, ntstatus);
1843 ntstatus = check_name(conn, directory);
1844 if (!NT_STATUS_IS_OK(ntstatus)) {
1845 reply_nterror(req, ntstatus);
1849 p = strrchr_m(directory,'/');
1851 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1852 if((directory[0] == '.') && (directory[1] == '\0')) {
1854 mask_contains_wcard = True;
1856 pstrcpy(mask,directory);
1858 pstrcpy(directory,"./");
1864 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1866 if (info_level == SMB_FIND_EA_LIST) {
1869 if (total_data < 4) {
1870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1874 ea_size = IVAL(pdata,0);
1875 if (ea_size != total_data) {
1876 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1877 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1882 if (!lp_ea_support(SNUM(conn))) {
1883 reply_doserror(req, ERRDOS, ERReasnotsupported);
1887 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1888 reply_nterror(req, NT_STATUS_NO_MEMORY);
1892 /* Pull out the list of names. */
1893 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1895 talloc_destroy(ea_ctx);
1896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1901 *ppdata = (char *)SMB_REALLOC(
1902 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1903 if(*ppdata == NULL ) {
1904 talloc_destroy(ea_ctx);
1905 reply_nterror(req, NT_STATUS_NO_MEMORY);
1909 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1911 /* Realloc the params space */
1912 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1913 if (*pparams == NULL) {
1914 talloc_destroy(ea_ctx);
1915 reply_nterror(req, NT_STATUS_NO_MEMORY);
1920 /* Save the wildcard match and attribs we are using on this directory -
1921 needed as lanman2 assumes these are being saved between calls */
1923 ntstatus = dptr_create(conn,
1929 mask_contains_wcard,
1933 if (!NT_STATUS_IS_OK(ntstatus)) {
1934 talloc_destroy(ea_ctx);
1935 reply_nterror(req, ntstatus);
1939 dptr_num = dptr_dnum(conn->dirptr);
1940 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1942 /* We don't need to check for VOL here as this is returned by
1943 a different TRANS2 call. */
1945 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1946 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1947 dont_descend = True;
1950 space_remaining = max_data_bytes;
1951 out_of_space = False;
1953 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1954 BOOL got_exact_match = False;
1956 /* this is a heuristic to avoid seeking the dirptr except when
1957 absolutely necessary. It allows for a filename of about 40 chars */
1958 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1959 out_of_space = True;
1962 finished = !get_lanman2_dir_entry(conn,
1964 mask,dirtype,info_level,
1965 requires_resume_key,dont_descend,
1967 space_remaining, &out_of_space,
1969 &last_entry_off, ea_list, ea_ctx);
1972 if (finished && out_of_space)
1975 if (!finished && !out_of_space)
1979 * As an optimisation if we know we aren't looking
1980 * for a wildcard name (ie. the name matches the wildcard exactly)
1981 * then we can finish on any (first) match.
1982 * This speeds up large directory searches. JRA.
1988 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1991 talloc_destroy(ea_ctx);
1993 /* Check if we can close the dirptr */
1994 if(close_after_first || (finished && close_if_end)) {
1995 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1996 dptr_close(&dptr_num);
2000 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2001 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2002 * the protocol level is less than NT1. Tested with smbclient. JRA.
2003 * This should fix the OS/2 client bug #2335.
2006 if(numentries == 0) {
2007 dptr_close(&dptr_num);
2008 if (Protocol < PROTOCOL_NT1) {
2009 reply_doserror(req, ERRDOS, ERRnofiles);
2012 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2013 ERRDOS, ERRbadfile);
2018 /* At this point pdata points to numentries directory entries. */
2020 /* Set up the return parameter block */
2021 SSVAL(params,0,dptr_num);
2022 SSVAL(params,2,numentries);
2023 SSVAL(params,4,finished);
2024 SSVAL(params,6,0); /* Never an EA error */
2025 SSVAL(params,8,last_entry_off);
2027 send_trans2_replies_new(req, params, 10, pdata, PTR_DIFF(p,pdata),
2030 if ((! *directory) && dptr_path(dptr_num))
2031 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2033 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2034 smb_fn_name(CVAL(req->inbuf,smb_com)),
2035 mask, directory, dirtype, numentries ) );
2038 * Force a name mangle here to ensure that the
2039 * mask as an 8.3 name is top of the mangled cache.
2040 * The reasons for this are subtle. Don't remove
2041 * this code unless you know what you are doing
2042 * (see PR#13758). JRA.
2045 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
2046 mangle_map(mask, True, True, conn->params);
2051 /****************************************************************************
2052 Reply to a TRANS2_FINDNEXT.
2053 ****************************************************************************/
2055 static void call_trans2findnext(connection_struct *conn,
2056 struct smb_request *req,
2057 char **pparams, int total_params,
2058 char **ppdata, int total_data,
2059 unsigned int max_data_bytes)
2061 /* We must be careful here that we don't return more than the
2062 allowed number of data bytes. If this means returning fewer than
2063 maxentries then so be it. We assume that the redirector has
2064 enough room for the fixed number of parameter bytes it has
2066 char *params = *pparams;
2067 char *pdata = *ppdata;
2073 uint16 findnext_flags;
2074 BOOL close_after_request;
2076 BOOL requires_resume_key;
2078 BOOL mask_contains_wcard = False;
2079 pstring resume_name;
2085 int i, last_entry_off=0;
2086 BOOL finished = False;
2087 BOOL dont_descend = False;
2088 BOOL out_of_space = False;
2089 int space_remaining;
2090 TALLOC_CTX *ea_ctx = NULL;
2091 struct ea_list *ea_list = NULL;
2092 NTSTATUS ntstatus = NT_STATUS_OK;
2094 if (total_params < 13) {
2095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2099 dptr_num = SVAL(params,0);
2100 maxentries = SVAL(params,2);
2101 info_level = SVAL(params,4);
2102 resume_key = IVAL(params,6);
2103 findnext_flags = SVAL(params,10);
2104 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2105 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2106 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2107 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2109 *mask = *directory = *resume_name = 0;
2111 srvstr_get_path_wcard(params, req->flags2, resume_name,
2112 params+12, sizeof(resume_name),
2113 total_params - 12, STR_TERMINATE, &ntstatus,
2114 &mask_contains_wcard);
2115 if (!NT_STATUS_IS_OK(ntstatus)) {
2116 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2117 complain (it thinks we're asking for the directory above the shared
2118 path or an invalid name). Catch this as the resume name is only compared, never used in
2119 a file access. JRA. */
2120 srvstr_pull(params, req->flags2,
2121 resume_name, params+12,
2122 sizeof(resume_name), total_params - 12,
2125 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2126 reply_nterror(req, ntstatus);
2131 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2132 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2133 resume_key = %d resume name = %s continue=%d level = %d\n",
2134 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2135 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2138 /* W2K3 seems to treat zero as 1. */
2142 switch (info_level) {
2143 case SMB_FIND_INFO_STANDARD:
2144 case SMB_FIND_EA_SIZE:
2145 case SMB_FIND_EA_LIST:
2146 case SMB_FIND_FILE_DIRECTORY_INFO:
2147 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2148 case SMB_FIND_FILE_NAMES_INFO:
2149 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2150 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2151 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2153 case SMB_FIND_FILE_UNIX:
2154 case SMB_FIND_FILE_UNIX_INFO2:
2155 if (!lp_unix_extensions()) {
2156 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2161 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2165 if (info_level == SMB_FIND_EA_LIST) {
2168 if (total_data < 4) {
2169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2173 ea_size = IVAL(pdata,0);
2174 if (ea_size != total_data) {
2175 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2176 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2181 if (!lp_ea_support(SNUM(conn))) {
2182 reply_doserror(req, ERRDOS, ERReasnotsupported);
2186 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2191 /* Pull out the list of names. */
2192 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2194 talloc_destroy(ea_ctx);
2195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2200 *ppdata = (char *)SMB_REALLOC(
2201 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2202 if(*ppdata == NULL) {
2203 talloc_destroy(ea_ctx);
2204 reply_nterror(req, NT_STATUS_NO_MEMORY);
2209 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2211 /* Realloc the params space */
2212 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2213 if(*pparams == NULL ) {
2214 talloc_destroy(ea_ctx);
2215 reply_nterror(req, NT_STATUS_NO_MEMORY);
2221 /* Check that the dptr is valid */
2222 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2223 talloc_destroy(ea_ctx);
2224 reply_doserror(req, ERRDOS, ERRnofiles);
2228 string_set(&conn->dirpath,dptr_path(dptr_num));
2230 /* Get the wildcard mask from the dptr */
2231 if((p = dptr_wcard(dptr_num))== NULL) {
2232 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2233 talloc_destroy(ea_ctx);
2234 reply_doserror(req, ERRDOS, ERRnofiles);
2239 pstrcpy(directory,conn->dirpath);
2241 /* Get the attr mask from the dptr */
2242 dirtype = dptr_attr(dptr_num);
2244 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2245 dptr_num, mask, dirtype,
2247 dptr_TellDir(conn->dirptr)));
2249 /* We don't need to check for VOL here as this is returned by
2250 a different TRANS2 call. */
2252 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2253 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2254 dont_descend = True;
2257 space_remaining = max_data_bytes;
2258 out_of_space = False;
2261 * Seek to the correct position. We no longer use the resume key but
2262 * depend on the last file name instead.
2265 if(*resume_name && !continue_bit) {
2268 long current_pos = 0;
2270 * Remember, mangle_map is called by
2271 * get_lanman2_dir_entry(), so the resume name
2272 * could be mangled. Ensure we check the unmangled name.
2275 if (mangle_is_mangled(resume_name, conn->params)) {
2276 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2281 * Fix for NT redirector problem triggered by resume key indexes
2282 * changing between directory scans. We now return a resume key of 0
2283 * and instead look for the filename to continue from (also given
2284 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2285 * findfirst/findnext (as is usual) then the directory pointer
2286 * should already be at the correct place.
2289 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2290 } /* end if resume_name && !continue_bit */
2292 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2293 BOOL got_exact_match = False;
2295 /* this is a heuristic to avoid seeking the dirptr except when
2296 absolutely necessary. It allows for a filename of about 40 chars */
2297 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2298 out_of_space = True;
2301 finished = !get_lanman2_dir_entry(conn,
2303 mask,dirtype,info_level,
2304 requires_resume_key,dont_descend,
2306 space_remaining, &out_of_space,
2308 &last_entry_off, ea_list, ea_ctx);
2311 if (finished && out_of_space)
2314 if (!finished && !out_of_space)
2318 * As an optimisation if we know we aren't looking
2319 * for a wildcard name (ie. the name matches the wildcard exactly)
2320 * then we can finish on any (first) match.
2321 * This speeds up large directory searches. JRA.
2327 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2330 talloc_destroy(ea_ctx);
2332 /* Check if we can close the dirptr */
2333 if(close_after_request || (finished && close_if_end)) {
2334 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2335 dptr_close(&dptr_num); /* This frees up the saved mask */
2338 /* Set up the return parameter block */
2339 SSVAL(params,0,numentries);
2340 SSVAL(params,2,finished);
2341 SSVAL(params,4,0); /* Never an EA error */
2342 SSVAL(params,6,last_entry_off);
2344 send_trans2_replies_new(req, params, 8, pdata, PTR_DIFF(p,pdata),
2347 if ((! *directory) && dptr_path(dptr_num))
2348 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2350 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2351 smb_fn_name(CVAL(req->inbuf,smb_com)),
2352 mask, directory, dirtype, numentries ) );
2357 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2359 E_md4hash(lp_servicename(SNUM(conn)),objid);
2363 /****************************************************************************
2364 Reply to a TRANS2_QFSINFO (query filesystem info).
2365 ****************************************************************************/
2367 static void call_trans2qfsinfo(connection_struct *conn,
2368 struct smb_request *req,
2369 char **pparams, int total_params,
2370 char **ppdata, int total_data,
2371 unsigned int max_data_bytes)
2373 char *pdata, *end_data;
2374 char *params = *pparams;
2378 const char *vname = volume_label(SNUM(conn));
2379 int snum = SNUM(conn);
2380 char *fstype = lp_fstype(SNUM(conn));
2383 if (total_params < 2) {
2384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2388 info_level = SVAL(params,0);
2390 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2392 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2393 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2394 reply_doserror(req, ERRSRV, ERRinvdevice);
2398 *ppdata = (char *)SMB_REALLOC(
2399 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2400 if (*ppdata == NULL ) {
2401 reply_nterror(req, NT_STATUS_NO_MEMORY);
2406 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2407 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2409 switch (info_level) {
2410 case SMB_INFO_ALLOCATION:
2412 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2414 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2415 reply_unixerror(req, ERRHRD, ERRgeneral);
2419 block_size = lp_block_size(snum);
2420 if (bsize < block_size) {
2421 SMB_BIG_UINT factor = block_size/bsize;
2426 if (bsize > block_size) {
2427 SMB_BIG_UINT factor = bsize/block_size;
2432 bytes_per_sector = 512;
2433 sectors_per_unit = bsize/bytes_per_sector;
2435 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2436 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2437 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2439 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2440 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2441 SIVAL(pdata,l1_cUnit,dsize);
2442 SIVAL(pdata,l1_cUnitAvail,dfree);
2443 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2447 case SMB_INFO_VOLUME:
2448 /* Return volume name */
2450 * Add volume serial number - hash of a combination of
2451 * the called hostname and the service name.
2453 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2455 * Win2k3 and previous mess this up by sending a name length
2456 * one byte short. I believe only older clients (OS/2 Win9x) use
2457 * this call so try fixing this by adding a terminating null to
2458 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2462 pdata+l2_vol_szVolLabel, vname,
2463 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2464 STR_NOALIGN|STR_TERMINATE);
2465 SCVAL(pdata,l2_vol_cch,len);
2466 data_len = l2_vol_szVolLabel + len;
2467 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2468 (unsigned)st.st_ctime, len, vname));
2471 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2472 case SMB_FS_ATTRIBUTE_INFORMATION:
2475 #if defined(HAVE_SYS_QUOTAS)
2476 quota_flag = FILE_VOLUME_QUOTAS;
2479 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2480 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2481 FILE_SUPPORTS_OBJECT_IDS|
2482 FILE_UNICODE_ON_DISK|
2483 quota_flag); /* FS ATTRIBUTES */
2485 SIVAL(pdata,4,255); /* Max filename component length */
2486 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2487 and will think we can't do long filenames */
2488 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2489 PTR_DIFF(end_data, pdata+12),
2492 data_len = 12 + len;
2495 case SMB_QUERY_FS_LABEL_INFO:
2496 case SMB_FS_LABEL_INFORMATION:
2497 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2498 PTR_DIFF(end_data, pdata+4), 0);
2503 case SMB_QUERY_FS_VOLUME_INFO:
2504 case SMB_FS_VOLUME_INFORMATION:
2507 * Add volume serial number - hash of a combination of
2508 * the called hostname and the service name.
2510 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2511 (str_checksum(get_local_machine_name())<<16));
2513 /* Max label len is 32 characters. */
2514 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2515 PTR_DIFF(end_data, pdata+18),
2517 SIVAL(pdata,12,len);
2520 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2521 (int)strlen(vname),vname, lp_servicename(snum)));
2524 case SMB_QUERY_FS_SIZE_INFO:
2525 case SMB_FS_SIZE_INFORMATION:
2527 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2529 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2530 reply_unixerror(req, ERRHRD, ERRgeneral);
2533 block_size = lp_block_size(snum);
2534 if (bsize < block_size) {
2535 SMB_BIG_UINT factor = block_size/bsize;
2540 if (bsize > block_size) {
2541 SMB_BIG_UINT factor = bsize/block_size;
2546 bytes_per_sector = 512;
2547 sectors_per_unit = bsize/bytes_per_sector;
2548 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2549 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2550 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2551 SBIG_UINT(pdata,0,dsize);
2552 SBIG_UINT(pdata,8,dfree);
2553 SIVAL(pdata,16,sectors_per_unit);
2554 SIVAL(pdata,20,bytes_per_sector);
2558 case SMB_FS_FULL_SIZE_INFORMATION:
2560 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2562 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2563 reply_unixerror(req, ERRHRD, ERRgeneral);
2566 block_size = lp_block_size(snum);
2567 if (bsize < block_size) {
2568 SMB_BIG_UINT factor = block_size/bsize;
2573 if (bsize > block_size) {
2574 SMB_BIG_UINT factor = bsize/block_size;
2579 bytes_per_sector = 512;
2580 sectors_per_unit = bsize/bytes_per_sector;
2581 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2582 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2583 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2584 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2585 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2586 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2587 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2588 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2592 case SMB_QUERY_FS_DEVICE_INFO:
2593 case SMB_FS_DEVICE_INFORMATION:
2595 SIVAL(pdata,0,0); /* dev type */
2596 SIVAL(pdata,4,0); /* characteristics */
2599 #ifdef HAVE_SYS_QUOTAS
2600 case SMB_FS_QUOTA_INFORMATION:
2602 * what we have to send --metze:
2604 * Unknown1: 24 NULL bytes
2605 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2606 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2607 * Quota Flags: 2 byte :
2608 * Unknown3: 6 NULL bytes
2612 * details for Quota Flags:
2614 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2615 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2616 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2617 * 0x0001 Enable Quotas: enable quota for this fs
2621 /* we need to fake up a fsp here,
2622 * because its not send in this call
2625 SMB_NTQUOTA_STRUCT quotas;
2628 ZERO_STRUCT(quotas);
2634 if (current_user.ut.uid != 0) {
2635 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2636 lp_servicename(SNUM(conn)),conn->user));
2637 reply_doserror(req, ERRDOS, ERRnoaccess);
2641 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2642 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2643 reply_doserror(req, ERRSRV, ERRerror);
2649 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2651 /* Unknown1 24 NULL bytes*/
2652 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2653 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2654 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2656 /* Default Soft Quota 8 bytes */
2657 SBIG_UINT(pdata,24,quotas.softlim);
2659 /* Default Hard Quota 8 bytes */
2660 SBIG_UINT(pdata,32,quotas.hardlim);
2662 /* Quota flag 2 bytes */
2663 SSVAL(pdata,40,quotas.qflags);
2665 /* Unknown3 6 NULL bytes */
2671 #endif /* HAVE_SYS_QUOTAS */
2672 case SMB_FS_OBJECTID_INFORMATION:
2674 unsigned char objid[16];
2675 memcpy(pdata,create_volume_objectid(conn, objid),16);
2681 * Query the version and capabilities of the CIFS UNIX extensions
2685 case SMB_QUERY_CIFS_UNIX_INFO:
2686 if (!lp_unix_extensions()) {
2687 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2691 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2692 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2693 /* We have POSIX ACLs, pathname and locking capability. */
2694 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2695 CIFS_UNIX_POSIX_ACLS_CAP|
2696 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2697 CIFS_UNIX_FCNTL_LOCKS_CAP|
2698 CIFS_UNIX_EXTATTR_CAP|
2699 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2700 /* Ensure we don't do this on signed or sealed data. */
2701 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2705 case SMB_QUERY_POSIX_FS_INFO:
2708 vfs_statvfs_struct svfs;
2710 if (!lp_unix_extensions()) {
2711 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2715 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2719 SIVAL(pdata,0,svfs.OptimalTransferSize);
2720 SIVAL(pdata,4,svfs.BlockSize);
2721 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2722 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2723 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2724 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2725 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2726 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2727 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2729 } else if (rc == EOPNOTSUPP) {
2730 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2732 #endif /* EOPNOTSUPP */
2734 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2735 reply_doserror(req, ERRSRV, ERRerror);
2741 case SMB_QUERY_POSIX_WHOAMI:
2747 if (!lp_unix_extensions()) {
2748 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2752 if (max_data_bytes < 40) {
2753 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2757 /* We ARE guest if global_sid_Builtin_Guests is
2758 * in our list of SIDs.
2760 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2761 current_user.nt_user_token)) {
2762 flags |= SMB_WHOAMI_GUEST;
2765 /* We are NOT guest if global_sid_Authenticated_Users
2766 * is in our list of SIDs.
2768 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2769 current_user.nt_user_token)) {
2770 flags &= ~SMB_WHOAMI_GUEST;
2773 /* NOTE: 8 bytes for UID/GID, irrespective of native
2774 * platform size. This matches
2775 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2777 data_len = 4 /* flags */
2784 + 4 /* pad/reserved */
2785 + (current_user.ut.ngroups * 8)
2787 + (current_user.nt_user_token->num_sids *
2791 SIVAL(pdata, 0, flags);
2792 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2793 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2794 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2797 if (data_len >= max_data_bytes) {
2798 /* Potential overflow, skip the GIDs and SIDs. */
2800 SIVAL(pdata, 24, 0); /* num_groups */
2801 SIVAL(pdata, 28, 0); /* num_sids */
2802 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2803 SIVAL(pdata, 36, 0); /* reserved */
2809 SIVAL(pdata, 24, current_user.ut.ngroups);
2811 current_user.nt_user_token->num_sids);
2813 /* We walk the SID list twice, but this call is fairly
2814 * infrequent, and I don't expect that it's performance
2815 * sensitive -- jpeach
2817 for (i = 0, sid_bytes = 0;
2818 i < current_user.nt_user_token->num_sids; ++i) {
2820 sid_size(¤t_user.nt_user_token->user_sids[i]);
2823 /* SID list byte count */
2824 SIVAL(pdata, 32, sid_bytes);
2826 /* 4 bytes pad/reserved - must be zero */
2827 SIVAL(pdata, 36, 0);
2831 for (i = 0; i < current_user.ut.ngroups; ++i) {
2832 SBIG_UINT(pdata, data_len,
2833 (SMB_BIG_UINT)current_user.ut.groups[i]);
2839 i < current_user.nt_user_token->num_sids; ++i) {
2841 sid_size(¤t_user.nt_user_token->user_sids[i]);
2843 sid_linearize(pdata + data_len, sid_len,
2844 ¤t_user.nt_user_token->user_sids[i]);
2845 data_len += sid_len;
2851 case SMB_MAC_QUERY_FS_INFO:
2853 * Thursby MAC extension... ONLY on NTFS filesystems
2854 * once we do streams then we don't need this
2856 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2858 SIVAL(pdata,84,0x100); /* Don't support mac... */
2863 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2868 send_trans2_replies_new(req, params, 0, pdata, data_len,
2871 DEBUG( 4, ( "%s info_level = %d\n",
2872 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2877 /****************************************************************************
2878 Reply to a TRANS2_SETFSINFO (set filesystem info).
2879 ****************************************************************************/
2881 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2882 char **pparams, int total_params, char **ppdata, int total_data,
2883 unsigned int max_data_bytes)
2885 char *pdata = *ppdata;
2886 char *params = *pparams;
2890 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2893 if (total_params < 4) {
2894 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2896 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2899 info_level = SVAL(params,2);
2901 switch(info_level) {
2902 case SMB_SET_CIFS_UNIX_INFO:
2904 uint16 client_unix_major;
2905 uint16 client_unix_minor;
2906 uint32 client_unix_cap_low;
2907 uint32 client_unix_cap_high;
2909 if (!lp_unix_extensions()) {
2910 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2913 /* There should be 12 bytes of capabilities set. */
2914 if (total_data < 8) {
2915 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2917 client_unix_major = SVAL(pdata,0);
2918 client_unix_minor = SVAL(pdata,2);
2919 client_unix_cap_low = IVAL(pdata,4);
2920 client_unix_cap_high = IVAL(pdata,8);
2921 /* Just print these values for now. */
2922 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2923 cap_low = 0x%x, cap_high = 0x%x\n",
2924 (unsigned int)client_unix_major,
2925 (unsigned int)client_unix_minor,
2926 (unsigned int)client_unix_cap_low,
2927 (unsigned int)client_unix_cap_high ));
2929 /* Here is where we must switch to posix pathname processing... */
2930 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2931 lp_set_posix_pathnames();
2932 mangle_change_to_posix();
2935 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2936 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2937 /* Client that knows how to do posix locks,
2938 * but not posix open/mkdir operations. Set a
2939 * default type for read/write checks. */
2941 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2946 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2949 size_t param_len = 0;
2950 size_t data_len = total_data;
2952 if (!lp_unix_extensions()) {
2953 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2956 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2958 status = srv_request_encryption_setup(conn,
2959 (unsigned char **)ppdata,
2961 (unsigned char **)pparams,
2965 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2966 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2967 } else if (!NT_STATUS_IS_OK(status)) {
2968 return ERROR_NT(status);
2971 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2973 if (NT_STATUS_IS_OK(status)) {
2974 /* Server-side transport encryption is now *on*. */
2975 status = srv_encryption_start(conn);
2976 if (!NT_STATUS_IS_OK(status)) {
2977 exit_server_cleanly("Failure in setting up encrypted transport");
2982 case SMB_FS_QUOTA_INFORMATION:
2984 files_struct *fsp = NULL;
2985 SMB_NTQUOTA_STRUCT quotas;
2987 ZERO_STRUCT(quotas);
2990 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2991 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2992 lp_servicename(SNUM(conn)),conn->user));
2993 return ERROR_DOS(ERRSRV,ERRaccess);
2996 /* note: normaly there're 48 bytes,
2997 * but we didn't use the last 6 bytes for now
3000 fsp = file_fsp(SVAL(params,0));
3001 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3002 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3003 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3006 if (total_data < 42) {
3007 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3009 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3012 /* unknown_1 24 NULL bytes in pdata*/
3014 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3015 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3016 #ifdef LARGE_SMB_OFF_T
3017 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3018 #else /* LARGE_SMB_OFF_T */
3019 if ((IVAL(pdata,28) != 0)&&
3020 ((quotas.softlim != 0xFFFFFFFF)||
3021 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3022 /* more than 32 bits? */
3023 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3025 #endif /* LARGE_SMB_OFF_T */
3027 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3028 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3029 #ifdef LARGE_SMB_OFF_T
3030 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3031 #else /* LARGE_SMB_OFF_T */
3032 if ((IVAL(pdata,36) != 0)&&
3033 ((quotas.hardlim != 0xFFFFFFFF)||
3034 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3035 /* more than 32 bits? */
3036 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3038 #endif /* LARGE_SMB_OFF_T */
3040 /* quota_flags 2 bytes **/
3041 quotas.qflags = SVAL(pdata,40);
3043 /* unknown_2 6 NULL bytes follow*/
3045 /* now set the quotas */
3046 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3047 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3048 return ERROR_DOS(ERRSRV,ERRerror);
3054 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3056 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3061 * sending this reply works fine,
3062 * but I'm not sure it's the same
3063 * like windows do...
3066 outsize = set_message(inbuf, outbuf,10,0,True);
3071 #if defined(HAVE_POSIX_ACLS)
3072 /****************************************************************************
3073 Utility function to count the number of entries in a POSIX acl.
3074 ****************************************************************************/
3076 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3078 unsigned int ace_count = 0;
3079 int entry_id = SMB_ACL_FIRST_ENTRY;
3080 SMB_ACL_ENTRY_T entry;
3082 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3084 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3085 entry_id = SMB_ACL_NEXT_ENTRY;
3092 /****************************************************************************
3093 Utility function to marshall a POSIX acl into wire format.
3094 ****************************************************************************/
3096 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3098 int entry_id = SMB_ACL_FIRST_ENTRY;
3099 SMB_ACL_ENTRY_T entry;
3101 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3102 SMB_ACL_TAG_T tagtype;
3103 SMB_ACL_PERMSET_T permset;
3104 unsigned char perms = 0;
3105 unsigned int own_grp;
3108 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3109 entry_id = SMB_ACL_NEXT_ENTRY;
3112 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3113 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3117 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3118 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3122 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3123 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3124 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3126 SCVAL(pdata,1,perms);
3129 case SMB_ACL_USER_OBJ:
3130 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3131 own_grp = (unsigned int)pst->st_uid;
3132 SIVAL(pdata,2,own_grp);
3137 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3139 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3142 own_grp = (unsigned int)*puid;
3143 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3144 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3145 SIVAL(pdata,2,own_grp);
3149 case SMB_ACL_GROUP_OBJ:
3150 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3151 own_grp = (unsigned int)pst->st_gid;
3152 SIVAL(pdata,2,own_grp);
3157 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3159 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3162 own_grp = (unsigned int)*pgid;
3163 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3164 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3165 SIVAL(pdata,2,own_grp);
3170 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3171 SIVAL(pdata,2,0xFFFFFFFF);
3172 SIVAL(pdata,6,0xFFFFFFFF);
3175 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3176 SIVAL(pdata,2,0xFFFFFFFF);
3177 SIVAL(pdata,6,0xFFFFFFFF);
3180 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3183 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3190 /****************************************************************************
3191 Store the FILE_UNIX_BASIC info.
3192 ****************************************************************************/
3194 static char *store_file_unix_basic(connection_struct *conn,
3197 const SMB_STRUCT_STAT *psbuf)
3199 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3200 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3202 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3205 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3208 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3209 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3210 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3213 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3217 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3221 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3224 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3228 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3232 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3235 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3239 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3246 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3247 * the chflags(2) (or equivalent) flags.
3249 * XXX: this really should be behind the VFS interface. To do this, we would
3250 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3251 * Each VFS module could then implement it's own mapping as appropriate for the
3252 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3254 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3258 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3262 { UF_IMMUTABLE, EXT_IMMUTABLE },
3266 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3270 { UF_HIDDEN, EXT_HIDDEN },
3273 /* Do not remove. We need to guarantee that this array has at least one
3274 * entry to build on HP-UX.
3280 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3281 uint32 *smb_fflags, uint32 *smb_fmask)
3283 #ifdef HAVE_STAT_ST_FLAGS
3286 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3287 *smb_fmask |= info2_flags_map[i].smb_fflag;
3288 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3289 *smb_fflags |= info2_flags_map[i].smb_fflag;
3292 #endif /* HAVE_STAT_ST_FLAGS */
3295 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3296 const uint32 smb_fflags,
3297 const uint32 smb_fmask,
3300 #ifdef HAVE_STAT_ST_FLAGS
3301 uint32 max_fmask = 0;
3304 *stat_fflags = psbuf->st_flags;
3306 /* For each flags requested in smb_fmask, check the state of the
3307 * corresponding flag in smb_fflags and set or clear the matching
3311 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3312 max_fmask |= info2_flags_map[i].smb_fflag;
3313 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3314 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3315 *stat_fflags |= info2_flags_map[i].stat_fflag;
3317 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3322 /* If smb_fmask is asking to set any bits that are not supported by
3323 * our flag mappings, we should fail.
3325 if ((smb_fmask & max_fmask) != smb_fmask) {
3332 #endif /* HAVE_STAT_ST_FLAGS */
3336 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3337 * of file flags and birth (create) time.
3339 static char *store_file_unix_basic_info2(connection_struct *conn,
3342 const SMB_STRUCT_STAT *psbuf)
3344 uint32 file_flags = 0;
3345 uint32 flags_mask = 0;
3347 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3349 /* Create (birth) time 64 bit */
3350 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3353 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3354 SIVAL(pdata, 0, file_flags); /* flags */
3355 SIVAL(pdata, 4, flags_mask); /* mask */
3361 /****************************************************************************
3362 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3363 ****************************************************************************/
3365 static void call_trans2qpipeinfo(connection_struct *conn,
3366 struct smb_request *req,
3367 unsigned int tran_call,
3368 char **pparams, int total_params,
3369 char **ppdata, int total_data,
3370 unsigned int max_data_bytes)
3372 char *params = *pparams;
3373 char *pdata = *ppdata;
3374 unsigned int data_size = 0;
3375 unsigned int param_size = 2;
3377 smb_np_struct *p_pipe = NULL;
3380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3384 if (total_params < 4) {
3385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3389 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3390 if (p_pipe == NULL) {
3391 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3395 info_level = SVAL(params,2);
3397 *pparams = (char *)SMB_REALLOC(*pparams,2);
3398 if (*pparams == NULL) {
3399 reply_nterror(req, NT_STATUS_NO_MEMORY);
3404 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3405 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3406 if (*ppdata == NULL ) {
3407 reply_nterror(req, NT_STATUS_NO_MEMORY);
3412 switch (info_level) {
3413 case SMB_FILE_STANDARD_INFORMATION:
3415 SOFF_T(pdata,0,4096LL);
3422 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3426 send_trans2_replies_new(req, params, param_size, *ppdata, data_size,
3432 /****************************************************************************
3433 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3434 file name or file id).
3435 ****************************************************************************/
3437 static void call_trans2qfilepathinfo(connection_struct *conn,
3438 struct smb_request *req,
3439 unsigned int tran_call,
3440 char **pparams, int total_params,
3441 char **ppdata, int total_data,
3442 unsigned int max_data_bytes)
3444 char *params = *pparams;
3445 char *pdata = *ppdata;
3446 char *dstart, *dend;
3450 SMB_OFF_T file_size=0;
3451 SMB_BIG_UINT allocation_size=0;
3452 unsigned int data_size = 0;
3453 unsigned int param_size = 2;
3454 SMB_STRUCT_STAT sbuf;
3455 pstring fname, dos_fname;
3460 BOOL delete_pending = False;
3462 time_t create_time, mtime, atime;
3463 struct timespec create_time_ts, mtime_ts, atime_ts;
3464 files_struct *fsp = NULL;
3465 struct file_id fileid;
3466 TALLOC_CTX *data_ctx = NULL;
3467 struct ea_list *ea_list = NULL;
3468 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3469 char *lock_data = NULL;
3472 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3478 if (tran_call == TRANSACT2_QFILEINFO) {
3479 if (total_params < 4) {
3480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3485 call_trans2qpipeinfo(conn, req, tran_call,
3486 pparams, total_params,
3492 fsp = file_fsp(SVAL(params,0));
3493 info_level = SVAL(params,2);
3495 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3497 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3498 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3502 if(fsp && (fsp->fake_file_handle)) {
3504 * This is actually for the QUOTA_FAKE_FILE --metze
3507 pstrcpy(fname, fsp->fsp_name);
3508 /* We know this name is ok, it's already passed the checks. */
3510 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3512 * This is actually a QFILEINFO on a directory
3513 * handle (returned from an NT SMB). NT5.0 seems
3514 * to do this call. JRA.
3516 /* We know this name is ok, it's already passed the checks. */
3517 pstrcpy(fname, fsp->fsp_name);
3519 if (INFO_LEVEL_IS_UNIX(info_level)) {
3520 /* Always do lstat for UNIX calls. */
3521 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3522 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3523 reply_unixerror(req,ERRDOS,ERRbadpath);
3526 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3527 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3528 reply_unixerror(req, ERRDOS, ERRbadpath);
3532 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3533 delete_pending = get_delete_on_close_flag(fileid);
3536 * Original code - this is an open file.
3538 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3542 pstrcpy(fname, fsp->fsp_name);
3543 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3544 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3545 reply_unixerror(req, ERRDOS, ERRbadfid);
3548 pos = fsp->fh->position_information;
3549 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3550 delete_pending = get_delete_on_close_flag(fileid);
3551 access_mask = fsp->access_mask;
3554 NTSTATUS status = NT_STATUS_OK;
3557 if (total_params < 7) {
3558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3562 info_level = SVAL(params,0);
3564 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3566 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3567 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3571 srvstr_get_path(params, req->flags2, fname, ¶ms[6],
3572 sizeof(fname), total_params - 6,
3573 STR_TERMINATE, &status);
3574 if (!NT_STATUS_IS_OK(status)) {
3575 reply_nterror(req, status);
3579 status = resolve_dfspath(conn,
3580 req->flags2 & FLAGS2_DFS_PATHNAMES,
3582 if (!NT_STATUS_IS_OK(status)) {
3583 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3584 reply_botherror(req,
3585 NT_STATUS_PATH_NOT_COVERED,
3586 ERRSRV, ERRbadpath);
3588 reply_nterror(req, status);
3592 status = unix_convert(conn, fname, False, NULL, &sbuf);
3593 if (!NT_STATUS_IS_OK(status)) {
3594 reply_nterror(req, status);
3597 status = check_name(conn, fname);
3598 if (!NT_STATUS_IS_OK(status)) {
3599 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3600 reply_nterror(req, status);
3604 if (INFO_LEVEL_IS_UNIX(info_level)) {
3605 /* Always do lstat for UNIX calls. */
3606 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3607 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3608 reply_unixerror(req, ERRDOS, ERRbadpath);
3611 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3612 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3613 reply_unixerror(req, ERRDOS, ERRbadpath);
3617 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3618 delete_pending = get_delete_on_close_flag(fileid);
3619 if (delete_pending) {
3620 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3625 nlink = sbuf.st_nlink;
3627 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3628 /* NTFS does not seem to count ".." */
3632 if ((nlink > 0) && delete_pending) {
3636 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3637 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3641 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3642 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3644 p = strrchr_m(fname,'/');
3650 mode = dos_mode(conn,fname,&sbuf);
3652 mode = FILE_ATTRIBUTE_NORMAL;
3654 fullpathname = fname;
3656 file_size = get_file_size(sbuf);
3658 /* Pull out any data sent here before we realloc. */
3659 switch (info_level) {
3660 case SMB_INFO_QUERY_EAS_FROM_LIST:
3662 /* Pull any EA list from the data portion. */
3665 if (total_data < 4) {
3667 req, NT_STATUS_INVALID_PARAMETER);
3670 ea_size = IVAL(pdata,0);
3672 if (total_data > 0 && ea_size != total_data) {
3673 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3674 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3676 req, NT_STATUS_INVALID_PARAMETER);
3680 if (!lp_ea_support(SNUM(conn))) {
3681 reply_doserror(req, ERRDOS,
3682 ERReasnotsupported);
3686 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3687 reply_nterror(req, NT_STATUS_NO_MEMORY);
3691 /* Pull out the list of names. */
3692 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3694 talloc_destroy(data_ctx);
3696 req, NT_STATUS_INVALID_PARAMETER);
3702 case SMB_QUERY_POSIX_LOCK:
3704 if (fsp == NULL || fsp->fh->fd == -1) {
3705 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3709 if (total_data != POSIX_LOCK_DATA_SIZE) {
3711 req, NT_STATUS_INVALID_PARAMETER);
3715 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3716 reply_nterror(req, NT_STATUS_NO_MEMORY);
3720 /* Copy the lock range data. */
3721 lock_data = (char *)TALLOC_MEMDUP(
3722 data_ctx, pdata, total_data);
3724 talloc_destroy(data_ctx);
3725 reply_nterror(req, NT_STATUS_NO_MEMORY);
3733 *pparams = (char *)SMB_REALLOC(*pparams,2);
3734 if (*pparams == NULL) {
3735 talloc_destroy(data_ctx);
3736 reply_nterror(req, NT_STATUS_NO_MEMORY);
3741 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3742 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3743 if (*ppdata == NULL ) {
3744 talloc_destroy(data_ctx);
3745 reply_nterror(req, NT_STATUS_NO_MEMORY);
3750 dend = dstart + data_size - 1;
3752 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3753 mtime_ts = get_mtimespec(&sbuf);
3754 atime_ts = get_atimespec(&sbuf);
3756 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3759 if (!null_timespec(fsp->pending_modtime)) {
3760 /* the pending modtime overrides the current modtime */
3761 mtime_ts = fsp->pending_modtime;
3765 /* Do we have this path open ? */
3766 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3767 fsp1 = file_find_di_first(fileid);
3768 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3769 /* the pending modtime overrides the current modtime */
3770 mtime_ts = fsp1->pending_modtime;
3772 if (fsp1 && fsp1->initial_allocation_size) {
3773 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3777 if (lp_dos_filetime_resolution(SNUM(conn))) {
3778 dos_filetime_timespec(&create_time_ts);
3779 dos_filetime_timespec(&mtime_ts);
3780 dos_filetime_timespec(&atime_ts);
3783 create_time = convert_timespec_to_time_t(create_time_ts);
3784 mtime = convert_timespec_to_time_t(mtime_ts);
3785 atime = convert_timespec_to_time_t(atime_ts);
3787 /* NT expects the name to be in an exact form of the *full*
3788 filename. See the trans2 torture test */
3789 if (strequal(base_name,".")) {
3790 pstrcpy(dos_fname, "\\");
3792 pstr_sprintf(dos_fname, "\\%s", fname);
3793 string_replace(dos_fname, '/', '\\');
3796 switch (info_level) {
3797 case SMB_INFO_STANDARD:
3798 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3800 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3801 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3802 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3803 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3804 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3805 SSVAL(pdata,l1_attrFile,mode);
3808 case SMB_INFO_QUERY_EA_SIZE:
3810 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3811 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3813 srv_put_dos_date2(pdata,0,create_time);
3814 srv_put_dos_date2(pdata,4,atime);
3815 srv_put_dos_date2(pdata,8,mtime); /* write time */
3816 SIVAL(pdata,12,(uint32)file_size);
3817 SIVAL(pdata,16,(uint32)allocation_size);
3818 SSVAL(pdata,20,mode);
3819 SIVAL(pdata,22,ea_size);
3823 case SMB_INFO_IS_NAME_VALID:
3824 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3825 if (tran_call == TRANSACT2_QFILEINFO) {
3826 /* os/2 needs this ? really ?*/
3827 reply_doserror(req, ERRDOS, ERRbadfunc);
3834 case SMB_INFO_QUERY_EAS_FROM_LIST:
3836 size_t total_ea_len = 0;
3837 struct ea_list *ea_file_list = NULL;
3839 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3841 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3842 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3844 if (!ea_list || (total_ea_len > data_size)) {
3845 talloc_destroy(data_ctx);
3847 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3851 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3852 talloc_destroy(data_ctx);
3856 case SMB_INFO_QUERY_ALL_EAS:
3858 /* We have data_size bytes to put EA's into. */
3859 size_t total_ea_len = 0;
3861 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3863 data_ctx = talloc_init("ea_ctx");
3865 reply_nterror(req, NT_STATUS_NO_MEMORY);
3869 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3870 if (!ea_list || (total_ea_len > data_size)) {
3871 talloc_destroy(data_ctx);
3873 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3877 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3878 talloc_destroy(data_ctx);
3882 case SMB_FILE_BASIC_INFORMATION:
3883 case SMB_QUERY_FILE_BASIC_INFO:
3885 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3886 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3887 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3889 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3893 put_long_date_timespec(pdata,create_time_ts);
3894 put_long_date_timespec(pdata+8,atime_ts);
3895 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3896 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3897 SIVAL(pdata,32,mode);
3899 DEBUG(5,("SMB_QFBI - "));
3900 DEBUG(5,("create: %s ", ctime(&create_time)));
3901 DEBUG(5,("access: %s ", ctime(&atime)));
3902 DEBUG(5,("write: %s ", ctime(&mtime)));
3903 DEBUG(5,("change: %s ", ctime(&mtime)));
3904 DEBUG(5,("mode: %x\n", mode));
3907 case SMB_FILE_STANDARD_INFORMATION:
3908 case SMB_QUERY_FILE_STANDARD_INFO:
3910 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3912 SOFF_T(pdata,0,allocation_size);
3913 SOFF_T(pdata,8,file_size);
3914 SIVAL(pdata,16,nlink);
3915 SCVAL(pdata,20,delete_pending?1:0);
3916 SCVAL(pdata,21,(mode&aDIR)?1:0);
3917 SSVAL(pdata,22,0); /* Padding. */
3920 case SMB_FILE_EA_INFORMATION:
3921 case SMB_QUERY_FILE_EA_INFO:
3923 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3924 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3926 SIVAL(pdata,0,ea_size);
3930 /* Get the 8.3 name - used if NT SMB was negotiated. */
3931 case SMB_QUERY_FILE_ALT_NAME_INFO:
3932 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3936 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3937 pstrcpy(short_name,base_name);
3938 /* Mangle if not already 8.3 */
3939 if(!mangle_is_8_3(short_name, True, conn->params)) {
3940 mangle_map(short_name,True,True,conn->params);
3942 len = srvstr_push(dstart, req->flags2,
3943 pdata+4, short_name,
3944 PTR_DIFF(dend, pdata+4),
3946 data_size = 4 + len;
3951 case SMB_QUERY_FILE_NAME_INFO:
3953 this must be *exactly* right for ACLs on mapped drives to work
3955 len = srvstr_push(dstart, req->flags2,
3957 PTR_DIFF(dend, pdata+4),
3959 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3960 data_size = 4 + len;
3964 case SMB_FILE_ALLOCATION_INFORMATION:
3965 case SMB_QUERY_FILE_ALLOCATION_INFO:
3966 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3968 SOFF_T(pdata,0,allocation_size);
3971 case SMB_FILE_END_OF_FILE_INFORMATION:
3972 case SMB_QUERY_FILE_END_OF_FILEINFO:
3973 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3975 SOFF_T(pdata,0,file_size);
3978 case SMB_QUERY_FILE_ALL_INFO:
3979 case SMB_FILE_ALL_INFORMATION:
3981 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3982 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3983 put_long_date_timespec(pdata,create_time_ts);
3984 put_long_date_timespec(pdata+8,atime_ts);
3985 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3986 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3987 SIVAL(pdata,32,mode);
3988 SIVAL(pdata,36,0); /* padding. */
3990 SOFF_T(pdata,0,allocation_size);
3991 SOFF_T(pdata,8,file_size);
3992 SIVAL(pdata,16,nlink);
3993 SCVAL(pdata,20,delete_pending);
3994 SCVAL(pdata,21,(mode&aDIR)?1:0);
3997 SIVAL(pdata,0,ea_size);
3998 pdata += 4; /* EA info */
3999 len = srvstr_push(dstart, req->flags2,
4001 PTR_DIFF(dend, pdata+4),
4005 data_size = PTR_DIFF(pdata,(*ppdata));
4008 case SMB_FILE_INTERNAL_INFORMATION:
4009 /* This should be an index number - looks like
4012 I think this causes us to fail the IFSKIT
4013 BasicFileInformationTest. -tpot */
4015 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4016 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4017 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4021 case SMB_FILE_ACCESS_INFORMATION:
4022 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4023 SIVAL(pdata,0,access_mask);
4027 case SMB_FILE_NAME_INFORMATION:
4028 /* Pathname with leading '\'. */
4031 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4032 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4033 SIVAL(pdata,0,byte_len);
4034 data_size = 4 + byte_len;
4038 case SMB_FILE_DISPOSITION_INFORMATION:
4039 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4041 SCVAL(pdata,0,delete_pending);
4044 case SMB_FILE_POSITION_INFORMATION:
4045 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4047 SOFF_T(pdata,0,pos);
4050 case SMB_FILE_MODE_INFORMATION:
4051 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4052 SIVAL(pdata,0,mode);
4056 case SMB_FILE_ALIGNMENT_INFORMATION:
4057 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4058 SIVAL(pdata,0,0); /* No alignment needed. */
4064 * NT4 server just returns "invalid query" to this - if we try to answer
4065 * it then NTws gets a BSOD! (tridge).
4066 * W2K seems to want this. JRA.
4068 case SMB_QUERY_FILE_STREAM_INFO:
4070 case SMB_FILE_STREAM_INFORMATION:
4071 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4075 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4076 SIVAL(pdata,0,0); /* ??? */
4077 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4078 SOFF_T(pdata,8,file_size);
4079 SOFF_T(pdata,16,allocation_size);
4080 data_size = 24 + byte_len;
4084 case SMB_QUERY_COMPRESSION_INFO:
4085 case SMB_FILE_COMPRESSION_INFORMATION:
4086 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4087 SOFF_T(pdata,0,file_size);
4088 SIVAL(pdata,8,0); /* ??? */
4089 SIVAL(pdata,12,0); /* ??? */
4093 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4094 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4095 put_long_date_timespec(pdata,create_time_ts);
4096 put_long_date_timespec(pdata+8,atime_ts);
4097 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4098 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4099 SOFF_T(pdata,32,allocation_size);
4100 SOFF_T(pdata,40,file_size);
4101 SIVAL(pdata,48,mode);
4102 SIVAL(pdata,52,0); /* ??? */
4106 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4107 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4108 SIVAL(pdata,0,mode);
4114 * CIFS UNIX Extensions.
4117 case SMB_QUERY_FILE_UNIX_BASIC:
4119 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4120 data_size = PTR_DIFF(pdata,(*ppdata));
4124 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4126 for (i=0; i<100; i++)
4127 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4133 case SMB_QUERY_FILE_UNIX_INFO2:
4135 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4136 data_size = PTR_DIFF(pdata,(*ppdata));
4140 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4142 for (i=0; i<100; i++)
4143 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4149 case SMB_QUERY_FILE_UNIX_LINK:
4153 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4155 if(!S_ISLNK(sbuf.st_mode)) {
4156 reply_unixerror(req, ERRSRV,
4161 reply_unixerror(req, ERRDOS, ERRbadlink);
4164 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
4166 reply_unixerror(req, ERRDOS,
4171 len = srvstr_push(dstart, req->flags2,
4173 PTR_DIFF(dend, pdata),
4176 data_size = PTR_DIFF(pdata,(*ppdata));
4181 #if defined(HAVE_POSIX_ACLS)
4182 case SMB_QUERY_POSIX_ACL:
4184 SMB_ACL_T file_acl = NULL;
4185 SMB_ACL_T def_acl = NULL;
4186 uint16 num_file_acls = 0;
4187 uint16 num_def_acls = 0;
4189 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4190 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4192 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4195 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4196 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4200 NT_STATUS_NOT_IMPLEMENTED);
4204 if (S_ISDIR(sbuf.st_mode)) {
4205 if (fsp && fsp->is_directory) {
4206 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4208 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4210 def_acl = free_empty_sys_acl(conn, def_acl);
4213 num_file_acls = count_acl_entries(conn, file_acl);
4214 num_def_acls = count_acl_entries(conn, def_acl);
4216 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4217 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4219 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4220 SMB_POSIX_ACL_HEADER_SIZE) ));
4222 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4225 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4229 NT_STATUS_BUFFER_TOO_SMALL);
4233 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4234 SSVAL(pdata,2,num_file_acls);
4235 SSVAL(pdata,4,num_def_acls);
4236 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4238 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4241 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4244 req, NT_STATUS_INTERNAL_ERROR);
4247 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4249 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4252 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4256 NT_STATUS_INTERNAL_ERROR);
4261 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4264 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4266 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4272 case SMB_QUERY_POSIX_LOCK:
4274 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4276 SMB_BIG_UINT offset;
4278 enum brl_type lock_type;
4280 if (total_data != POSIX_LOCK_DATA_SIZE) {
4282 req, NT_STATUS_INVALID_PARAMETER);
4286 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4287 case POSIX_LOCK_TYPE_READ:
4288 lock_type = READ_LOCK;
4290 case POSIX_LOCK_TYPE_WRITE:
4291 lock_type = WRITE_LOCK;
4293 case POSIX_LOCK_TYPE_UNLOCK:
4295 /* There's no point in asking for an unlock... */
4296 talloc_destroy(data_ctx);
4299 NT_STATUS_INVALID_PARAMETER);
4303 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4304 #if defined(HAVE_LONGLONG)
4305 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4306 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4307 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4308 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4309 #else /* HAVE_LONGLONG */
4310 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4311 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4312 #endif /* HAVE_LONGLONG */
4314 status = query_lock(fsp,
4321 if (ERROR_WAS_LOCK_DENIED(status)) {
4322 /* Here we need to report who has it locked... */
4323 data_size = POSIX_LOCK_DATA_SIZE;
4325 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4326 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4327 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4328 #if defined(HAVE_LONGLONG)
4329 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4330 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4331 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4332 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4333 #else /* HAVE_LONGLONG */
4334 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4335 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4336 #endif /* HAVE_LONGLONG */
4338 } else if (NT_STATUS_IS_OK(status)) {
4339 /* For success we just return a copy of what we sent
4340 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4341 data_size = POSIX_LOCK_DATA_SIZE;
4342 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4343 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4345 reply_nterror(req, status);
4352 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4356 send_trans2_replies_new(req, params, param_size, *ppdata, data_size,
4362 /****************************************************************************
4363 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4365 ****************************************************************************/
4367 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4369 SMB_STRUCT_STAT sbuf1, sbuf2;
4370 pstring last_component_oldname;
4371 pstring last_component_newname;
4372 NTSTATUS status = NT_STATUS_OK;
4377 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4378 if (!NT_STATUS_IS_OK(status)) {
4382 status = check_name(conn, oldname);
4383 if (!NT_STATUS_IS_OK(status)) {
4387 /* source must already exist. */
4388 if (!VALID_STAT(sbuf1)) {
4389 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4392 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4393 if (!NT_STATUS_IS_OK(status)) {
4397 status = check_name(conn, newname);
4398 if (!NT_STATUS_IS_OK(status)) {
4402 /* Disallow if newname already exists. */
4403 if (VALID_STAT(sbuf2)) {
4404 return NT_STATUS_OBJECT_NAME_COLLISION;
4407 /* No links from a directory. */
4408 if (S_ISDIR(sbuf1.st_mode)) {
4409 return NT_STATUS_FILE_IS_A_DIRECTORY;
4412 /* Ensure this is within the share. */
4413 status = check_reduced_name(conn, oldname);
4414 if (!NT_STATUS_IS_OK(status)) {
4418 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4420 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4421 status = map_nt_error_from_unix(errno);
4422 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4423 nt_errstr(status), newname, oldname));
4429 /****************************************************************************
4430 Deal with setting the time from any of the setfilepathinfo functions.
4431 ****************************************************************************/
4433 static NTSTATUS smb_set_file_time(connection_struct *conn,
4436 const SMB_STRUCT_STAT *psbuf,
4437 struct timespec ts[2])
4440 FILE_NOTIFY_CHANGE_LAST_ACCESS
4441 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4444 if (!VALID_STAT(*psbuf)) {
4445 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4448 /* get some defaults (no modifications) if any info is zero or -1. */
4449 if (null_timespec(ts[0])) {
4450 ts[0] = get_atimespec(psbuf);
4451 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4454 if (null_timespec(ts[1])) {
4455 ts[1] = get_mtimespec(psbuf);
4456 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4459 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4460 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4463 * Try and set the times of this file if
4464 * they are different from the current values.
4468 struct timespec mts = get_mtimespec(psbuf);
4469 struct timespec ats = get_atimespec(psbuf);
4470 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4471 return NT_STATUS_OK;
4477 * This was a setfileinfo on an open file.
4478 * NT does this a lot. We also need to
4479 * set the time here, as it can be read by
4480 * FindFirst/FindNext and with the patch for bug #2045
4481 * in smbd/fileio.c it ensures that this timestamp is
4482 * kept sticky even after a write. We save the request
4483 * away and will set it on file close and after a write. JRA.
4486 if (!null_timespec(ts[1])) {
4487 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4488 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4489 fsp_set_pending_modtime(fsp, ts[1]);
4493 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4495 if(file_ntimes(conn, fname, ts)!=0) {
4496 return map_nt_error_from_unix(errno);
4499 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4501 return NT_STATUS_OK;
4504 /****************************************************************************
4505 Deal with setting the dosmode from any of the setfilepathinfo functions.
4506 ****************************************************************************/
4508 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4510 SMB_STRUCT_STAT *psbuf,
4513 if (!VALID_STAT(*psbuf)) {
4514 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4518 if (S_ISDIR(psbuf->st_mode)) {
4525 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4527 /* check the mode isn't different, before changing it */
4528 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4530 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4531 fname, (unsigned int)dosmode ));
4533 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4534 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4535 fname, strerror(errno)));
4536 return map_nt_error_from_unix(errno);
4539 return NT_STATUS_OK;
4542 /****************************************************************************
4543 Deal with setting the size from any of the setfilepathinfo functions.
4544 ****************************************************************************/
4546 static NTSTATUS smb_set_file_size(connection_struct *conn,
4547 struct smb_request *req,
4550 SMB_STRUCT_STAT *psbuf,
4553 NTSTATUS status = NT_STATUS_OK;
4554 files_struct *new_fsp = NULL;
4556 if (!VALID_STAT(*psbuf)) {
4557 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4560 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4562 if (size == get_file_size(*psbuf)) {
4563 return NT_STATUS_OK;
4566 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4567 fname, (double)size ));
4569 if (fsp && fsp->fh->fd != -1) {
4570 /* Handle based call. */
4571 if (vfs_set_filelen(fsp, size) == -1) {
4572 return map_nt_error_from_unix(errno);
4574 return NT_STATUS_OK;
4577 status = open_file_ntcreate(conn, req, fname, psbuf,
4579 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4582 FILE_ATTRIBUTE_NORMAL,
4583 FORCE_OPLOCK_BREAK_TO_NONE,
4586 if (!NT_STATUS_IS_OK(status)) {
4587 /* NB. We check for open_was_deferred in the caller. */
4591 if (vfs_set_filelen(new_fsp, size) == -1) {
4592 status = map_nt_error_from_unix(errno);
4593 close_file(new_fsp,NORMAL_CLOSE);
4597 close_file(new_fsp,NORMAL_CLOSE);
4598 return NT_STATUS_OK;
4601 /****************************************************************************
4602 Deal with SMB_INFO_SET_EA.
4603 ****************************************************************************/
4605 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4611 struct ea_list *ea_list = NULL;
4612 TALLOC_CTX *ctx = NULL;
4613 NTSTATUS status = NT_STATUS_OK;
4615 if (total_data < 10) {
4617 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4618 length. They seem to have no effect. Bug #3212. JRA */
4620 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4621 /* We're done. We only get EA info in this call. */
4622 return NT_STATUS_OK;
4625 return NT_STATUS_INVALID_PARAMETER;
4628 if (IVAL(pdata,0) > total_data) {
4629 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4630 IVAL(pdata,0), (unsigned int)total_data));
4631 return NT_STATUS_INVALID_PARAMETER;
4634 ctx = talloc_init("SMB_INFO_SET_EA");
4636 return NT_STATUS_NO_MEMORY;
4638 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4640 talloc_destroy(ctx);
4641 return NT_STATUS_INVALID_PARAMETER;
4643 status = set_ea(conn, fsp, fname, ea_list);
4644 talloc_destroy(ctx);
4649 /****************************************************************************
4650 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4651 ****************************************************************************/
4653 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4658 SMB_STRUCT_STAT *psbuf)
4660 NTSTATUS status = NT_STATUS_OK;
4661 BOOL delete_on_close;
4664 if (total_data < 1) {
4665 return NT_STATUS_INVALID_PARAMETER;
4669 return NT_STATUS_INVALID_HANDLE;
4672 delete_on_close = (CVAL(pdata,0) ? True : False);
4673 dosmode = dos_mode(conn, fname, psbuf);
4675 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4676 "delete_on_close = %u\n",
4678 (unsigned int)dosmode,
4679 (unsigned int)delete_on_close ));
4681 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4683 if (!NT_STATUS_IS_OK(status)) {
4687 /* The set is across all open files on this dev/inode pair. */
4688 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4689 return NT_STATUS_ACCESS_DENIED;
4691 return NT_STATUS_OK;
4694 /****************************************************************************
4695 Deal with SMB_FILE_POSITION_INFORMATION.
4696 ****************************************************************************/
4698 static NTSTATUS smb_file_position_information(connection_struct *conn,
4703 SMB_BIG_UINT position_information;
4705 if (total_data < 8) {
4706 return NT_STATUS_INVALID_PARAMETER;
4710 /* Ignore on pathname based set. */
4711 return NT_STATUS_OK;
4714 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4715 #ifdef LARGE_SMB_OFF_T
4716 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4717 #else /* LARGE_SMB_OFF_T */
4718 if (IVAL(pdata,4) != 0) {
4719 /* more than 32 bits? */
4720 return NT_STATUS_INVALID_PARAMETER;
4722 #endif /* LARGE_SMB_OFF_T */
4724 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4725 fsp->fsp_name, (double)position_information ));
4726 fsp->fh->position_information = position_information;
4727 return NT_STATUS_OK;
4730 /****************************************************************************
4731 Deal with SMB_FILE_MODE_INFORMATION.
4732 ****************************************************************************/
4734 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4740 if (total_data < 4) {
4741 return NT_STATUS_INVALID_PARAMETER;
4743 mode = IVAL(pdata,0);
4744 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4745 return NT_STATUS_INVALID_PARAMETER;
4747 return NT_STATUS_OK;
4750 /****************************************************************************
4751 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4752 ****************************************************************************/
4754 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4755 struct smb_request *req,
4760 pstring link_target;
4761 const char *newname = fname;
4762 NTSTATUS status = NT_STATUS_OK;
4764 /* Set a symbolic link. */
4765 /* Don't allow this if follow links is false. */
4767 if (total_data == 0) {
4768 return NT_STATUS_INVALID_PARAMETER;
4771 if (!lp_symlinks(SNUM(conn))) {
4772 return NT_STATUS_ACCESS_DENIED;
4775 srvstr_pull(pdata, req->flags2, link_target, pdata,
4776 sizeof(link_target), total_data, STR_TERMINATE);
4778 /* !widelinks forces the target path to be within the share. */
4779 /* This means we can interpret the target as a pathname. */
4780 if (!lp_widelinks(SNUM(conn))) {
4782 char *last_dirp = NULL;
4784 if (*link_target == '/') {
4785 /* No absolute paths allowed. */
4786 return NT_STATUS_ACCESS_DENIED;
4788 pstrcpy(rel_name, newname);
4789 last_dirp = strrchr_m(rel_name, '/');
4791 last_dirp[1] = '\0';
4793 pstrcpy(rel_name, "./");
4795 pstrcat(rel_name, link_target);
4797 status = check_name(conn, rel_name);
4798 if (!NT_STATUS_IS_OK(status)) {
4803 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4804 newname, link_target ));
4806 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4807 return map_nt_error_from_unix(errno);
4810 return NT_STATUS_OK;
4813 /****************************************************************************
4814 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4815 ****************************************************************************/
4817 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4818 struct smb_request *req,
4819 const char *pdata, int total_data,
4823 NTSTATUS status = NT_STATUS_OK;
4825 /* Set a hard link. */
4826 if (total_data == 0) {
4827 return NT_STATUS_INVALID_PARAMETER;
4830 srvstr_get_path(pdata, req->flags2, oldname, pdata,
4831 sizeof(oldname), total_data, STR_TERMINATE, &status);
4832 if (!NT_STATUS_IS_OK(status)) {
4836 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
4838 if (!NT_STATUS_IS_OK(status)) {
4842 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4845 return hardlink_internals(conn, oldname, fname);
4848 /****************************************************************************
4849 Deal with SMB_FILE_RENAME_INFORMATION.
4850 ****************************************************************************/
4852 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4853 struct smb_request *req,
4854 const char *pdata, int total_data,
4855 files_struct *fsp, pstring fname)
4862 BOOL dest_has_wcard = False;
4863 NTSTATUS status = NT_STATUS_OK;
4866 if (total_data < 13) {
4867 return NT_STATUS_INVALID_PARAMETER;
4870 overwrite = (CVAL(pdata,0) ? True : False);
4871 root_fid = IVAL(pdata,4);
4872 len = IVAL(pdata,8);
4874 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4875 return NT_STATUS_INVALID_PARAMETER;
4878 srvstr_get_path_wcard(pdata, req->flags2, newname, &pdata[12],
4879 sizeof(newname), len, 0, &status,
4881 if (!NT_STATUS_IS_OK(status)) {
4885 status = resolve_dfspath_wcard(conn,
4886 req->flags2 & FLAGS2_DFS_PATHNAMES,
4887 newname, &dest_has_wcard);
4888 if (!NT_STATUS_IS_OK(status)) {
4892 /* Check the new name has no '/' characters. */
4893 if (strchr_m(newname, '/')) {
4894 return NT_STATUS_NOT_SUPPORTED;
4897 /* Create the base directory. */
4898 pstrcpy(base_name, fname);
4899 p = strrchr_m(base_name, '/');
4903 pstrcpy(base_name, "./");
4905 /* Append the new name. */
4906 pstrcat(base_name, newname);
4909 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4910 fsp->fnum, fsp->fsp_name, base_name ));
4911 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4913 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4915 status = rename_internals(conn, req, fname, base_name, 0,
4916 overwrite, False, dest_has_wcard);
4922 /****************************************************************************
4923 Deal with SMB_SET_POSIX_ACL.
4924 ****************************************************************************/
4926 #if defined(HAVE_POSIX_ACLS)
4927 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4932 SMB_STRUCT_STAT *psbuf)
4934 uint16 posix_acl_version;
4935 uint16 num_file_acls;
4936 uint16 num_def_acls;
4937 BOOL valid_file_acls = True;
4938 BOOL valid_def_acls = True;
4940 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4941 return NT_STATUS_INVALID_PARAMETER;
4943 posix_acl_version = SVAL(pdata,0);
4944 num_file_acls = SVAL(pdata,2);
4945 num_def_acls = SVAL(pdata,4);
4947 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4948 valid_file_acls = False;
4952 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4953 valid_def_acls = False;
4957 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4958 return NT_STATUS_INVALID_PARAMETER;
4961 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4962 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4963 return NT_STATUS_INVALID_PARAMETER;
4966 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4967 fname ? fname : fsp->fsp_name,
4968 (unsigned int)num_file_acls,
4969 (unsigned int)num_def_acls));
4971 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4972 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4973 return map_nt_error_from_unix(errno);
4976 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4977 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4978 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4979 return map_nt_error_from_unix(errno);
4981 return NT_STATUS_OK;
4985 /****************************************************************************
4986 Deal with SMB_SET_POSIX_LOCK.
4987 ****************************************************************************/
4989 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4997 SMB_BIG_UINT offset;
4999 BOOL blocking_lock = False;
5000 enum brl_type lock_type;
5001 NTSTATUS status = NT_STATUS_OK;
5003 if (fsp == NULL || fsp->fh->fd == -1) {
5004 return NT_STATUS_INVALID_HANDLE;
5007 if (total_data != POSIX_LOCK_DATA_SIZE) {
5008 return NT_STATUS_INVALID_PARAMETER;
5011 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5012 case POSIX_LOCK_TYPE_READ:
5013 lock_type = READ_LOCK;
5015 case POSIX_LOCK_TYPE_WRITE:
5016 /* Return the right POSIX-mappable error code for files opened read-only. */
5017 if (!fsp->can_write) {
5018 return NT_STATUS_INVALID_HANDLE;
5020 lock_type = WRITE_LOCK;
5022 case POSIX_LOCK_TYPE_UNLOCK:
5023 lock_type = UNLOCK_LOCK;
5026 return NT_STATUS_INVALID_PARAMETER;
5029 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5030 blocking_lock = False;
5031 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5032 blocking_lock = True;
5034 return NT_STATUS_INVALID_PARAMETER;
5037 if (!lp_blocking_locks(SNUM(conn))) {
5038 blocking_lock = False;
5041 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5042 #if defined(HAVE_LONGLONG)
5043 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5044 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5045 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5046 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5047 #else /* HAVE_LONGLONG */
5048 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5049 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5050 #endif /* HAVE_LONGLONG */
5052 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5053 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5055 (unsigned int)lock_type,
5056 (unsigned int)lock_pid,
5060 if (lock_type == UNLOCK_LOCK) {
5061 status = do_unlock(smbd_messaging_context(),
5068 uint32 block_smbpid;
5070 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5081 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5083 * A blocking lock was requested. Package up
5084 * this smb into a queued request and push it
5085 * onto the blocking lock queue.
5087 if(push_blocking_lock_request(br_lck,
5088 (char *)inbuf, length,
5090 -1, /* infinite timeout. */
5098 TALLOC_FREE(br_lck);
5102 TALLOC_FREE(br_lck);
5108 /****************************************************************************
5109 Deal with SMB_INFO_STANDARD.
5110 ****************************************************************************/
5112 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5117 const SMB_STRUCT_STAT *psbuf)
5119 struct timespec ts[2];
5121 if (total_data < 12) {
5122 return NT_STATUS_INVALID_PARAMETER;
5126 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5128 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5130 DEBUG(10,("smb_set_info_standard: file %s\n",
5131 fname ? fname : fsp->fsp_name ));
5133 return smb_set_file_time(conn,
5140 /****************************************************************************
5141 Deal with SMB_SET_FILE_BASIC_INFO.
5142 ****************************************************************************/
5144 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5149 SMB_STRUCT_STAT *psbuf)
5151 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5152 struct timespec write_time;
5153 struct timespec changed_time;
5155 struct timespec ts[2];
5156 NTSTATUS status = NT_STATUS_OK;
5158 if (total_data < 36) {
5159 return NT_STATUS_INVALID_PARAMETER;
5162 /* Set the attributes */
5163 dosmode = IVAL(pdata,32);
5164 status = smb_set_file_dosmode(conn,
5168 if (!NT_STATUS_IS_OK(status)) {
5172 /* Ignore create time at offset pdata. */
5175 ts[0] = interpret_long_date(pdata+8);
5177 write_time = interpret_long_date(pdata+16);
5178 changed_time = interpret_long_date(pdata+24);
5181 ts[1] = timespec_min(&write_time, &changed_time);
5183 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5187 /* Prefer a defined time to an undefined one. */
5188 if (null_timespec(ts[1])) {
5189 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5192 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5193 fname ? fname : fsp->fsp_name ));
5195 return smb_set_file_time(conn,
5202 /****************************************************************************
5203 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5204 ****************************************************************************/
5206 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5207 struct smb_request *req,
5212 SMB_STRUCT_STAT *psbuf)
5214 SMB_BIG_UINT allocation_size = 0;
5215 NTSTATUS status = NT_STATUS_OK;
5216 files_struct *new_fsp = NULL;
5218 if (!VALID_STAT(*psbuf)) {
5219 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5222 if (total_data < 8) {
5223 return NT_STATUS_INVALID_PARAMETER;
5226 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5227 #ifdef LARGE_SMB_OFF_T
5228 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5229 #else /* LARGE_SMB_OFF_T */
5230 if (IVAL(pdata,4) != 0) {
5231 /* more than 32 bits? */
5232 return NT_STATUS_INVALID_PARAMETER;
5234 #endif /* LARGE_SMB_OFF_T */
5236 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5237 fname, (double)allocation_size ));
5239 if (allocation_size) {
5240 allocation_size = smb_roundup(conn, allocation_size);
5243 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5244 fname, (double)allocation_size ));
5246 if (fsp && fsp->fh->fd != -1) {
5247 /* Open file handle. */
5248 /* Only change if needed. */
5249 if (allocation_size != get_file_size(*psbuf)) {
5250 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5251 return map_nt_error_from_unix(errno);
5254 /* But always update the time. */
5255 if (null_timespec(fsp->pending_modtime)) {
5257 * This is equivalent to a write. Ensure it's seen immediately
5258 * if there are no pending writes.
5260 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5262 return NT_STATUS_OK;
5265 /* Pathname or stat or directory file. */
5267 status = open_file_ntcreate(conn, req, fname, psbuf,
5269 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5272 FILE_ATTRIBUTE_NORMAL,
5273 FORCE_OPLOCK_BREAK_TO_NONE,
5276 if (!NT_STATUS_IS_OK(status)) {
5277 /* NB. We check for open_was_deferred in the caller. */
5281 /* Only change if needed. */
5282 if (allocation_size != get_file_size(*psbuf)) {
5283 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5284 status = map_nt_error_from_unix(errno);
5285 close_file(new_fsp,NORMAL_CLOSE);
5290 /* Changing the allocation size should set the last mod time. */
5291 /* Don't need to call set_filetime as this will be flushed on
5294 fsp_set_pending_modtime(new_fsp, timespec_current());
5296 close_file(new_fsp,NORMAL_CLOSE);
5297 return NT_STATUS_OK;
5300 /****************************************************************************
5301 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5302 ****************************************************************************/
5304 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5305 struct smb_request *req,
5310 SMB_STRUCT_STAT *psbuf)
5314 if (total_data < 8) {
5315 return NT_STATUS_INVALID_PARAMETER;
5318 size = IVAL(pdata,0);
5319 #ifdef LARGE_SMB_OFF_T
5320 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5321 #else /* LARGE_SMB_OFF_T */
5322 if (IVAL(pdata,4) != 0) {
5323 /* more than 32 bits? */
5324 return NT_STATUS_INVALID_PARAMETER;
5326 #endif /* LARGE_SMB_OFF_T */
5327 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5328 "file %s to %.0f\n", fname, (double)size ));
5330 return smb_set_file_size(conn, req,
5337 /****************************************************************************
5338 Allow a UNIX info mknod.
5339 ****************************************************************************/
5341 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5345 SMB_STRUCT_STAT *psbuf)
5347 uint32 file_type = IVAL(pdata,56);
5348 #if defined(HAVE_MAKEDEV)
5349 uint32 dev_major = IVAL(pdata,60);
5350 uint32 dev_minor = IVAL(pdata,68);
5352 SMB_DEV_T dev = (SMB_DEV_T)0;
5353 uint32 raw_unixmode = IVAL(pdata,84);
5357 if (total_data < 100) {
5358 return NT_STATUS_INVALID_PARAMETER;
5361 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5362 if (!NT_STATUS_IS_OK(status)) {
5366 #if defined(HAVE_MAKEDEV)
5367 dev = makedev(dev_major, dev_minor);
5370 switch (file_type) {
5371 #if defined(S_IFIFO)
5372 case UNIX_TYPE_FIFO:
5373 unixmode |= S_IFIFO;
5376 #if defined(S_IFSOCK)
5377 case UNIX_TYPE_SOCKET:
5378 unixmode |= S_IFSOCK;
5381 #if defined(S_IFCHR)
5382 case UNIX_TYPE_CHARDEV:
5383 unixmode |= S_IFCHR;
5386 #if defined(S_IFBLK)
5387 case UNIX_TYPE_BLKDEV:
5388 unixmode |= S_IFBLK;
5392 return NT_STATUS_INVALID_PARAMETER;
5395 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5396 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5398 /* Ok - do the mknod. */
5399 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5400 return map_nt_error_from_unix(errno);
5403 /* If any of the other "set" calls fail we
5404 * don't want to end up with a half-constructed mknod.
5407 if (lp_inherit_perms(SNUM(conn))) {
5409 conn, parent_dirname(fname),
5413 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5414 status = map_nt_error_from_unix(errno);
5415 SMB_VFS_UNLINK(conn,fname);
5418 return NT_STATUS_OK;
5421 /****************************************************************************
5422 Deal with SMB_SET_FILE_UNIX_BASIC.
5423 ****************************************************************************/
5425 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5426 struct smb_request *req,
5431 SMB_STRUCT_STAT *psbuf)
5433 struct timespec ts[2];
5434 uint32 raw_unixmode;
5437 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5438 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5439 NTSTATUS status = NT_STATUS_OK;
5440 BOOL delete_on_fail = False;
5441 enum perm_type ptype;
5443 if (total_data < 100) {
5444 return NT_STATUS_INVALID_PARAMETER;
5447 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5448 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5449 size=IVAL(pdata,0); /* first 8 Bytes are size */
5450 #ifdef LARGE_SMB_OFF_T
5451 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5452 #else /* LARGE_SMB_OFF_T */
5453 if (IVAL(pdata,4) != 0) {
5454 /* more than 32 bits? */
5455 return NT_STATUS_INVALID_PARAMETER;
5457 #endif /* LARGE_SMB_OFF_T */
5460 ts[0] = interpret_long_date(pdata+24); /* access_time */
5461 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5462 set_owner = (uid_t)IVAL(pdata,40);
5463 set_grp = (gid_t)IVAL(pdata,48);
5464 raw_unixmode = IVAL(pdata,84);
5466 if (VALID_STAT(*psbuf)) {
5467 if (S_ISDIR(psbuf->st_mode)) {
5468 ptype = PERM_EXISTING_DIR;
5470 ptype = PERM_EXISTING_FILE;
5473 ptype = PERM_NEW_FILE;
5476 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5477 if (!NT_STATUS_IS_OK(status)) {
5481 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5482 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5483 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5485 if (!VALID_STAT(*psbuf)) {
5487 * The only valid use of this is to create character and block
5488 * devices, and named pipes. This is deprecated (IMHO) and
5489 * a new info level should be used for mknod. JRA.
5492 status = smb_unix_mknod(conn,
5497 if (!NT_STATUS_IS_OK(status)) {
5501 /* Ensure we don't try and change anything else. */
5502 raw_unixmode = SMB_MODE_NO_CHANGE;
5503 size = get_file_size(*psbuf);
5504 ts[0] = get_atimespec(psbuf);
5505 ts[1] = get_mtimespec(psbuf);
5507 * We continue here as we might want to change the
5510 delete_on_fail = True;
5514 /* Horrible backwards compatibility hack as an old server bug
5515 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5519 size = get_file_size(*psbuf);
5524 * Deal with the UNIX specific mode set.
5527 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5528 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5529 (unsigned int)unixmode, fname ));
5530 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5531 return map_nt_error_from_unix(errno);
5536 * Deal with the UNIX specific uid set.
5539 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5542 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5543 (unsigned int)set_owner, fname ));
5545 if (S_ISLNK(psbuf->st_mode)) {
5546 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5548 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5552 status = map_nt_error_from_unix(errno);
5553 if (delete_on_fail) {
5554 SMB_VFS_UNLINK(conn,fname);
5561 * Deal with the UNIX specific gid set.
5564 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5565 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5566 (unsigned int)set_owner, fname ));
5567 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5568 status = map_nt_error_from_unix(errno);
5569 if (delete_on_fail) {
5570 SMB_VFS_UNLINK(conn,fname);
5576 /* Deal with any size changes. */
5578 status = smb_set_file_size(conn, req,
5583 if (!NT_STATUS_IS_OK(status)) {
5587 /* Deal with any time changes. */
5589 return smb_set_file_time(conn,
5596 /****************************************************************************
5597 Deal with SMB_SET_FILE_UNIX_INFO2.
5598 ****************************************************************************/
5600 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5601 struct smb_request *req,
5606 SMB_STRUCT_STAT *psbuf)
5612 if (total_data < 116) {
5613 return NT_STATUS_INVALID_PARAMETER;
5616 /* Start by setting all the fields that are common between UNIX_BASIC
5619 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5621 if (!NT_STATUS_IS_OK(status)) {
5625 smb_fflags = IVAL(pdata, 108);
5626 smb_fmask = IVAL(pdata, 112);
5628 /* NB: We should only attempt to alter the file flags if the client
5629 * sends a non-zero mask.
5631 if (smb_fmask != 0) {
5632 int stat_fflags = 0;
5634 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5636 /* Client asked to alter a flag we don't understand. */
5637 return NT_STATUS_INVALID_PARAMETER;
5640 if (fsp && fsp->fh->fd != -1) {
5641 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5642 return NT_STATUS_NOT_SUPPORTED;
5644 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5645 return map_nt_error_from_unix(errno);
5650 /* XXX: need to add support for changing the create_time here. You
5651 * can do this for paths on Darwin with setattrlist(2). The right way
5652 * to hook this up is probably by extending the VFS utimes interface.
5655 return NT_STATUS_OK;
5658 /****************************************************************************
5659 Create a directory with POSIX semantics.
5660 ****************************************************************************/
5662 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5663 struct smb_request *req,
5667 SMB_STRUCT_STAT *psbuf,
5668 int *pdata_return_size)
5670 NTSTATUS status = NT_STATUS_OK;
5671 uint32 raw_unixmode = 0;
5672 uint32 mod_unixmode = 0;
5673 mode_t unixmode = (mode_t)0;
5674 files_struct *fsp = NULL;
5675 uint16 info_level_return = 0;
5677 char *pdata = *ppdata;
5679 if (total_data < 18) {
5680 return NT_STATUS_INVALID_PARAMETER;
5683 raw_unixmode = IVAL(pdata,8);
5684 /* Next 4 bytes are not yet defined. */
5686 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5687 if (!NT_STATUS_IS_OK(status)) {
5691 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5693 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5694 fname, (unsigned int)unixmode ));
5696 status = open_directory(conn, req,
5699 FILE_READ_ATTRIBUTES, /* Just a stat open */
5700 FILE_SHARE_NONE, /* Ignored for stat opens */
5707 if (NT_STATUS_IS_OK(status)) {
5708 close_file(fsp, NORMAL_CLOSE);
5711 info_level_return = SVAL(pdata,16);
5713 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5714 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5715 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5716 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5718 *pdata_return_size = 12;
5721 /* Realloc the data size */
5722 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5723 if (*ppdata == NULL) {
5724 *pdata_return_size = 0;
5725 return NT_STATUS_NO_MEMORY;
5729 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5730 SSVAL(pdata,2,0); /* No fnum. */
5731 SIVAL(pdata,4,info); /* Was directory created. */
5733 switch (info_level_return) {
5734 case SMB_QUERY_FILE_UNIX_BASIC:
5735 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5736 SSVAL(pdata,10,0); /* Padding. */
5737 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5739 case SMB_QUERY_FILE_UNIX_INFO2:
5740 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5741 SSVAL(pdata,10,0); /* Padding. */
5742 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5745 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5746 SSVAL(pdata,10,0); /* Padding. */
5753 /****************************************************************************
5754 Open/Create a file with POSIX semantics.
5755 ****************************************************************************/
5757 static NTSTATUS smb_posix_open(connection_struct *conn,
5758 struct smb_request *req,
5762 SMB_STRUCT_STAT *psbuf,
5763 int *pdata_return_size)
5765 BOOL extended_oplock_granted = False;
5766 char *pdata = *ppdata;
5768 uint32 wire_open_mode = 0;
5769 uint32 raw_unixmode = 0;
5770 uint32 mod_unixmode = 0;
5771 uint32 create_disp = 0;
5772 uint32 access_mask = 0;
5773 uint32 create_options = 0;
5774 NTSTATUS status = NT_STATUS_OK;
5775 mode_t unixmode = (mode_t)0;
5776 files_struct *fsp = NULL;
5777 int oplock_request = 0;
5779 uint16 info_level_return = 0;
5781 if (total_data < 18) {
5782 return NT_STATUS_INVALID_PARAMETER;
5785 flags = IVAL(pdata,0);
5786 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5787 if (oplock_request) {
5788 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5791 wire_open_mode = IVAL(pdata,4);
5793 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5794 return smb_posix_mkdir(conn, req,
5802 switch (wire_open_mode & SMB_ACCMODE) {
5804 access_mask = FILE_READ_DATA;
5807 access_mask = FILE_WRITE_DATA;
5810 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5813 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5814 (unsigned int)wire_open_mode ));
5815 return NT_STATUS_INVALID_PARAMETER;
5818 wire_open_mode &= ~SMB_ACCMODE;
5820 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5821 create_disp = FILE_CREATE;
5822 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5823 create_disp = FILE_OVERWRITE_IF;
5824 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5825 create_disp = FILE_OPEN_IF;
5827 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5828 (unsigned int)wire_open_mode ));
5829 return NT_STATUS_INVALID_PARAMETER;
5832 raw_unixmode = IVAL(pdata,8);
5833 /* Next 4 bytes are not yet defined. */
5835 status = unix_perms_from_wire(conn,
5838 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5841 if (!NT_STATUS_IS_OK(status)) {
5845 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5847 if (wire_open_mode & SMB_O_SYNC) {
5848 create_options |= FILE_WRITE_THROUGH;
5850 if (wire_open_mode & SMB_O_APPEND) {
5851 access_mask |= FILE_APPEND_DATA;
5853 if (wire_open_mode & SMB_O_DIRECT) {
5854 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5857 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5859 (unsigned int)wire_open_mode,
5860 (unsigned int)unixmode ));
5862 status = open_file_ntcreate(conn, req,
5866 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5868 0, /* no create options yet. */
5874 if (!NT_STATUS_IS_OK(status)) {
5878 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5879 extended_oplock_granted = True;
5882 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5883 extended_oplock_granted = True;
5886 info_level_return = SVAL(pdata,16);
5888 /* Allocate the correct return size. */
5890 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5891 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5892 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5893 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5895 *pdata_return_size = 12;
5898 /* Realloc the data size */
5899 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5900 if (*ppdata == NULL) {
5901 close_file(fsp,ERROR_CLOSE);
5902 *pdata_return_size = 0;
5903 return NT_STATUS_NO_MEMORY;
5907 if (extended_oplock_granted) {
5908 if (flags & REQUEST_BATCH_OPLOCK) {
5909 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5911 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5913 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5914 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5916 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5919 SSVAL(pdata,2,fsp->fnum);
5920 SIVAL(pdata,4,info); /* Was file created etc. */
5922 switch (info_level_return) {
5923 case SMB_QUERY_FILE_UNIX_BASIC:
5924 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5925 SSVAL(pdata,10,0); /* padding. */
5926 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5928 case SMB_QUERY_FILE_UNIX_INFO2:
5929 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5930 SSVAL(pdata,10,0); /* padding. */
5931 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5934 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5935 SSVAL(pdata,10,0); /* padding. */
5938 return NT_STATUS_OK;
5941 /****************************************************************************
5942 Delete a file with POSIX semantics.
5943 ****************************************************************************/
5945 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5946 struct smb_request *req,
5950 SMB_STRUCT_STAT *psbuf)
5952 NTSTATUS status = NT_STATUS_OK;
5953 files_struct *fsp = NULL;
5958 struct share_mode_lock *lck = NULL;
5960 if (total_data < 2) {
5961 return NT_STATUS_INVALID_PARAMETER;
5964 flags = SVAL(pdata,0);
5966 if (!VALID_STAT(*psbuf)) {
5967 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5970 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5971 !VALID_STAT_OF_DIR(*psbuf)) {
5972 return NT_STATUS_NOT_A_DIRECTORY;
5975 DEBUG(10,("smb_posix_unlink: %s %s\n",
5976 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5979 if (VALID_STAT_OF_DIR(*psbuf)) {
5980 status = open_directory(conn, req,
5984 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5987 FILE_FLAG_POSIX_SEMANTICS|0777,
5992 status = open_file_ntcreate(conn, req,
5996 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5999 FILE_FLAG_POSIX_SEMANTICS|0777,
6000 0, /* No oplock, but break existing ones. */
6005 if (!NT_STATUS_IS_OK(status)) {
6010 * Don't lie to client. If we can't really delete due to
6011 * non-POSIX opens return SHARING_VIOLATION.
6014 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6016 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6017 "lock for file %s\n", fsp->fsp_name));
6018 close_file(fsp, NORMAL_CLOSE);
6019 return NT_STATUS_INVALID_PARAMETER;
6023 * See if others still have the file open. If this is the case, then
6024 * don't delete. If all opens are POSIX delete we can set the delete
6025 * on close disposition.
6027 for (i=0; i<lck->num_share_modes; i++) {
6028 struct share_mode_entry *e = &lck->share_modes[i];
6029 if (is_valid_share_mode_entry(e)) {
6030 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6033 /* Fail with sharing violation. */
6034 close_file(fsp, NORMAL_CLOSE);
6036 return NT_STATUS_SHARING_VIOLATION;
6041 * Set the delete on close.
6043 status = smb_set_file_disposition_info(conn,
6050 if (!NT_STATUS_IS_OK(status)) {
6051 close_file(fsp, NORMAL_CLOSE);
6056 return close_file(fsp, NORMAL_CLOSE);
6059 /****************************************************************************
6060 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6061 ****************************************************************************/
6063 static void call_trans2setfilepathinfo(connection_struct *conn,
6064 struct smb_request *req,
6065 unsigned int tran_call,
6066 char **pparams, int total_params,
6067 char **ppdata, int total_data,
6068 unsigned int max_data_bytes)
6070 char *params = *pparams;
6071 char *pdata = *ppdata;
6073 SMB_STRUCT_STAT sbuf;
6075 files_struct *fsp = NULL;
6076 NTSTATUS status = NT_STATUS_OK;
6077 int data_return_size = 0;
6080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6086 if (tran_call == TRANSACT2_SETFILEINFO) {
6087 if (total_params < 4) {
6088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6092 fsp = file_fsp(SVAL(params,0));
6093 info_level = SVAL(params,2);
6095 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
6097 * This is actually a SETFILEINFO on a directory
6098 * handle (returned from an NT SMB). NT5.0 seems
6099 * to do this call. JRA.
6101 pstrcpy(fname, fsp->fsp_name);
6102 if (INFO_LEVEL_IS_UNIX(info_level)) {
6103 /* Always do lstat for UNIX calls. */
6104 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6105 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6106 reply_unixerror(req,ERRDOS,ERRbadpath);
6110 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6111 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6112 reply_unixerror(req,ERRDOS,ERRbadpath);
6116 } else if (fsp && fsp->print_file) {
6118 * Doing a DELETE_ON_CLOSE should cancel a print job.
6120 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6121 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6123 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6126 send_trans2_replies_new(req, params, 2,
6132 reply_unixerror(req, ERRDOS, ERRbadpath);
6137 * Original code - this is an open file.
6139 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6143 pstrcpy(fname, fsp->fsp_name);
6145 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6146 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6147 reply_unixerror(req, ERRDOS, ERRbadfid);
6153 if (total_params < 7) {
6154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6158 info_level = SVAL(params,0);
6159 srvstr_get_path(params, req->flags2, fname, ¶ms[6],
6160 sizeof(fname), total_params - 6, STR_TERMINATE,
6162 if (!NT_STATUS_IS_OK(status)) {
6163 reply_nterror(req, status);
6167 status = resolve_dfspath(conn,
6168 req->flags2 & FLAGS2_DFS_PATHNAMES,
6170 if (!NT_STATUS_IS_OK(status)) {
6171 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6172 reply_botherror(req,
6173 NT_STATUS_PATH_NOT_COVERED,
6174 ERRSRV, ERRbadpath);
6177 reply_nterror(req, status);
6181 status = unix_convert(conn, fname, False, NULL, &sbuf);
6182 if (!NT_STATUS_IS_OK(status)) {
6183 reply_nterror(req, status);
6187 status = check_name(conn, fname);
6188 if (!NT_STATUS_IS_OK(status)) {
6189 reply_nterror(req, status);
6193 if (INFO_LEVEL_IS_UNIX(info_level)) {
6195 * For CIFS UNIX extensions the target name may not exist.
6198 /* Always do lstat for UNIX calls. */
6199 SMB_VFS_LSTAT(conn,fname,&sbuf);
6201 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6202 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6203 reply_unixerror(req, ERRDOS, ERRbadpath);
6208 if (!CAN_WRITE(conn)) {
6209 reply_doserror(req, ERRSRV, ERRaccess);
6213 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6214 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6218 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6219 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6221 /* Realloc the parameter size */
6222 *pparams = (char *)SMB_REALLOC(*pparams,2);
6223 if (*pparams == NULL) {
6224 reply_nterror(req, NT_STATUS_NO_MEMORY);
6231 if (fsp && !null_timespec(fsp->pending_modtime)) {
6232 /* the pending modtime overrides the current modtime */
6233 set_mtimespec(&sbuf, fsp->pending_modtime);
6236 switch (info_level) {
6238 case SMB_INFO_STANDARD:
6240 status = smb_set_info_standard(conn,
6249 case SMB_INFO_SET_EA:
6251 status = smb_info_set_ea(conn,
6259 case SMB_SET_FILE_BASIC_INFO:
6260 case SMB_FILE_BASIC_INFORMATION:
6262 status = smb_set_file_basic_info(conn,
6271 case SMB_FILE_ALLOCATION_INFORMATION:
6272 case SMB_SET_FILE_ALLOCATION_INFO:
6274 status = smb_set_file_allocation_info(conn, req,
6283 case SMB_FILE_END_OF_FILE_INFORMATION:
6284 case SMB_SET_FILE_END_OF_FILE_INFO:
6286 status = smb_set_file_end_of_file_info(conn, req,
6295 case SMB_FILE_DISPOSITION_INFORMATION:
6296 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6299 /* JRA - We used to just ignore this on a path ?
6300 * Shouldn't this be invalid level on a pathname
6303 if (tran_call != TRANSACT2_SETFILEINFO) {
6304 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6307 status = smb_set_file_disposition_info(conn,
6316 case SMB_FILE_POSITION_INFORMATION:
6318 status = smb_file_position_information(conn,
6325 /* From tridge Samba4 :
6326 * MODE_INFORMATION in setfileinfo (I have no
6327 * idea what "mode information" on a file is - it takes a value of 0,
6328 * 2, 4 or 6. What could it be?).
6331 case SMB_FILE_MODE_INFORMATION:
6333 status = smb_file_mode_information(conn,
6340 * CIFS UNIX extensions.
6343 case SMB_SET_FILE_UNIX_BASIC:
6345 status = smb_set_file_unix_basic(conn, req,
6354 case SMB_SET_FILE_UNIX_INFO2:
6356 status = smb_set_file_unix_info2(conn, req,
6365 case SMB_SET_FILE_UNIX_LINK:
6367 if (tran_call != TRANSACT2_SETPATHINFO) {
6368 /* We must have a pathname for this. */
6369 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6372 status = smb_set_file_unix_link(conn, req, pdata,
6377 case SMB_SET_FILE_UNIX_HLINK:
6379 if (tran_call != TRANSACT2_SETPATHINFO) {
6380 /* We must have a pathname for this. */
6381 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6384 status = smb_set_file_unix_hlink(conn, req,
6390 case SMB_FILE_RENAME_INFORMATION:
6392 status = smb_file_rename_information(conn, req,
6398 #if defined(HAVE_POSIX_ACLS)
6399 case SMB_SET_POSIX_ACL:
6401 status = smb_set_posix_acl(conn,
6411 case SMB_SET_POSIX_LOCK:
6413 if (tran_call != TRANSACT2_SETFILEINFO) {
6414 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6417 status = smb_set_posix_lock(conn, req->inbuf,
6418 smb_len(req->inbuf) + 4,
6419 pdata, total_data, fsp);
6423 case SMB_POSIX_PATH_OPEN:
6425 if (tran_call != TRANSACT2_SETPATHINFO) {
6426 /* We must have a pathname for this. */
6427 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6431 status = smb_posix_open(conn, req,
6440 case SMB_POSIX_PATH_UNLINK:
6442 if (tran_call != TRANSACT2_SETPATHINFO) {
6443 /* We must have a pathname for this. */
6444 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6448 status = smb_posix_unlink(conn, req,
6457 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6462 if (!NT_STATUS_IS_OK(status)) {
6463 if (open_was_deferred(req->mid)) {
6464 /* We have re-scheduled this call. */
6467 if (blocking_lock_was_deferred(req->mid)) {
6468 /* We have re-scheduled this call. */
6471 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6472 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6473 ERRSRV, ERRbadpath);
6476 reply_nterror(req, status);
6481 send_trans2_replies_new(req, params, 2, *ppdata, data_return_size,
6487 /****************************************************************************
6488 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6489 ****************************************************************************/
6491 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6492 char **pparams, int total_params,
6493 char **ppdata, int total_data,
6494 unsigned int max_data_bytes)
6496 char *params = *pparams;
6497 char *pdata = *ppdata;
6499 SMB_STRUCT_STAT sbuf;
6500 NTSTATUS status = NT_STATUS_OK;
6501 struct ea_list *ea_list = NULL;
6503 if (!CAN_WRITE(conn)) {
6504 reply_doserror(req, ERRSRV, ERRaccess);
6508 if (total_params < 5) {
6509 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6513 srvstr_get_path(params, req->flags2, directory, ¶ms[4],
6514 sizeof(directory), total_params - 4, STR_TERMINATE,
6516 if (!NT_STATUS_IS_OK(status)) {
6517 reply_nterror(req, status);
6521 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6523 status = unix_convert(conn, directory, False, NULL, &sbuf);
6524 if (!NT_STATUS_IS_OK(status)) {
6525 reply_nterror(req, status);
6529 status = check_name(conn, directory);
6530 if (!NT_STATUS_IS_OK(status)) {
6531 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6532 reply_nterror(req, status);
6536 /* Any data in this call is an EA list. */
6537 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6538 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6543 * OS/2 workplace shell seems to send SET_EA requests of "null"
6544 * length (4 bytes containing IVAL 4).
6545 * They seem to have no effect. Bug #3212. JRA.
6548 if (total_data != 4) {
6549 if (total_data < 10) {
6550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6554 if (IVAL(pdata,0) > total_data) {
6555 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6556 IVAL(pdata,0), (unsigned int)total_data));
6557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6561 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6567 } else if (IVAL(pdata,0) != 4) {
6568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6572 status = create_directory(conn, directory);
6574 if (!NT_STATUS_IS_OK(status)) {
6575 reply_nterror(req, status);
6579 /* Try and set any given EA. */
6581 status = set_ea(conn, NULL, directory, ea_list);
6582 if (!NT_STATUS_IS_OK(status)) {
6583 reply_nterror(req, status);
6588 /* Realloc the parameter and data sizes */
6589 *pparams = (char *)SMB_REALLOC(*pparams,2);
6590 if(*pparams == NULL) {
6591 reply_nterror(req, NT_STATUS_NO_MEMORY);
6598 send_trans2_replies_new(req, params, 2, *ppdata, 0, max_data_bytes);
6603 /****************************************************************************
6604 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6605 We don't actually do this - we just send a null response.
6606 ****************************************************************************/
6608 static void call_trans2findnotifyfirst(connection_struct *conn,
6609 struct smb_request *req,
6610 char **pparams, int total_params,
6611 char **ppdata, int total_data,
6612 unsigned int max_data_bytes)
6614 static uint16 fnf_handle = 257;
6615 char *params = *pparams;
6618 if (total_params < 6) {
6619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6623 info_level = SVAL(params,4);
6624 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6626 switch (info_level) {
6631 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6635 /* Realloc the parameter and data sizes */
6636 *pparams = (char *)SMB_REALLOC(*pparams,6);
6637 if (*pparams == NULL) {
6638 reply_nterror(req, NT_STATUS_NO_MEMORY);
6643 SSVAL(params,0,fnf_handle);
6644 SSVAL(params,2,0); /* No changes */
6645 SSVAL(params,4,0); /* No EA errors */
6652 send_trans2_replies_new(req, params, 6, *ppdata, 0, max_data_bytes);
6657 /****************************************************************************
6658 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6659 changes). Currently this does nothing.
6660 ****************************************************************************/
6662 static void call_trans2findnotifynext(connection_struct *conn,
6663 struct smb_request *req,
6664 char **pparams, int total_params,
6665 char **ppdata, int total_data,
6666 unsigned int max_data_bytes)
6668 char *params = *pparams;
6670 DEBUG(3,("call_trans2findnotifynext\n"));
6672 /* Realloc the parameter and data sizes */
6673 *pparams = (char *)SMB_REALLOC(*pparams,4);
6674 if (*pparams == NULL) {
6675 reply_nterror(req, NT_STATUS_NO_MEMORY);
6680 SSVAL(params,0,0); /* No changes */
6681 SSVAL(params,2,0); /* No EA errors */
6683 send_trans2_replies_new(req, params, 4, *ppdata, 0, max_data_bytes);
6688 /****************************************************************************
6689 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6690 ****************************************************************************/
6692 static void call_trans2getdfsreferral(connection_struct *conn,
6693 struct smb_request *req,
6694 char **pparams, int total_params,
6695 char **ppdata, int total_data,
6696 unsigned int max_data_bytes)
6698 char *params = *pparams;
6701 int max_referral_level;
6702 NTSTATUS status = NT_STATUS_OK;
6704 DEBUG(10,("call_trans2getdfsreferral\n"));
6706 if (total_params < 3) {
6707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6711 max_referral_level = SVAL(params,0);
6713 if(!lp_host_msdfs()) {
6714 reply_doserror(req, ERRDOS, ERRbadfunc);
6718 srvstr_pull(params, req->flags2, pathname, ¶ms[2],
6719 sizeof(pathname), total_params - 2, STR_TERMINATE);
6720 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6721 ppdata,&status)) < 0) {
6722 reply_nterror(req, status);
6726 SSVAL(req->inbuf, smb_flg2,
6727 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6728 send_trans2_replies_new(req,0,0,*ppdata,reply_size, max_data_bytes);
6733 #define LMCAT_SPL 0x53
6734 #define LMFUNC_GETJOBID 0x60
6736 /****************************************************************************
6737 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6738 ****************************************************************************/
6740 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6741 char **pparams, int total_params, char **ppdata, int total_data,
6742 unsigned int max_data_bytes)
6744 char *pdata = *ppdata;
6745 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv15));
6747 /* check for an invalid fid before proceeding */
6750 return(ERROR_DOS(ERRDOS,ERRbadfid));
6752 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6753 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6754 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6755 if (*ppdata == NULL) {
6756 return ERROR_NT(NT_STATUS_NO_MEMORY);
6760 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6761 CAN ACCEPT THIS IN UNICODE. JRA. */
6763 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6764 srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata + 2,
6765 global_myname(), 15,
6766 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6767 srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata+18,
6768 lp_servicename(SNUM(conn)), 13,
6769 STR_ASCII|STR_TERMINATE); /* Service name */
6770 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6773 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6774 return ERROR_DOS(ERRSRV,ERRerror);
6778 /****************************************************************************
6779 Reply to a SMBfindclose (stop trans2 directory search).
6780 ****************************************************************************/
6782 int reply_findclose(connection_struct *conn,
6783 char *inbuf,char *outbuf,int length,int bufsize)
6786 int dptr_num=SVALS(inbuf,smb_vwv0);
6787 START_PROFILE(SMBfindclose);
6789 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6791 dptr_close(&dptr_num);
6793 outsize = set_message(inbuf, outbuf,0,0,False);
6795 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6797 END_PROFILE(SMBfindclose);
6801 /****************************************************************************
6802 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6803 ****************************************************************************/
6805 int reply_findnclose(connection_struct *conn,
6806 char *inbuf,char *outbuf,int length,int bufsize)
6810 START_PROFILE(SMBfindnclose);
6812 dptr_num = SVAL(inbuf,smb_vwv0);
6814 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6816 /* We never give out valid handles for a
6817 findnotifyfirst - so any dptr_num is ok here.
6820 outsize = set_message(inbuf, outbuf,0,0,False);
6822 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6824 END_PROFILE(SMBfindnclose);
6828 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6829 struct trans_state *state,
6830 char *inbuf, char *outbuf, int size, int bufsize)
6834 if (Protocol >= PROTOCOL_NT1) {
6835 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6838 /* Now we must call the relevant TRANS2 function */
6839 switch(state->call) {
6840 case TRANSACT2_OPEN:
6842 START_PROFILE(Trans2_open);
6843 call_trans2open(conn, req,
6844 &state->param, state->total_param,
6845 &state->data, state->total_data,
6846 state->max_data_return);
6847 END_PROFILE(Trans2_open);
6851 case TRANSACT2_FINDFIRST:
6853 START_PROFILE(Trans2_findfirst);
6854 call_trans2findfirst(conn, req,
6855 &state->param, state->total_param,
6856 &state->data, state->total_data,
6857 state->max_data_return);
6858 END_PROFILE(Trans2_findfirst);
6862 case TRANSACT2_FINDNEXT:
6864 START_PROFILE(Trans2_findnext);
6865 call_trans2findnext(conn, req,
6866 &state->param, state->total_param,
6867 &state->data, state->total_data,
6868 state->max_data_return);
6869 END_PROFILE(Trans2_findnext);
6873 case TRANSACT2_QFSINFO:
6875 START_PROFILE(Trans2_qfsinfo);
6876 call_trans2qfsinfo(conn, req,
6877 &state->param, state->total_param,
6878 &state->data, state->total_data,
6879 state->max_data_return);
6880 END_PROFILE(Trans2_qfsinfo);
6884 case TRANSACT2_SETFSINFO:
6886 START_PROFILE(Trans2_setfsinfo);
6887 outsize = call_trans2setfsinfo(
6888 conn, inbuf, outbuf, size, bufsize,
6889 &state->param, state->total_param,
6890 &state->data, state->total_data,
6891 state->max_data_return);
6892 END_PROFILE(Trans2_setfsinfo);
6896 case TRANSACT2_QPATHINFO:
6897 case TRANSACT2_QFILEINFO:
6899 START_PROFILE(Trans2_qpathinfo);
6900 call_trans2qfilepathinfo(conn, req, state->call,
6901 &state->param, state->total_param,
6902 &state->data, state->total_data,
6903 state->max_data_return);
6904 END_PROFILE(Trans2_qpathinfo);
6908 case TRANSACT2_SETPATHINFO:
6909 case TRANSACT2_SETFILEINFO:
6911 START_PROFILE(Trans2_setpathinfo);
6912 call_trans2setfilepathinfo(conn, req, state->call,
6913 &state->param, state->total_param,
6914 &state->data, state->total_data,
6915 state->max_data_return);
6916 END_PROFILE(Trans2_setpathinfo);
6920 case TRANSACT2_FINDNOTIFYFIRST:
6922 START_PROFILE(Trans2_findnotifyfirst);
6923 call_trans2findnotifyfirst(conn, req,
6924 &state->param, state->total_param,
6925 &state->data, state->total_data,
6926 state->max_data_return);
6927 END_PROFILE(Trans2_findnotifyfirst);
6931 case TRANSACT2_FINDNOTIFYNEXT:
6933 START_PROFILE(Trans2_findnotifynext);
6934 call_trans2findnotifynext(conn, req,
6935 &state->param, state->total_param,
6936 &state->data, state->total_data,
6937 state->max_data_return);
6938 END_PROFILE(Trans2_findnotifynext);
6942 case TRANSACT2_MKDIR:
6944 START_PROFILE(Trans2_mkdir);
6945 call_trans2mkdir(conn, req,
6946 &state->param, state->total_param,
6947 &state->data, state->total_data,
6948 state->max_data_return);
6949 END_PROFILE(Trans2_mkdir);
6953 case TRANSACT2_GET_DFS_REFERRAL:
6955 START_PROFILE(Trans2_get_dfs_referral);
6956 call_trans2getdfsreferral(conn, req,
6957 &state->param, state->total_param,
6958 &state->data, state->total_data,
6959 state->max_data_return);
6960 END_PROFILE(Trans2_get_dfs_referral);
6964 case TRANSACT2_IOCTL:
6966 START_PROFILE(Trans2_ioctl);
6967 outsize = call_trans2ioctl(
6968 conn, inbuf, outbuf, size, bufsize,
6969 &state->param, state->total_param,
6970 &state->data, state->total_data,
6971 state->max_data_return);
6972 END_PROFILE(Trans2_ioctl);
6977 /* Error in request */
6978 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6979 outsize = ERROR_DOS(ERRSRV,ERRerror);
6985 /****************************************************************************
6986 Reply to a SMBtrans2.
6987 ****************************************************************************/
6989 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6990 int size, int bufsize)
6993 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6994 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6995 unsigned int psoff = SVAL(inbuf, smb_psoff);
6996 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6997 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6998 struct trans_state *state;
7001 START_PROFILE(SMBtrans2);
7003 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
7004 if (!NT_STATUS_IS_OK(result)) {
7005 DEBUG(2, ("Got invalid trans2 request: %s\n",
7006 nt_errstr(result)));
7007 END_PROFILE(SMBtrans2);
7008 return ERROR_NT(result);
7011 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7012 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7013 && (tran_call != TRANSACT2_QFILEINFO)) {
7014 END_PROFILE(SMBtrans2);
7015 return ERROR_DOS(ERRSRV,ERRaccess);
7018 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7019 DEBUG(0, ("talloc failed\n"));
7020 END_PROFILE(SMBtrans2);
7021 return ERROR_NT(NT_STATUS_NO_MEMORY);
7024 state->cmd = SMBtrans2;
7026 state->mid = SVAL(inbuf, smb_mid);
7027 state->vuid = SVAL(inbuf, smb_uid);
7028 state->setup_count = SVAL(inbuf, smb_suwcnt);
7029 state->setup = NULL;
7030 state->total_param = SVAL(inbuf, smb_tpscnt);
7031 state->param = NULL;
7032 state->total_data = SVAL(inbuf, smb_tdscnt);
7034 state->max_param_return = SVAL(inbuf, smb_mprcnt);
7035 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
7036 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
7037 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
7038 state->one_way = BITSETW(inbuf+smb_vwv5,1);
7040 state->call = tran_call;
7042 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7043 is so as a sanity check */
7044 if (state->setup_count != 1) {
7046 * Need to have rc=0 for ioctl to get job id for OS/2.
7047 * Network printing will fail if function is not successful.
7048 * Similar function in reply.c will be used if protocol
7049 * is LANMAN1.0 instead of LM1.2X002.
7050 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7051 * outbuf doesn't have to be set(only job id is used).
7053 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
7054 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
7055 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7056 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7058 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7059 DEBUG(2,("Transaction is %d\n",tran_call));
7061 END_PROFILE(SMBtrans2);
7062 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7066 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7069 if (state->total_data) {
7070 /* Can't use talloc here, the core routines do realloc on the
7071 * params and data. */
7072 state->data = (char *)SMB_MALLOC(state->total_data);
7073 if (state->data == NULL) {
7074 DEBUG(0,("reply_trans2: data malloc fail for %u "
7075 "bytes !\n", (unsigned int)state->total_data));
7077 END_PROFILE(SMBtrans2);
7078 return(ERROR_DOS(ERRDOS,ERRnomem));
7080 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7082 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
7083 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
7086 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
7089 if (state->total_param) {
7090 /* Can't use talloc here, the core routines do realloc on the
7091 * params and data. */
7092 state->param = (char *)SMB_MALLOC(state->total_param);
7093 if (state->param == NULL) {
7094 DEBUG(0,("reply_trans: param malloc fail for %u "
7095 "bytes !\n", (unsigned int)state->total_param));
7096 SAFE_FREE(state->data);
7098 END_PROFILE(SMBtrans2);
7099 return(ERROR_DOS(ERRDOS,ERRnomem));
7101 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7103 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
7104 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
7107 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
7110 state->received_data = dscnt;
7111 state->received_param = pscnt;
7113 if ((state->received_param == state->total_param) &&
7114 (state->received_data == state->total_data)) {
7116 struct smb_request *req;
7118 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
7119 END_PROFILE(SMBtrans2);
7120 return ERROR_NT(NT_STATUS_NO_MEMORY);
7123 init_smb_request(req, (uint8 *)inbuf);
7125 outsize = handle_trans2(conn, req, state, inbuf, outbuf,
7127 if (req->outbuf != NULL) {
7128 outsize = smb_len(req->outbuf) + 4;
7129 memcpy(outbuf, req->outbuf, outsize);
7132 SAFE_FREE(state->data);
7133 SAFE_FREE(state->param);
7135 END_PROFILE(SMBtrans2);
7139 DLIST_ADD(conn->pending_trans, state);
7141 /* We need to send an interim response then receive the rest
7142 of the parameter/data bytes */
7143 outsize = set_message(inbuf, outbuf,0,0,False);
7145 END_PROFILE(SMBtrans2);
7150 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7151 SAFE_FREE(state->data);
7152 SAFE_FREE(state->param);
7154 END_PROFILE(SMBtrans2);
7155 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7159 /****************************************************************************
7160 Reply to a SMBtranss2
7161 ****************************************************************************/
7163 int reply_transs2(connection_struct *conn,
7164 char *inbuf,char *outbuf,int size,int bufsize)
7167 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7168 struct trans_state *state;
7169 struct smb_request *req;
7171 START_PROFILE(SMBtranss2);
7175 for (state = conn->pending_trans; state != NULL;
7176 state = state->next) {
7177 if (state->mid == SVAL(inbuf,smb_mid)) {
7182 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7183 END_PROFILE(SMBtranss2);
7184 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7187 /* Revise state->total_param and state->total_data in case they have
7188 changed downwards */
7190 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
7191 state->total_param = SVAL(inbuf, smb_tpscnt);
7192 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
7193 state->total_data = SVAL(inbuf, smb_tdscnt);
7195 pcnt = SVAL(inbuf, smb_spscnt);
7196 poff = SVAL(inbuf, smb_spsoff);
7197 pdisp = SVAL(inbuf, smb_spsdisp);
7199 dcnt = SVAL(inbuf, smb_sdscnt);
7200 doff = SVAL(inbuf, smb_sdsoff);
7201 ddisp = SVAL(inbuf, smb_sdsdisp);
7203 state->received_param += pcnt;
7204 state->received_data += dcnt;
7206 if ((state->received_data > state->total_data) ||
7207 (state->received_param > state->total_param))
7211 if (pdisp+pcnt > state->total_param)
7213 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7215 if (pdisp > state->total_param)
7217 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
7218 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
7220 if (state->param + pdisp < state->param)
7223 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
7228 if (ddisp+dcnt > state->total_data)
7230 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7232 if (ddisp > state->total_data)
7234 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
7235 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
7237 if (state->data + ddisp < state->data)
7240 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
7244 if ((state->received_param < state->total_param) ||
7245 (state->received_data < state->total_data)) {
7246 END_PROFILE(SMBtranss2);
7250 /* construct_reply_common has done us the favor to pre-fill the
7251 * command field with SMBtranss2 which is wrong :-)
7253 SCVAL(outbuf,smb_com,SMBtrans2);
7255 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
7256 END_PROFILE(SMBtranss2);
7257 return ERROR_NT(NT_STATUS_NO_MEMORY);
7260 init_smb_request(req, (uint8 *)inbuf);
7262 outsize = handle_trans2(conn, req, state, inbuf, outbuf, size,
7264 if (req->outbuf != NULL) {
7265 outsize = smb_len(req->outbuf) + 4;
7266 memcpy(outbuf, req->outbuf, outsize);
7270 DLIST_REMOVE(conn->pending_trans, state);
7271 SAFE_FREE(state->data);
7272 SAFE_FREE(state->param);
7276 END_PROFILE(SMBtranss2);
7277 return(ERROR_DOS(ERRSRV,ERRnosupport));
7280 END_PROFILE(SMBtranss2);
7285 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7286 DLIST_REMOVE(conn->pending_trans, state);
7287 SAFE_FREE(state->data);
7288 SAFE_FREE(state->param);
7290 END_PROFILE(SMBtranss2);
7291 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);