[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob7392271b483ddf3b33a2b70c2848edf42da3d75b
1 /*
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/>.
26 #include "includes.h"
28 extern int max_send;
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,
38 char *pdata,
39 files_struct *fsp,
40 const SMB_STRUCT_STAT *psbuf);
42 static char *store_file_unix_basic_info2(connection_struct *conn,
43 char *pdata,
44 files_struct *fsp,
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);
61 return val;
64 /********************************************************************
65 Given a stat buffer return the allocated size on disk, taking into
66 account sparse files.
67 ********************************************************************/
69 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
71 SMB_BIG_UINT ret;
73 if(S_ISDIR(sbuf->st_mode)) {
74 return 0;
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;
79 #else
80 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
81 #endif
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,
102 NULL
105 int i;
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
109 return True;
111 return False;
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;
123 char *val = NULL;
124 ssize_t sizeret;
126 again:
128 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
129 if (!val) {
130 return False;
133 if (fsp && fsp->fh->fd != -1) {
134 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
135 } else {
136 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
139 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
140 attr_size = 65536;
141 goto again;
144 if (sizeret == -1) {
145 return False;
148 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
149 dump_data(10, (uint8 *)val, sizeret);
151 pea->flags = 0;
152 if (strnequal(ea_name, "user.", 5)) {
153 pea->name = &ea_name[5];
154 } else {
155 pea->name = ea_name;
157 pea->value.data = (unsigned char *)val;
158 pea->value.length = (size_t)sizeret;
159 return True;
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;
171 char *ea_namelist;
172 char *p;
173 ssize_t sizeret;
174 int i;
175 struct ea_list *ea_list_head = NULL;
177 *pea_total_len = 0;
179 if (!lp_ea_support(SNUM(conn))) {
180 return NULL;
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++) {
186 if (!ea_namelist) {
187 return NULL;
190 if (fsp && fsp->fh->fd != -1) {
191 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
192 } else {
193 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
196 if (sizeret == -1 && errno == ERANGE) {
197 ea_namelist_size *= 2;
198 } else {
199 break;
203 if (sizeret == -1)
204 return NULL;
206 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
208 if (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))
213 continue;
215 listp = TALLOC_P(mem_ctx, struct ea_list);
216 if (!listp)
217 return NULL;
219 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
220 return NULL;
224 fstring dos_ea_name;
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) {
235 *pea_total_len += 4;
239 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
240 return ea_list_head;
243 /****************************************************************************
244 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
245 that was filled.
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;
252 char *p = pdata;
254 SMB_ASSERT(total_data_size >= 4);
256 if (!lp_ea_support(SNUM(conn))) {
257 SIVAL(pdata,4,0);
258 return 4;
261 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
262 size_t dos_namelen;
263 fstring dos_ea_name;
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) {
267 break;
269 if (ea_list->ea.value.length > 65535) {
270 break;
272 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
273 break;
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))) {
299 return 0;
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);
304 return total_ea_len;
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)
313 size_t total_ea_len;
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);
322 break;
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) {
339 int ret;
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);
360 } else {
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);
365 #ifdef ENOATTR
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",
369 unix_ea_name));
370 ret = 0;
372 #endif
373 } else {
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);
379 } else {
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);
387 if (ret == -1) {
388 #ifdef ENOTSUP
389 if (errno == ENOTSUP) {
390 return NT_STATUS_EAS_NOT_SUPPORTED;
392 #endif
393 return map_nt_error_from_unix(errno);
397 return NT_STATUS_OK;
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;
406 size_t offset = 0;
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)) {
418 break;
420 /* Ensure the name is null terminated. */
421 if (pdata[offset + namelen] != '\0') {
422 return NULL;
424 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
425 if (!eal->ea.name) {
426 return NULL;
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));
434 return ea_list_head;
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);
444 uint16 val_len;
445 unsigned int namelen;
447 if (!eal) {
448 return NULL;
451 if (data_size < 6) {
452 return NULL;
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) {
460 return NULL;
463 /* Ensure the name is null terminated. */
464 if (pdata[namelen + 4] != '\0') {
465 return NULL;
467 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
468 if (!eal->ea.name) {
469 return NULL;
472 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
473 if (!eal->ea.value.data) {
474 return NULL;
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--;
484 if (pbytes_used) {
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);
491 return eal;
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;
501 size_t offset = 0;
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);
507 if (!eal) {
508 return NULL;
511 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
512 offset += bytes_used;
515 return ea_list_head;
518 /****************************************************************************
519 Count the total EA size needed.
520 ****************************************************************************/
522 static size_t ea_list_size(struct ea_list *ealist)
524 fstring dos_ea_name;
525 struct ea_list *listp;
526 size_t ret = 0;
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. */
533 if (ret) {
534 ret += 4;
537 return ret;
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)) {
553 break;
557 if (flistp) {
558 /* Copy the data from this entry. */
559 nlistp->ea.flags = flistp->ea.flags;
560 nlistp->ea.value = flistp->ea.value;
561 } else {
562 /* Null entry. */
563 nlistp->ea.flags = 0;
564 ZERO_STRUCT(nlistp->ea.value);
568 *total_ea_len = ea_list_size(name_list);
569 return 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 void send_trans2_replies(struct smb_request *req,
580 const char *params,
581 int paramsize,
582 const char *pdata,
583 int datasize,
584 int max_data_bytes)
586 /* As we are using a protocol > LANMAN1 then the max_send
587 variable must have been set in the sessetupX call.
588 This takes precedence over the max_xmit field in the
589 global struct. These different max_xmit variables should
590 be merged as this is now too confusing */
592 int data_to_send = datasize;
593 int params_to_send = paramsize;
594 int useable_space;
595 const char *pp = params;
596 const char *pd = pdata;
597 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
598 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
599 int data_alignment_offset = 0;
600 BOOL overflow = False;
602 /* Modify the data_to_send and datasize and set the error if
603 we're trying to send more than max_data_bytes. We still send
604 the part of the packet(s) that fit. Strange, but needed
605 for OS/2. */
607 if (max_data_bytes > 0 && datasize > max_data_bytes) {
608 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
609 max_data_bytes, datasize ));
610 datasize = data_to_send = max_data_bytes;
611 overflow = True;
614 /* If there genuinely are no parameters or data to send just send the empty packet */
616 if(params_to_send == 0 && data_to_send == 0) {
617 reply_outbuf(req, 10, 0);
618 show_msg((char *)req->outbuf);
619 return;
622 /* When sending params and data ensure that both are nicely aligned */
623 /* Only do this alignment when there is also data to send - else
624 can cause NT redirector problems. */
626 if (((params_to_send % 4) != 0) && (data_to_send != 0))
627 data_alignment_offset = 4 - (params_to_send % 4);
629 /* Space is bufsize minus Netbios over TCP header minus SMB header */
630 /* The alignment_offset is to align the param bytes on an even byte
631 boundary. NT 4.0 Beta needs this to work correctly. */
633 useable_space = max_send - (smb_size
634 + 2 * 10 /* wct */
635 + alignment_offset
636 + data_alignment_offset);
638 /* useable_space can never be more than max_send minus the alignment offset. */
640 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
642 while (params_to_send || data_to_send) {
643 /* Calculate whether we will totally or partially fill this packet */
645 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
647 /* We can never send more than useable_space */
649 * Note that 'useable_space' does not include the alignment offsets,
650 * but we must include the alignment offsets in the calculation of
651 * the length of the data we send over the wire, as the alignment offsets
652 * are sent here. Fix from Marc_Jacobsen@hp.com.
655 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
657 reply_outbuf(req, 10, total_sent_thistime);
659 /* Set total params and data to be sent */
660 SSVAL(req->outbuf,smb_tprcnt,paramsize);
661 SSVAL(req->outbuf,smb_tdrcnt,datasize);
663 /* Calculate how many parameters and data we can fit into
664 * this packet. Parameters get precedence
667 params_sent_thistime = MIN(params_to_send,useable_space);
668 data_sent_thistime = useable_space - params_sent_thistime;
669 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
671 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
673 /* smb_proff is the offset from the start of the SMB header to the
674 parameter bytes, however the first 4 bytes of outbuf are
675 the Netbios over TCP header. Thus use smb_base() to subtract
676 them from the calculation */
678 SSVAL(req->outbuf,smb_proff,
679 ((smb_buf(req->outbuf)+alignment_offset)
680 - smb_base(req->outbuf)));
682 if(params_sent_thistime == 0)
683 SSVAL(req->outbuf,smb_prdisp,0);
684 else
685 /* Absolute displacement of param bytes sent in this packet */
686 SSVAL(req->outbuf,smb_prdisp,pp - params);
688 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
689 if(data_sent_thistime == 0) {
690 SSVAL(req->outbuf,smb_droff,0);
691 SSVAL(req->outbuf,smb_drdisp, 0);
692 } else {
693 /* The offset of the data bytes is the offset of the
694 parameter bytes plus the number of parameters being sent this time */
695 SSVAL(req->outbuf, smb_droff,
696 ((smb_buf(req->outbuf)+alignment_offset)
697 - smb_base(req->outbuf))
698 + params_sent_thistime + data_alignment_offset);
699 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
702 /* Initialize the padding for alignment */
704 if (alignment_offset != 0) {
705 memset(smb_buf(req->outbuf), 0, alignment_offset);
708 /* Copy the param bytes into the packet */
710 if(params_sent_thistime) {
711 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
712 params_sent_thistime);
715 /* Copy in the data bytes */
716 if(data_sent_thistime) {
717 if (data_alignment_offset != 0) {
718 memset((smb_buf(req->outbuf)+alignment_offset+
719 params_sent_thistime), 0,
720 data_alignment_offset);
722 memcpy(smb_buf(req->outbuf)+alignment_offset
723 +params_sent_thistime+data_alignment_offset,
724 pd,data_sent_thistime);
727 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
728 params_sent_thistime, data_sent_thistime, useable_space));
729 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
730 params_to_send, data_to_send, paramsize, datasize));
732 if (overflow) {
733 error_packet_set((char *)req->outbuf,
734 ERRDOS,ERRbufferoverflow,
735 STATUS_BUFFER_OVERFLOW,
736 __LINE__,__FILE__);
739 /* Send the packet */
740 show_msg((char *)req->outbuf);
741 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
742 exit_server_cleanly("send_trans2_replies: send_smb failed.");
744 TALLOC_FREE(req->outbuf);
746 pp += params_sent_thistime;
747 pd += data_sent_thistime;
749 params_to_send -= params_sent_thistime;
750 data_to_send -= data_sent_thistime;
752 /* Sanity check */
753 if(params_to_send < 0 || data_to_send < 0) {
754 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
755 params_to_send, data_to_send));
756 return;
760 return;
763 /****************************************************************************
764 Reply to a TRANSACT2_OPEN.
765 ****************************************************************************/
767 static void call_trans2open(connection_struct *conn,
768 struct smb_request *req,
769 char **pparams, int total_params,
770 char **ppdata, int total_data,
771 unsigned int max_data_bytes)
773 char *params = *pparams;
774 char *pdata = *ppdata;
775 int deny_mode;
776 int32 open_attr;
777 BOOL oplock_request;
778 #if 0
779 BOOL return_additional_info;
780 int16 open_sattr;
781 time_t open_time;
782 #endif
783 int open_ofun;
784 uint32 open_size;
785 char *pname;
786 char *fname = NULL;
787 SMB_OFF_T size=0;
788 int fattr=0,mtime=0;
789 SMB_INO_T inode = 0;
790 SMB_STRUCT_STAT sbuf;
791 int smb_action = 0;
792 files_struct *fsp;
793 struct ea_list *ea_list = NULL;
794 uint16 flags = 0;
795 NTSTATUS status;
796 uint32 access_mask;
797 uint32 share_mode;
798 uint32 create_disposition;
799 uint32 create_options = 0;
800 TALLOC_CTX *ctx = talloc_tos();
803 * Ensure we have enough parameters to perform the operation.
806 if (total_params < 29) {
807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
808 return;
811 flags = SVAL(params, 0);
812 deny_mode = SVAL(params, 2);
813 open_attr = SVAL(params,6);
814 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
815 if (oplock_request) {
816 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
819 #if 0
820 return_additional_info = BITSETW(params,0);
821 open_sattr = SVAL(params, 4);
822 open_time = make_unix_date3(params+8);
823 #endif
824 open_ofun = SVAL(params,12);
825 open_size = IVAL(params,14);
826 pname = &params[28];
828 if (IS_IPC(conn)) {
829 reply_doserror(req, ERRSRV, ERRaccess);
830 return;
833 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
834 total_params - 28, STR_TERMINATE,
835 &status);
836 if (!NT_STATUS_IS_OK(status)) {
837 reply_nterror(req, status);
838 return;
841 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
842 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
843 (unsigned int)open_ofun, open_size));
845 /* XXXX we need to handle passed times, sattr and flags */
847 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
848 if (!NT_STATUS_IS_OK(status)) {
849 reply_nterror(req, status);
850 return;
853 status = check_name(conn, fname);
854 if (!NT_STATUS_IS_OK(status)) {
855 reply_nterror(req, status);
856 return;
859 if (open_ofun == 0) {
860 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
861 return;
864 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
865 &access_mask,
866 &share_mode,
867 &create_disposition,
868 &create_options)) {
869 reply_doserror(req, ERRDOS, ERRbadaccess);
870 return;
873 /* Any data in this call is an EA list. */
874 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
875 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
876 return;
879 if (total_data != 4) {
880 if (total_data < 10) {
881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
882 return;
885 if (IVAL(pdata,0) > total_data) {
886 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
887 IVAL(pdata,0), (unsigned int)total_data));
888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889 return;
892 ea_list = read_ea_list(talloc_tos(), pdata + 4,
893 total_data - 4);
894 if (!ea_list) {
895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
896 return;
898 } else if (IVAL(pdata,0) != 4) {
899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
900 return;
903 status = open_file_ntcreate(conn, req, fname, &sbuf,
904 access_mask,
905 share_mode,
906 create_disposition,
907 create_options,
908 open_attr,
909 oplock_request,
910 &smb_action, &fsp);
912 if (!NT_STATUS_IS_OK(status)) {
913 if (open_was_deferred(req->mid)) {
914 /* We have re-scheduled this call. */
915 return;
917 reply_openerror(req, status);
918 return;
921 size = get_file_size(sbuf);
922 fattr = dos_mode(conn,fname,&sbuf);
923 mtime = sbuf.st_mtime;
924 inode = sbuf.st_ino;
925 if (fattr & aDIR) {
926 close_file(fsp,ERROR_CLOSE);
927 reply_doserror(req, ERRDOS,ERRnoaccess);
928 return;
931 /* Save the requested allocation size. */
932 /* Allocate space for the file if a size hint is supplied */
933 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
934 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
935 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
936 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
937 if (fsp->is_directory) {
938 close_file(fsp,ERROR_CLOSE);
939 /* Can't set allocation size on a directory. */
940 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
941 return;
943 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
944 close_file(fsp,ERROR_CLOSE);
945 reply_nterror(req, NT_STATUS_DISK_FULL);
946 return;
949 /* Adjust size here to return the right size in the reply.
950 Windows does it this way. */
951 size = fsp->initial_allocation_size;
952 } else {
953 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
957 if (ea_list && smb_action == FILE_WAS_CREATED) {
958 status = set_ea(conn, fsp, fname, ea_list);
959 if (!NT_STATUS_IS_OK(status)) {
960 close_file(fsp,ERROR_CLOSE);
961 reply_nterror(req, status);
962 return;
966 /* Realloc the size of parameters and data we will return */
967 *pparams = (char *)SMB_REALLOC(*pparams, 30);
968 if(*pparams == NULL ) {
969 reply_nterror(req, NT_STATUS_NO_MEMORY);
970 return;
972 params = *pparams;
974 SSVAL(params,0,fsp->fnum);
975 SSVAL(params,2,fattr);
976 srv_put_dos_date2(params,4, mtime);
977 SIVAL(params,8, (uint32)size);
978 SSVAL(params,12,deny_mode);
979 SSVAL(params,14,0); /* open_type - file or directory. */
980 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
982 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
983 smb_action |= EXTENDED_OPLOCK_GRANTED;
986 SSVAL(params,18,smb_action);
989 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
991 SIVAL(params,20,inode);
992 SSVAL(params,24,0); /* Padding. */
993 if (flags & 8) {
994 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
995 SIVAL(params, 26, ea_size);
996 } else {
997 SIVAL(params, 26, 0);
1000 /* Send the required number of replies */
1001 send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1004 /*********************************************************
1005 Routine to check if a given string matches exactly.
1006 as a special case a mask of "." does NOT match. That
1007 is required for correct wildcard semantics
1008 Case can be significant or not.
1009 **********************************************************/
1011 static BOOL exact_match(connection_struct *conn,
1012 const char *str,
1013 const char *mask)
1015 if (mask[0] == '.' && mask[1] == 0)
1016 return False;
1017 if (conn->case_sensitive)
1018 return strcmp(str,mask)==0;
1019 if (StrCaseCmp(str,mask) != 0) {
1020 return False;
1022 if (dptr_has_wild(conn->dirptr)) {
1023 return False;
1025 return True;
1028 /****************************************************************************
1029 Return the filetype for UNIX extensions.
1030 ****************************************************************************/
1032 static uint32 unix_filetype(mode_t mode)
1034 if(S_ISREG(mode))
1035 return UNIX_TYPE_FILE;
1036 else if(S_ISDIR(mode))
1037 return UNIX_TYPE_DIR;
1038 #ifdef S_ISLNK
1039 else if(S_ISLNK(mode))
1040 return UNIX_TYPE_SYMLINK;
1041 #endif
1042 #ifdef S_ISCHR
1043 else if(S_ISCHR(mode))
1044 return UNIX_TYPE_CHARDEV;
1045 #endif
1046 #ifdef S_ISBLK
1047 else if(S_ISBLK(mode))
1048 return UNIX_TYPE_BLKDEV;
1049 #endif
1050 #ifdef S_ISFIFO
1051 else if(S_ISFIFO(mode))
1052 return UNIX_TYPE_FIFO;
1053 #endif
1054 #ifdef S_ISSOCK
1055 else if(S_ISSOCK(mode))
1056 return UNIX_TYPE_SOCKET;
1057 #endif
1059 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1060 return UNIX_TYPE_UNKNOWN;
1063 /****************************************************************************
1064 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1065 ****************************************************************************/
1067 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1069 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1070 SMB_STRUCT_STAT *psbuf,
1071 uint32 perms,
1072 enum perm_type ptype,
1073 mode_t *ret_perms)
1075 mode_t ret = 0;
1077 if (perms == SMB_MODE_NO_CHANGE) {
1078 if (!VALID_STAT(*psbuf)) {
1079 return NT_STATUS_INVALID_PARAMETER;
1080 } else {
1081 *ret_perms = psbuf->st_mode;
1082 return NT_STATUS_OK;
1086 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1087 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1088 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1089 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1090 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1091 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1092 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1093 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1094 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1095 #ifdef S_ISVTX
1096 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1097 #endif
1098 #ifdef S_ISGID
1099 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1100 #endif
1101 #ifdef S_ISUID
1102 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1103 #endif
1105 switch (ptype) {
1106 case PERM_NEW_FILE:
1107 /* Apply mode mask */
1108 ret &= lp_create_mask(SNUM(conn));
1109 /* Add in force bits */
1110 ret |= lp_force_create_mode(SNUM(conn));
1111 break;
1112 case PERM_NEW_DIR:
1113 ret &= lp_dir_mask(SNUM(conn));
1114 /* Add in force bits */
1115 ret |= lp_force_dir_mode(SNUM(conn));
1116 break;
1117 case PERM_EXISTING_FILE:
1118 /* Apply mode mask */
1119 ret &= lp_security_mask(SNUM(conn));
1120 /* Add in force bits */
1121 ret |= lp_force_security_mode(SNUM(conn));
1122 break;
1123 case PERM_EXISTING_DIR:
1124 /* Apply mode mask */
1125 ret &= lp_dir_security_mask(SNUM(conn));
1126 /* Add in force bits */
1127 ret |= lp_force_dir_security_mode(SNUM(conn));
1128 break;
1131 *ret_perms = ret;
1132 return NT_STATUS_OK;
1135 /****************************************************************************
1136 Get a level dependent lanman2 dir entry.
1137 ****************************************************************************/
1139 static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
1140 connection_struct *conn,
1141 uint16 flags2,
1142 const char *path_mask,
1143 uint32 dirtype,
1144 int info_level,
1145 int requires_resume_key,
1146 BOOL dont_descend,
1147 char **ppdata,
1148 char *base_data,
1149 char *end_data,
1150 int space_remaining,
1151 BOOL *out_of_space,
1152 BOOL *got_exact_match,
1153 int *last_entry_off,
1154 struct ea_list *name_list)
1156 const char *dname;
1157 BOOL found = False;
1158 SMB_STRUCT_STAT sbuf;
1159 const char *mask = NULL;
1160 char *pathreal = NULL;
1161 const char *fname = NULL;
1162 char *p, *q, *pdata = *ppdata;
1163 uint32 reskey=0;
1164 long prev_dirpos=0;
1165 uint32 mode=0;
1166 SMB_OFF_T file_size = 0;
1167 SMB_BIG_UINT allocation_size = 0;
1168 uint32 len;
1169 struct timespec mdate_ts, adate_ts, create_date_ts;
1170 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1171 char *nameptr;
1172 char *last_entry_ptr;
1173 BOOL was_8_3;
1174 uint32 nt_extmode; /* Used for NT connections instead of mode */
1175 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1176 BOOL check_mangled_names = lp_manglednames(conn->params);
1177 char mangled_name[13]; /* mangled 8.3 name. */
1179 *out_of_space = False;
1180 *got_exact_match = False;
1182 ZERO_STRUCT(mdate_ts);
1183 ZERO_STRUCT(adate_ts);
1184 ZERO_STRUCT(create_date_ts);
1186 if (!conn->dirptr) {
1187 return(False);
1190 p = strrchr_m(path_mask,'/');
1191 if(p != NULL) {
1192 if(p[1] == '\0') {
1193 mask = talloc_strdup(ctx,"*.*");
1194 } else {
1195 mask = p+1;
1197 } else {
1198 mask = path_mask;
1201 while (!found) {
1202 BOOL got_match;
1203 BOOL ms_dfs_link = False;
1205 /* Needed if we run out of space */
1206 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1207 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1210 * Due to bugs in NT client redirectors we are not using
1211 * resume keys any more - set them to zero.
1212 * Check out the related comments in findfirst/findnext.
1213 * JRA.
1216 reskey = 0;
1218 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1219 (long)conn->dirptr,curr_dirpos));
1221 if (!dname) {
1222 return(False);
1226 * fname may get mangled, dname is never mangled.
1227 * Whenever we're accessing the filesystem we use
1228 * pathreal which is composed from dname.
1231 pathreal = NULL;
1232 fname = dname;
1234 /* Mangle fname if it's an illegal name. */
1235 if (mangle_must_mangle(dname,conn->params)) {
1236 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1237 continue; /* Error - couldn't mangle. */
1239 fname = mangled_name;
1242 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1243 got_match = mask_match(fname, mask, conn->case_sensitive);
1246 if(!got_match && check_mangled_names &&
1247 !mangle_is_8_3(fname, False, conn->params)) {
1249 * It turns out that NT matches wildcards against
1250 * both long *and* short names. This may explain some
1251 * of the wildcard wierdness from old DOS clients
1252 * that some people have been seeing.... JRA.
1254 /* Force the mangling into 8.3. */
1255 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1256 continue; /* Error - couldn't mangle. */
1259 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1260 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1264 if (got_match) {
1265 BOOL isdots = (ISDOT(dname) || ISDOTDOT(dname));
1267 if (dont_descend && !isdots) {
1268 continue;
1271 if (needslash) {
1272 pathreal = NULL;
1273 pathreal = talloc_asprintf(ctx,
1274 "%s/%s",
1275 conn->dirpath,
1276 dname);
1277 } else {
1278 pathreal = talloc_asprintf(ctx,
1279 "%s%s",
1280 conn->dirpath,
1281 dname);
1284 if (!pathreal) {
1285 return False;
1288 if (INFO_LEVEL_IS_UNIX(info_level)) {
1289 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1290 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1291 pathreal,strerror(errno)));
1292 TALLOC_FREE(pathreal);
1293 continue;
1295 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1296 /* Needed to show the msdfs symlinks as
1297 * directories */
1299 if(lp_host_msdfs() &&
1300 lp_msdfs_root(SNUM(conn)) &&
1301 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1302 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1303 "as a directory\n",
1304 pathreal));
1305 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1307 } else {
1309 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1310 pathreal,strerror(errno)));
1311 TALLOC_FREE(pathreal);
1312 continue;
1316 if (ms_dfs_link) {
1317 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1318 } else {
1319 mode = dos_mode(conn,pathreal,&sbuf);
1322 if (!dir_check_ftype(conn,mode,dirtype)) {
1323 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1324 TALLOC_FREE(pathreal);
1325 continue;
1328 if (!(mode & aDIR)) {
1329 file_size = get_file_size(sbuf);
1331 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1333 mdate_ts = get_mtimespec(&sbuf);
1334 adate_ts = get_atimespec(&sbuf);
1335 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1337 if (lp_dos_filetime_resolution(SNUM(conn))) {
1338 dos_filetime_timespec(&create_date_ts);
1339 dos_filetime_timespec(&mdate_ts);
1340 dos_filetime_timespec(&adate_ts);
1343 create_date = convert_timespec_to_time_t(create_date_ts);
1344 mdate = convert_timespec_to_time_t(mdate_ts);
1345 adate = convert_timespec_to_time_t(adate_ts);
1347 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1349 found = True;
1351 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1355 p = pdata;
1356 last_entry_ptr = p;
1358 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1360 switch (info_level) {
1361 case SMB_FIND_INFO_STANDARD:
1362 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1363 if(requires_resume_key) {
1364 SIVAL(p,0,reskey);
1365 p += 4;
1367 srv_put_dos_date2(p,0,create_date);
1368 srv_put_dos_date2(p,4,adate);
1369 srv_put_dos_date2(p,8,mdate);
1370 SIVAL(p,12,(uint32)file_size);
1371 SIVAL(p,16,(uint32)allocation_size);
1372 SSVAL(p,20,mode);
1373 p += 23;
1374 nameptr = p;
1375 p += align_string(pdata, p, 0);
1376 len = srvstr_push(base_data, flags2, p,
1377 fname, PTR_DIFF(end_data, p),
1378 STR_TERMINATE);
1379 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1380 if (len > 2) {
1381 SCVAL(nameptr, -1, len - 2);
1382 } else {
1383 SCVAL(nameptr, -1, 0);
1385 } else {
1386 if (len > 1) {
1387 SCVAL(nameptr, -1, len - 1);
1388 } else {
1389 SCVAL(nameptr, -1, 0);
1392 p += len;
1393 break;
1395 case SMB_FIND_EA_SIZE:
1396 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1397 if(requires_resume_key) {
1398 SIVAL(p,0,reskey);
1399 p += 4;
1401 srv_put_dos_date2(p,0,create_date);
1402 srv_put_dos_date2(p,4,adate);
1403 srv_put_dos_date2(p,8,mdate);
1404 SIVAL(p,12,(uint32)file_size);
1405 SIVAL(p,16,(uint32)allocation_size);
1406 SSVAL(p,20,mode);
1408 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1409 SIVAL(p,22,ea_size); /* Extended attributes */
1411 p += 27;
1412 nameptr = p - 1;
1413 len = srvstr_push(base_data, flags2,
1414 p, fname, PTR_DIFF(end_data, p),
1415 STR_TERMINATE | STR_NOALIGN);
1416 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1417 if (len > 2) {
1418 len -= 2;
1419 } else {
1420 len = 0;
1422 } else {
1423 if (len > 1) {
1424 len -= 1;
1425 } else {
1426 len = 0;
1429 SCVAL(nameptr,0,len);
1430 p += len;
1431 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1432 break;
1434 case SMB_FIND_EA_LIST:
1436 struct ea_list *file_list = NULL;
1437 size_t ea_len = 0;
1439 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1440 if (!name_list) {
1441 return False;
1443 if(requires_resume_key) {
1444 SIVAL(p,0,reskey);
1445 p += 4;
1447 srv_put_dos_date2(p,0,create_date);
1448 srv_put_dos_date2(p,4,adate);
1449 srv_put_dos_date2(p,8,mdate);
1450 SIVAL(p,12,(uint32)file_size);
1451 SIVAL(p,16,(uint32)allocation_size);
1452 SSVAL(p,20,mode);
1453 p += 22; /* p now points to the EA area. */
1455 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1456 name_list = ea_list_union(name_list, file_list, &ea_len);
1458 /* We need to determine if this entry will fit in the space available. */
1459 /* Max string size is 255 bytes. */
1460 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1461 /* Move the dirptr back to prev_dirpos */
1462 dptr_SeekDir(conn->dirptr, prev_dirpos);
1463 *out_of_space = True;
1464 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1465 return False; /* Not finished - just out of space */
1468 /* Push the ea_data followed by the name. */
1469 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1470 nameptr = p;
1471 len = srvstr_push(base_data, flags2,
1472 p + 1, fname, PTR_DIFF(end_data, p),
1473 STR_TERMINATE | STR_NOALIGN);
1474 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1475 if (len > 2) {
1476 len -= 2;
1477 } else {
1478 len = 0;
1480 } else {
1481 if (len > 1) {
1482 len -= 1;
1483 } else {
1484 len = 0;
1487 SCVAL(nameptr,0,len);
1488 p += len + 1;
1489 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1490 break;
1493 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1495 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1496 p += 4;
1497 SIVAL(p,0,reskey); p += 4;
1498 put_long_date_timespec(p,create_date_ts); p += 8;
1499 put_long_date_timespec(p,adate_ts); p += 8;
1500 put_long_date_timespec(p,mdate_ts); p += 8;
1501 put_long_date_timespec(p,mdate_ts); p += 8;
1502 SOFF_T(p,0,file_size); p += 8;
1503 SOFF_T(p,0,allocation_size); p += 8;
1504 SIVAL(p,0,nt_extmode); p += 4;
1505 q = p; p += 4; /* q is placeholder for name length. */
1507 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1508 SIVAL(p,0,ea_size); /* Extended attributes */
1509 p += 4;
1511 /* Clear the short name buffer. This is
1512 * IMPORTANT as not doing so will trigger
1513 * a Win2k client bug. JRA.
1515 if (!was_8_3 && check_mangled_names) {
1516 if (!name_to_8_3(fname,mangled_name,True,
1517 conn->params)) {
1518 /* Error - mangle failed ! */
1519 memset(mangled_name,'\0',12);
1521 mangled_name[12] = 0;
1522 len = srvstr_push(base_data, flags2,
1523 p+2, mangled_name, 24,
1524 STR_UPPER|STR_UNICODE);
1525 if (len < 24) {
1526 memset(p + 2 + len,'\0',24 - len);
1528 SSVAL(p, 0, len);
1529 } else {
1530 memset(p,'\0',26);
1532 p += 2 + 24;
1533 len = srvstr_push(base_data, flags2, p,
1534 fname, PTR_DIFF(end_data, p),
1535 STR_TERMINATE_ASCII);
1536 SIVAL(q,0,len);
1537 p += len;
1538 SIVAL(p,0,0); /* Ensure any padding is null. */
1539 len = PTR_DIFF(p, pdata);
1540 len = (len + 3) & ~3;
1541 SIVAL(pdata,0,len);
1542 p = pdata + len;
1543 break;
1545 case SMB_FIND_FILE_DIRECTORY_INFO:
1546 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1547 p += 4;
1548 SIVAL(p,0,reskey); p += 4;
1549 put_long_date_timespec(p,create_date_ts); p += 8;
1550 put_long_date_timespec(p,adate_ts); p += 8;
1551 put_long_date_timespec(p,mdate_ts); p += 8;
1552 put_long_date_timespec(p,mdate_ts); p += 8;
1553 SOFF_T(p,0,file_size); p += 8;
1554 SOFF_T(p,0,allocation_size); p += 8;
1555 SIVAL(p,0,nt_extmode); p += 4;
1556 len = srvstr_push(base_data, flags2,
1557 p + 4, fname, PTR_DIFF(end_data, p),
1558 STR_TERMINATE_ASCII);
1559 SIVAL(p,0,len);
1560 p += 4 + len;
1561 SIVAL(p,0,0); /* Ensure any padding is null. */
1562 len = PTR_DIFF(p, pdata);
1563 len = (len + 3) & ~3;
1564 SIVAL(pdata,0,len);
1565 p = pdata + len;
1566 break;
1568 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1569 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1570 p += 4;
1571 SIVAL(p,0,reskey); p += 4;
1572 put_long_date_timespec(p,create_date_ts); p += 8;
1573 put_long_date_timespec(p,adate_ts); p += 8;
1574 put_long_date_timespec(p,mdate_ts); p += 8;
1575 put_long_date_timespec(p,mdate_ts); p += 8;
1576 SOFF_T(p,0,file_size); p += 8;
1577 SOFF_T(p,0,allocation_size); p += 8;
1578 SIVAL(p,0,nt_extmode); p += 4;
1579 q = p; p += 4; /* q is placeholder for name length. */
1581 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1582 SIVAL(p,0,ea_size); /* Extended attributes */
1583 p +=4;
1585 len = srvstr_push(base_data, flags2, p,
1586 fname, PTR_DIFF(end_data, p),
1587 STR_TERMINATE_ASCII);
1588 SIVAL(q, 0, len);
1589 p += len;
1591 SIVAL(p,0,0); /* Ensure any padding is null. */
1592 len = PTR_DIFF(p, pdata);
1593 len = (len + 3) & ~3;
1594 SIVAL(pdata,0,len);
1595 p = pdata + len;
1596 break;
1598 case SMB_FIND_FILE_NAMES_INFO:
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1600 p += 4;
1601 SIVAL(p,0,reskey); p += 4;
1602 p += 4;
1603 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1604 acl on a dir (tridge) */
1605 len = srvstr_push(base_data, flags2, p,
1606 fname, PTR_DIFF(end_data, p),
1607 STR_TERMINATE_ASCII);
1608 SIVAL(p, -4, len);
1609 p += len;
1610 SIVAL(p,0,0); /* Ensure any padding is null. */
1611 len = PTR_DIFF(p, pdata);
1612 len = (len + 3) & ~3;
1613 SIVAL(pdata,0,len);
1614 p = pdata + len;
1615 break;
1617 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1618 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1619 p += 4;
1620 SIVAL(p,0,reskey); p += 4;
1621 put_long_date_timespec(p,create_date_ts); p += 8;
1622 put_long_date_timespec(p,adate_ts); p += 8;
1623 put_long_date_timespec(p,mdate_ts); p += 8;
1624 put_long_date_timespec(p,mdate_ts); p += 8;
1625 SOFF_T(p,0,file_size); p += 8;
1626 SOFF_T(p,0,allocation_size); p += 8;
1627 SIVAL(p,0,nt_extmode); p += 4;
1628 q = p; p += 4; /* q is placeholder for name length. */
1630 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1631 SIVAL(p,0,ea_size); /* Extended attributes */
1632 p +=4;
1634 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1635 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1636 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1637 len = srvstr_push(base_data, flags2, p,
1638 fname, PTR_DIFF(end_data, p),
1639 STR_TERMINATE_ASCII);
1640 SIVAL(q, 0, len);
1641 p += len;
1642 SIVAL(p,0,0); /* Ensure any padding is null. */
1643 len = PTR_DIFF(p, pdata);
1644 len = (len + 3) & ~3;
1645 SIVAL(pdata,0,len);
1646 p = pdata + len;
1647 break;
1649 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1650 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1651 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1652 p += 4;
1653 SIVAL(p,0,reskey); p += 4;
1654 put_long_date_timespec(p,create_date_ts); p += 8;
1655 put_long_date_timespec(p,adate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 SOFF_T(p,0,file_size); p += 8;
1659 SOFF_T(p,0,allocation_size); p += 8;
1660 SIVAL(p,0,nt_extmode); p += 4;
1661 q = p; p += 4; /* q is placeholder for name length */
1663 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1664 SIVAL(p,0,ea_size); /* Extended attributes */
1665 p +=4;
1667 /* Clear the short name buffer. This is
1668 * IMPORTANT as not doing so will trigger
1669 * a Win2k client bug. JRA.
1671 if (!was_8_3 && check_mangled_names) {
1672 if (!name_to_8_3(fname,mangled_name,True,
1673 conn->params)) {
1674 /* Error - mangle failed ! */
1675 memset(mangled_name,'\0',12);
1677 mangled_name[12] = 0;
1678 len = srvstr_push(base_data, flags2,
1679 p+2, mangled_name, 24,
1680 STR_UPPER|STR_UNICODE);
1681 SSVAL(p, 0, len);
1682 if (len < 24) {
1683 memset(p + 2 + len,'\0',24 - len);
1685 SSVAL(p, 0, len);
1686 } else {
1687 memset(p,'\0',26);
1689 p += 26;
1690 SSVAL(p,0,0); p += 2; /* Reserved ? */
1691 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1692 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1693 len = srvstr_push(base_data, flags2, p,
1694 fname, PTR_DIFF(end_data, p),
1695 STR_TERMINATE_ASCII);
1696 SIVAL(q,0,len);
1697 p += len;
1698 SIVAL(p,0,0); /* Ensure any padding is null. */
1699 len = PTR_DIFF(p, pdata);
1700 len = (len + 3) & ~3;
1701 SIVAL(pdata,0,len);
1702 p = pdata + len;
1703 break;
1705 /* CIFS UNIX Extension. */
1707 case SMB_FIND_FILE_UNIX:
1708 case SMB_FIND_FILE_UNIX_INFO2:
1709 p+= 4;
1710 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1712 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1714 if (info_level == SMB_FIND_FILE_UNIX) {
1715 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1716 p = store_file_unix_basic(conn, p,
1717 NULL, &sbuf);
1718 len = srvstr_push(base_data, flags2, p,
1719 fname, PTR_DIFF(end_data, p),
1720 STR_TERMINATE);
1721 } else {
1722 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1723 p = store_file_unix_basic_info2(conn, p,
1724 NULL, &sbuf);
1725 nameptr = p;
1726 p += 4;
1727 len = srvstr_push(base_data, flags2, p, fname,
1728 PTR_DIFF(end_data, p), 0);
1729 SIVAL(nameptr, 0, len);
1732 p += len;
1733 SIVAL(p,0,0); /* Ensure any padding is null. */
1735 len = PTR_DIFF(p, pdata);
1736 len = (len + 3) & ~3;
1737 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1738 p = pdata + len;
1739 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1741 break;
1743 default:
1744 return(False);
1748 if (PTR_DIFF(p,pdata) > space_remaining) {
1749 /* Move the dirptr back to prev_dirpos */
1750 dptr_SeekDir(conn->dirptr, prev_dirpos);
1751 *out_of_space = True;
1752 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1753 return False; /* Not finished - just out of space */
1756 /* Setup the last entry pointer, as an offset from base_data */
1757 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1758 /* Advance the data pointer to the next slot */
1759 *ppdata = p;
1761 return(found);
1764 /****************************************************************************
1765 Reply to a TRANS2_FINDFIRST.
1766 ****************************************************************************/
1768 static void call_trans2findfirst(connection_struct *conn,
1769 struct smb_request *req,
1770 char **pparams, int total_params,
1771 char **ppdata, int total_data,
1772 unsigned int max_data_bytes)
1774 /* We must be careful here that we don't return more than the
1775 allowed number of data bytes. If this means returning fewer than
1776 maxentries then so be it. We assume that the redirector has
1777 enough room for the fixed number of parameter bytes it has
1778 requested. */
1779 char *params = *pparams;
1780 char *pdata = *ppdata;
1781 char *data_end;
1782 uint32 dirtype;
1783 int maxentries;
1784 uint16 findfirst_flags;
1785 BOOL close_after_first;
1786 BOOL close_if_end;
1787 BOOL requires_resume_key;
1788 int info_level;
1789 char *directory = NULL;
1790 const char *mask = NULL;
1791 char *p;
1792 int last_entry_off=0;
1793 int dptr_num = -1;
1794 int numentries = 0;
1795 int i;
1796 BOOL finished = False;
1797 BOOL dont_descend = False;
1798 BOOL out_of_space = False;
1799 int space_remaining;
1800 BOOL mask_contains_wcard = False;
1801 SMB_STRUCT_STAT sbuf;
1802 struct ea_list *ea_list = NULL;
1803 NTSTATUS ntstatus = NT_STATUS_OK;
1804 TALLOC_CTX *ctx = talloc_tos();
1806 if (total_params < 13) {
1807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1808 return;
1811 dirtype = SVAL(params,0);
1812 maxentries = SVAL(params,2);
1813 findfirst_flags = SVAL(params,4);
1814 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1815 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1816 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1817 info_level = SVAL(params,6);
1819 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1820 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1821 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1822 info_level, max_data_bytes));
1824 if (!maxentries) {
1825 /* W2K3 seems to treat zero as 1. */
1826 maxentries = 1;
1829 switch (info_level) {
1830 case SMB_FIND_INFO_STANDARD:
1831 case SMB_FIND_EA_SIZE:
1832 case SMB_FIND_EA_LIST:
1833 case SMB_FIND_FILE_DIRECTORY_INFO:
1834 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1835 case SMB_FIND_FILE_NAMES_INFO:
1836 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1837 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1838 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1839 break;
1840 case SMB_FIND_FILE_UNIX:
1841 case SMB_FIND_FILE_UNIX_INFO2:
1842 if (!lp_unix_extensions()) {
1843 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1844 return;
1846 break;
1847 default:
1848 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1849 return;
1852 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1853 params+12, total_params - 12,
1854 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1855 if (!NT_STATUS_IS_OK(ntstatus)) {
1856 reply_nterror(req, ntstatus);
1857 return;
1860 ntstatus = resolve_dfspath_wcard(ctx, conn,
1861 req->flags2 & FLAGS2_DFS_PATHNAMES,
1862 directory,
1863 &directory,
1864 &mask_contains_wcard);
1865 if (!NT_STATUS_IS_OK(ntstatus)) {
1866 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1867 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1868 ERRSRV, ERRbadpath);
1869 return;
1871 reply_nterror(req, ntstatus);
1872 return;
1875 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1876 if (!NT_STATUS_IS_OK(ntstatus)) {
1877 reply_nterror(req, ntstatus);
1878 return;
1881 ntstatus = check_name(conn, directory);
1882 if (!NT_STATUS_IS_OK(ntstatus)) {
1883 reply_nterror(req, ntstatus);
1884 return;
1887 p = strrchr_m(directory,'/');
1888 if(p == NULL) {
1889 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1890 if((directory[0] == '.') && (directory[1] == '\0')) {
1891 mask = "*";
1892 mask_contains_wcard = True;
1893 } else {
1894 mask = directory;
1896 directory = talloc_strdup(talloc_tos(), "./");
1897 if (!directory) {
1898 reply_nterror(req, NT_STATUS_NO_MEMORY);
1899 return;
1901 } else {
1902 mask = p+1;
1903 *p = 0;
1906 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1908 if (info_level == SMB_FIND_EA_LIST) {
1909 uint32 ea_size;
1911 if (total_data < 4) {
1912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1913 return;
1916 ea_size = IVAL(pdata,0);
1917 if (ea_size != total_data) {
1918 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1919 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1921 return;
1924 if (!lp_ea_support(SNUM(conn))) {
1925 reply_doserror(req, ERRDOS, ERReasnotsupported);
1926 return;
1929 /* Pull out the list of names. */
1930 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1931 if (!ea_list) {
1932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1933 return;
1937 *ppdata = (char *)SMB_REALLOC(
1938 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1939 if(*ppdata == NULL ) {
1940 reply_nterror(req, NT_STATUS_NO_MEMORY);
1941 return;
1943 pdata = *ppdata;
1944 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1946 /* Realloc the params space */
1947 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1948 if (*pparams == NULL) {
1949 reply_nterror(req, NT_STATUS_NO_MEMORY);
1950 return;
1952 params = *pparams;
1954 /* Save the wildcard match and attribs we are using on this directory -
1955 needed as lanman2 assumes these are being saved between calls */
1957 ntstatus = dptr_create(conn,
1958 directory,
1959 False,
1960 True,
1961 req->smbpid,
1962 mask,
1963 mask_contains_wcard,
1964 dirtype,
1965 &conn->dirptr);
1967 if (!NT_STATUS_IS_OK(ntstatus)) {
1968 reply_nterror(req, ntstatus);
1969 return;
1972 dptr_num = dptr_dnum(conn->dirptr);
1973 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1975 /* We don't need to check for VOL here as this is returned by
1976 a different TRANS2 call. */
1978 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1979 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1980 dont_descend = True;
1982 p = pdata;
1983 space_remaining = max_data_bytes;
1984 out_of_space = False;
1986 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1987 BOOL got_exact_match = False;
1989 /* this is a heuristic to avoid seeking the dirptr except when
1990 absolutely necessary. It allows for a filename of about 40 chars */
1991 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1992 out_of_space = True;
1993 finished = False;
1994 } else {
1995 TALLOC_CTX *sub_ctx = talloc_stackframe();
1997 finished = !get_lanman2_dir_entry(sub_ctx,
1998 conn,
1999 req->flags2,
2000 mask,dirtype,info_level,
2001 requires_resume_key,dont_descend,
2002 &p,pdata,data_end,
2003 space_remaining, &out_of_space,
2004 &got_exact_match,
2005 &last_entry_off, ea_list);
2007 TALLOC_FREE(sub_ctx);
2010 if (finished && out_of_space)
2011 finished = False;
2013 if (!finished && !out_of_space)
2014 numentries++;
2017 * As an optimisation if we know we aren't looking
2018 * for a wildcard name (ie. the name matches the wildcard exactly)
2019 * then we can finish on any (first) match.
2020 * This speeds up large directory searches. JRA.
2023 if(got_exact_match)
2024 finished = True;
2026 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2029 /* Check if we can close the dirptr */
2030 if(close_after_first || (finished && close_if_end)) {
2031 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2032 dptr_close(&dptr_num);
2036 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2037 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2038 * the protocol level is less than NT1. Tested with smbclient. JRA.
2039 * This should fix the OS/2 client bug #2335.
2042 if(numentries == 0) {
2043 dptr_close(&dptr_num);
2044 if (Protocol < PROTOCOL_NT1) {
2045 reply_doserror(req, ERRDOS, ERRnofiles);
2046 return;
2047 } else {
2048 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2049 ERRDOS, ERRbadfile);
2050 return;
2054 /* At this point pdata points to numentries directory entries. */
2056 /* Set up the return parameter block */
2057 SSVAL(params,0,dptr_num);
2058 SSVAL(params,2,numentries);
2059 SSVAL(params,4,finished);
2060 SSVAL(params,6,0); /* Never an EA error */
2061 SSVAL(params,8,last_entry_off);
2063 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2064 max_data_bytes);
2066 if ((! *directory) && dptr_path(dptr_num)) {
2067 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2068 if (!directory) {
2069 reply_nterror(req, NT_STATUS_NO_MEMORY);
2073 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2074 smb_fn_name(CVAL(req->inbuf,smb_com)),
2075 mask, directory, dirtype, numentries ) );
2078 * Force a name mangle here to ensure that the
2079 * mask as an 8.3 name is top of the mangled cache.
2080 * The reasons for this are subtle. Don't remove
2081 * this code unless you know what you are doing
2082 * (see PR#13758). JRA.
2085 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2086 char mangled_name[13];
2087 name_to_8_3(mask, mangled_name, True, conn->params);
2090 return;
2093 /****************************************************************************
2094 Reply to a TRANS2_FINDNEXT.
2095 ****************************************************************************/
2097 static void call_trans2findnext(connection_struct *conn,
2098 struct smb_request *req,
2099 char **pparams, int total_params,
2100 char **ppdata, int total_data,
2101 unsigned int max_data_bytes)
2103 /* We must be careful here that we don't return more than the
2104 allowed number of data bytes. If this means returning fewer than
2105 maxentries then so be it. We assume that the redirector has
2106 enough room for the fixed number of parameter bytes it has
2107 requested. */
2108 char *params = *pparams;
2109 char *pdata = *ppdata;
2110 char *data_end;
2111 int dptr_num;
2112 int maxentries;
2113 uint16 info_level;
2114 uint32 resume_key;
2115 uint16 findnext_flags;
2116 BOOL close_after_request;
2117 BOOL close_if_end;
2118 BOOL requires_resume_key;
2119 BOOL continue_bit;
2120 BOOL mask_contains_wcard = False;
2121 char *resume_name = NULL;
2122 const char *mask = NULL;
2123 const char *directory = NULL;
2124 char *p = NULL;
2125 uint16 dirtype;
2126 int numentries = 0;
2127 int i, last_entry_off=0;
2128 BOOL finished = False;
2129 BOOL dont_descend = False;
2130 BOOL out_of_space = False;
2131 int space_remaining;
2132 struct ea_list *ea_list = NULL;
2133 NTSTATUS ntstatus = NT_STATUS_OK;
2134 TALLOC_CTX *ctx = talloc_tos();
2136 if (total_params < 13) {
2137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2138 return;
2141 dptr_num = SVAL(params,0);
2142 maxentries = SVAL(params,2);
2143 info_level = SVAL(params,4);
2144 resume_key = IVAL(params,6);
2145 findnext_flags = SVAL(params,10);
2146 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2147 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2148 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2149 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2151 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2152 params+12,
2153 total_params - 12, STR_TERMINATE, &ntstatus,
2154 &mask_contains_wcard);
2155 if (!NT_STATUS_IS_OK(ntstatus)) {
2156 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2157 complain (it thinks we're asking for the directory above the shared
2158 path or an invalid name). Catch this as the resume name is only compared, never used in
2159 a file access. JRA. */
2160 srvstr_pull_talloc(ctx, params, req->flags2,
2161 &resume_name, params+12,
2162 total_params - 12,
2163 STR_TERMINATE);
2165 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2166 reply_nterror(req, ntstatus);
2167 return;
2171 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2172 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2173 resume_key = %d resume name = %s continue=%d level = %d\n",
2174 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2175 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2177 if (!maxentries) {
2178 /* W2K3 seems to treat zero as 1. */
2179 maxentries = 1;
2182 switch (info_level) {
2183 case SMB_FIND_INFO_STANDARD:
2184 case SMB_FIND_EA_SIZE:
2185 case SMB_FIND_EA_LIST:
2186 case SMB_FIND_FILE_DIRECTORY_INFO:
2187 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2188 case SMB_FIND_FILE_NAMES_INFO:
2189 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2190 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2191 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2192 break;
2193 case SMB_FIND_FILE_UNIX:
2194 case SMB_FIND_FILE_UNIX_INFO2:
2195 if (!lp_unix_extensions()) {
2196 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2197 return;
2199 break;
2200 default:
2201 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2202 return;
2205 if (info_level == SMB_FIND_EA_LIST) {
2206 uint32 ea_size;
2208 if (total_data < 4) {
2209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2210 return;
2213 ea_size = IVAL(pdata,0);
2214 if (ea_size != total_data) {
2215 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2216 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2218 return;
2221 if (!lp_ea_support(SNUM(conn))) {
2222 reply_doserror(req, ERRDOS, ERReasnotsupported);
2223 return;
2226 /* Pull out the list of names. */
2227 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2228 if (!ea_list) {
2229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2230 return;
2234 *ppdata = (char *)SMB_REALLOC(
2235 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2236 if(*ppdata == NULL) {
2237 reply_nterror(req, NT_STATUS_NO_MEMORY);
2238 return;
2241 pdata = *ppdata;
2242 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2244 /* Realloc the params space */
2245 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2246 if(*pparams == NULL ) {
2247 reply_nterror(req, NT_STATUS_NO_MEMORY);
2248 return;
2251 params = *pparams;
2253 /* Check that the dptr is valid */
2254 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2255 reply_doserror(req, ERRDOS, ERRnofiles);
2256 return;
2259 string_set(&conn->dirpath,dptr_path(dptr_num));
2261 /* Get the wildcard mask from the dptr */
2262 if((p = dptr_wcard(dptr_num))== NULL) {
2263 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2264 reply_doserror(req, ERRDOS, ERRnofiles);
2265 return;
2268 mask = p;
2269 directory = conn->dirpath;
2271 /* Get the attr mask from the dptr */
2272 dirtype = dptr_attr(dptr_num);
2274 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2275 dptr_num, mask, dirtype,
2276 (long)conn->dirptr,
2277 dptr_TellDir(conn->dirptr)));
2279 /* We don't need to check for VOL here as this is returned by
2280 a different TRANS2 call. */
2282 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2283 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2284 dont_descend = True;
2286 p = pdata;
2287 space_remaining = max_data_bytes;
2288 out_of_space = False;
2291 * Seek to the correct position. We no longer use the resume key but
2292 * depend on the last file name instead.
2295 if(*resume_name && !continue_bit) {
2296 SMB_STRUCT_STAT st;
2298 long current_pos = 0;
2300 * Remember, name_to_8_3 is called by
2301 * get_lanman2_dir_entry(), so the resume name
2302 * could be mangled. Ensure we check the unmangled name.
2305 if (mangle_is_mangled(resume_name, conn->params)) {
2306 char *new_resume_name = NULL;
2307 mangle_lookup_name_from_8_3(ctx,
2308 resume_name,
2309 &new_resume_name,
2310 conn->params);
2311 if (new_resume_name) {
2312 resume_name = new_resume_name;
2317 * Fix for NT redirector problem triggered by resume key indexes
2318 * changing between directory scans. We now return a resume key of 0
2319 * and instead look for the filename to continue from (also given
2320 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2321 * findfirst/findnext (as is usual) then the directory pointer
2322 * should already be at the correct place.
2325 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2326 } /* end if resume_name && !continue_bit */
2328 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2329 BOOL got_exact_match = False;
2331 /* this is a heuristic to avoid seeking the dirptr except when
2332 absolutely necessary. It allows for a filename of about 40 chars */
2333 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2334 out_of_space = True;
2335 finished = False;
2336 } else {
2337 TALLOC_CTX *sub_ctx = talloc_stackframe();
2339 finished = !get_lanman2_dir_entry(sub_ctx,
2340 conn,
2341 req->flags2,
2342 mask,dirtype,info_level,
2343 requires_resume_key,dont_descend,
2344 &p,pdata,data_end,
2345 space_remaining, &out_of_space,
2346 &got_exact_match,
2347 &last_entry_off, ea_list);
2349 TALLOC_FREE(sub_ctx);
2352 if (finished && out_of_space)
2353 finished = False;
2355 if (!finished && !out_of_space)
2356 numentries++;
2359 * As an optimisation if we know we aren't looking
2360 * for a wildcard name (ie. the name matches the wildcard exactly)
2361 * then we can finish on any (first) match.
2362 * This speeds up large directory searches. JRA.
2365 if(got_exact_match)
2366 finished = True;
2368 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2371 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2372 smb_fn_name(CVAL(req->inbuf,smb_com)),
2373 mask, directory, dirtype, numentries ) );
2375 /* Check if we can close the dirptr */
2376 if(close_after_request || (finished && close_if_end)) {
2377 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2378 dptr_close(&dptr_num); /* This frees up the saved mask */
2381 /* Set up the return parameter block */
2382 SSVAL(params,0,numentries);
2383 SSVAL(params,2,finished);
2384 SSVAL(params,4,0); /* Never an EA error */
2385 SSVAL(params,6,last_entry_off);
2387 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2388 max_data_bytes);
2390 return;
2393 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2395 E_md4hash(lp_servicename(SNUM(conn)),objid);
2396 return objid;
2399 /****************************************************************************
2400 Reply to a TRANS2_QFSINFO (query filesystem info).
2401 ****************************************************************************/
2403 static void call_trans2qfsinfo(connection_struct *conn,
2404 struct smb_request *req,
2405 char **pparams, int total_params,
2406 char **ppdata, int total_data,
2407 unsigned int max_data_bytes)
2409 char *pdata, *end_data;
2410 char *params = *pparams;
2411 uint16 info_level;
2412 int data_len, len;
2413 SMB_STRUCT_STAT st;
2414 const char *vname = volume_label(SNUM(conn));
2415 int snum = SNUM(conn);
2416 char *fstype = lp_fstype(SNUM(conn));
2417 int quota_flag = 0;
2419 if (total_params < 2) {
2420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2421 return;
2424 info_level = SVAL(params,0);
2426 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2428 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2429 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2430 reply_doserror(req, ERRSRV, ERRinvdevice);
2431 return;
2434 *ppdata = (char *)SMB_REALLOC(
2435 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2436 if (*ppdata == NULL ) {
2437 reply_nterror(req, NT_STATUS_NO_MEMORY);
2438 return;
2441 pdata = *ppdata;
2442 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2443 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2445 switch (info_level) {
2446 case SMB_INFO_ALLOCATION:
2448 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2449 data_len = 18;
2450 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2451 reply_unixerror(req, ERRHRD, ERRgeneral);
2452 return;
2455 block_size = lp_block_size(snum);
2456 if (bsize < block_size) {
2457 SMB_BIG_UINT factor = block_size/bsize;
2458 bsize = block_size;
2459 dsize /= factor;
2460 dfree /= factor;
2462 if (bsize > block_size) {
2463 SMB_BIG_UINT factor = bsize/block_size;
2464 bsize = block_size;
2465 dsize *= factor;
2466 dfree *= factor;
2468 bytes_per_sector = 512;
2469 sectors_per_unit = bsize/bytes_per_sector;
2471 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2472 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2473 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2475 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2476 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2477 SIVAL(pdata,l1_cUnit,dsize);
2478 SIVAL(pdata,l1_cUnitAvail,dfree);
2479 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2480 break;
2483 case SMB_INFO_VOLUME:
2484 /* Return volume name */
2486 * Add volume serial number - hash of a combination of
2487 * the called hostname and the service name.
2489 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2491 * Win2k3 and previous mess this up by sending a name length
2492 * one byte short. I believe only older clients (OS/2 Win9x) use
2493 * this call so try fixing this by adding a terminating null to
2494 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2496 len = srvstr_push(
2497 pdata, req->flags2,
2498 pdata+l2_vol_szVolLabel, vname,
2499 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2500 STR_NOALIGN|STR_TERMINATE);
2501 SCVAL(pdata,l2_vol_cch,len);
2502 data_len = l2_vol_szVolLabel + len;
2503 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2504 (unsigned)st.st_ctime, len, vname));
2505 break;
2507 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2508 case SMB_FS_ATTRIBUTE_INFORMATION:
2511 #if defined(HAVE_SYS_QUOTAS)
2512 quota_flag = FILE_VOLUME_QUOTAS;
2513 #endif
2515 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2516 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2517 FILE_SUPPORTS_OBJECT_IDS|
2518 FILE_UNICODE_ON_DISK|
2519 quota_flag); /* FS ATTRIBUTES */
2521 SIVAL(pdata,4,255); /* Max filename component length */
2522 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2523 and will think we can't do long filenames */
2524 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2525 PTR_DIFF(end_data, pdata+12),
2526 STR_UNICODE);
2527 SIVAL(pdata,8,len);
2528 data_len = 12 + len;
2529 break;
2531 case SMB_QUERY_FS_LABEL_INFO:
2532 case SMB_FS_LABEL_INFORMATION:
2533 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2534 PTR_DIFF(end_data, pdata+4), 0);
2535 data_len = 4 + len;
2536 SIVAL(pdata,0,len);
2537 break;
2539 case SMB_QUERY_FS_VOLUME_INFO:
2540 case SMB_FS_VOLUME_INFORMATION:
2543 * Add volume serial number - hash of a combination of
2544 * the called hostname and the service name.
2546 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2547 (str_checksum(get_local_machine_name())<<16));
2549 /* Max label len is 32 characters. */
2550 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2551 PTR_DIFF(end_data, pdata+18),
2552 STR_UNICODE);
2553 SIVAL(pdata,12,len);
2554 data_len = 18+len;
2556 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2557 (int)strlen(vname),vname, lp_servicename(snum)));
2558 break;
2560 case SMB_QUERY_FS_SIZE_INFO:
2561 case SMB_FS_SIZE_INFORMATION:
2563 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2564 data_len = 24;
2565 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2566 reply_unixerror(req, ERRHRD, ERRgeneral);
2567 return;
2569 block_size = lp_block_size(snum);
2570 if (bsize < block_size) {
2571 SMB_BIG_UINT factor = block_size/bsize;
2572 bsize = block_size;
2573 dsize /= factor;
2574 dfree /= factor;
2576 if (bsize > block_size) {
2577 SMB_BIG_UINT factor = bsize/block_size;
2578 bsize = block_size;
2579 dsize *= factor;
2580 dfree *= factor;
2582 bytes_per_sector = 512;
2583 sectors_per_unit = bsize/bytes_per_sector;
2584 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2585 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2586 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2587 SBIG_UINT(pdata,0,dsize);
2588 SBIG_UINT(pdata,8,dfree);
2589 SIVAL(pdata,16,sectors_per_unit);
2590 SIVAL(pdata,20,bytes_per_sector);
2591 break;
2594 case SMB_FS_FULL_SIZE_INFORMATION:
2596 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2597 data_len = 32;
2598 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2599 reply_unixerror(req, ERRHRD, ERRgeneral);
2600 return;
2602 block_size = lp_block_size(snum);
2603 if (bsize < block_size) {
2604 SMB_BIG_UINT factor = block_size/bsize;
2605 bsize = block_size;
2606 dsize /= factor;
2607 dfree /= factor;
2609 if (bsize > block_size) {
2610 SMB_BIG_UINT factor = bsize/block_size;
2611 bsize = block_size;
2612 dsize *= factor;
2613 dfree *= factor;
2615 bytes_per_sector = 512;
2616 sectors_per_unit = bsize/bytes_per_sector;
2617 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2618 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2619 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2620 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2621 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2622 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2623 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2624 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2625 break;
2628 case SMB_QUERY_FS_DEVICE_INFO:
2629 case SMB_FS_DEVICE_INFORMATION:
2630 data_len = 8;
2631 SIVAL(pdata,0,0); /* dev type */
2632 SIVAL(pdata,4,0); /* characteristics */
2633 break;
2635 #ifdef HAVE_SYS_QUOTAS
2636 case SMB_FS_QUOTA_INFORMATION:
2638 * what we have to send --metze:
2640 * Unknown1: 24 NULL bytes
2641 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2642 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2643 * Quota Flags: 2 byte :
2644 * Unknown3: 6 NULL bytes
2646 * 48 bytes total
2648 * details for Quota Flags:
2650 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2651 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2652 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2653 * 0x0001 Enable Quotas: enable quota for this fs
2657 /* we need to fake up a fsp here,
2658 * because its not send in this call
2660 files_struct fsp;
2661 SMB_NTQUOTA_STRUCT quotas;
2663 ZERO_STRUCT(fsp);
2664 ZERO_STRUCT(quotas);
2666 fsp.conn = conn;
2667 fsp.fnum = -1;
2669 /* access check */
2670 if (current_user.ut.uid != 0) {
2671 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2672 lp_servicename(SNUM(conn)),conn->user));
2673 reply_doserror(req, ERRDOS, ERRnoaccess);
2674 return;
2677 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2678 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2679 reply_doserror(req, ERRSRV, ERRerror);
2680 return;
2683 data_len = 48;
2685 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2687 /* Unknown1 24 NULL bytes*/
2688 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2689 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2690 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2692 /* Default Soft Quota 8 bytes */
2693 SBIG_UINT(pdata,24,quotas.softlim);
2695 /* Default Hard Quota 8 bytes */
2696 SBIG_UINT(pdata,32,quotas.hardlim);
2698 /* Quota flag 2 bytes */
2699 SSVAL(pdata,40,quotas.qflags);
2701 /* Unknown3 6 NULL bytes */
2702 SSVAL(pdata,42,0);
2703 SIVAL(pdata,44,0);
2705 break;
2707 #endif /* HAVE_SYS_QUOTAS */
2708 case SMB_FS_OBJECTID_INFORMATION:
2710 unsigned char objid[16];
2711 memcpy(pdata,create_volume_objectid(conn, objid),16);
2712 data_len = 64;
2713 break;
2717 * Query the version and capabilities of the CIFS UNIX extensions
2718 * in use.
2721 case SMB_QUERY_CIFS_UNIX_INFO:
2722 if (!lp_unix_extensions()) {
2723 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2724 return;
2726 data_len = 12;
2727 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2728 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2729 /* We have POSIX ACLs, pathname and locking capability. */
2730 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2731 CIFS_UNIX_POSIX_ACLS_CAP|
2732 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2733 CIFS_UNIX_FCNTL_LOCKS_CAP|
2734 CIFS_UNIX_EXTATTR_CAP|
2735 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2736 CIFS_UNIX_LARGE_READ_CAP)));
2737 break;
2739 case SMB_QUERY_POSIX_FS_INFO:
2741 int rc;
2742 vfs_statvfs_struct svfs;
2744 if (!lp_unix_extensions()) {
2745 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2746 return;
2749 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2751 if (!rc) {
2752 data_len = 56;
2753 SIVAL(pdata,0,svfs.OptimalTransferSize);
2754 SIVAL(pdata,4,svfs.BlockSize);
2755 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2756 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2757 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2758 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2759 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2760 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2761 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2762 #ifdef EOPNOTSUPP
2763 } else if (rc == EOPNOTSUPP) {
2764 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2765 return;
2766 #endif /* EOPNOTSUPP */
2767 } else {
2768 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2769 reply_doserror(req, ERRSRV, ERRerror);
2770 return;
2772 break;
2775 case SMB_QUERY_POSIX_WHOAMI:
2777 uint32_t flags = 0;
2778 uint32_t sid_bytes;
2779 int i;
2781 if (!lp_unix_extensions()) {
2782 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2783 return;
2786 if (max_data_bytes < 40) {
2787 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2788 return;
2791 /* We ARE guest if global_sid_Builtin_Guests is
2792 * in our list of SIDs.
2794 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2795 current_user.nt_user_token)) {
2796 flags |= SMB_WHOAMI_GUEST;
2799 /* We are NOT guest if global_sid_Authenticated_Users
2800 * is in our list of SIDs.
2802 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2803 current_user.nt_user_token)) {
2804 flags &= ~SMB_WHOAMI_GUEST;
2807 /* NOTE: 8 bytes for UID/GID, irrespective of native
2808 * platform size. This matches
2809 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2811 data_len = 4 /* flags */
2812 + 4 /* flag mask */
2813 + 8 /* uid */
2814 + 8 /* gid */
2815 + 4 /* ngroups */
2816 + 4 /* num_sids */
2817 + 4 /* SID bytes */
2818 + 4 /* pad/reserved */
2819 + (current_user.ut.ngroups * 8)
2820 /* groups list */
2821 + (current_user.nt_user_token->num_sids *
2822 SID_MAX_SIZE)
2823 /* SID list */;
2825 SIVAL(pdata, 0, flags);
2826 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2827 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2828 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2831 if (data_len >= max_data_bytes) {
2832 /* Potential overflow, skip the GIDs and SIDs. */
2834 SIVAL(pdata, 24, 0); /* num_groups */
2835 SIVAL(pdata, 28, 0); /* num_sids */
2836 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2837 SIVAL(pdata, 36, 0); /* reserved */
2839 data_len = 40;
2840 break;
2843 SIVAL(pdata, 24, current_user.ut.ngroups);
2844 SIVAL(pdata, 28,
2845 current_user.nt_user_token->num_sids);
2847 /* We walk the SID list twice, but this call is fairly
2848 * infrequent, and I don't expect that it's performance
2849 * sensitive -- jpeach
2851 for (i = 0, sid_bytes = 0;
2852 i < current_user.nt_user_token->num_sids; ++i) {
2853 sid_bytes +=
2854 sid_size(&current_user.nt_user_token->user_sids[i]);
2857 /* SID list byte count */
2858 SIVAL(pdata, 32, sid_bytes);
2860 /* 4 bytes pad/reserved - must be zero */
2861 SIVAL(pdata, 36, 0);
2862 data_len = 40;
2864 /* GID list */
2865 for (i = 0; i < current_user.ut.ngroups; ++i) {
2866 SBIG_UINT(pdata, data_len,
2867 (SMB_BIG_UINT)current_user.ut.groups[i]);
2868 data_len += 8;
2871 /* SID list */
2872 for (i = 0;
2873 i < current_user.nt_user_token->num_sids; ++i) {
2874 int sid_len =
2875 sid_size(&current_user.nt_user_token->user_sids[i]);
2877 sid_linearize(pdata + data_len, sid_len,
2878 &current_user.nt_user_token->user_sids[i]);
2879 data_len += sid_len;
2882 break;
2885 case SMB_MAC_QUERY_FS_INFO:
2887 * Thursby MAC extension... ONLY on NTFS filesystems
2888 * once we do streams then we don't need this
2890 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2891 data_len = 88;
2892 SIVAL(pdata,84,0x100); /* Don't support mac... */
2893 break;
2895 /* drop through */
2896 default:
2897 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2898 return;
2902 send_trans2_replies(req, params, 0, pdata, data_len,
2903 max_data_bytes);
2905 DEBUG( 4, ( "%s info_level = %d\n",
2906 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2908 return;
2911 /****************************************************************************
2912 Reply to a TRANS2_SETFSINFO (set filesystem info).
2913 ****************************************************************************/
2915 static void call_trans2setfsinfo(connection_struct *conn,
2916 struct smb_request *req,
2917 char **pparams, int total_params,
2918 char **ppdata, int total_data,
2919 unsigned int max_data_bytes)
2921 char *pdata = *ppdata;
2922 char *params = *pparams;
2923 uint16 info_level;
2925 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2927 /* */
2928 if (total_params < 4) {
2929 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2930 total_params));
2931 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2932 return;
2935 info_level = SVAL(params,2);
2937 switch(info_level) {
2938 case SMB_SET_CIFS_UNIX_INFO:
2940 uint16 client_unix_major;
2941 uint16 client_unix_minor;
2942 uint32 client_unix_cap_low;
2943 uint32 client_unix_cap_high;
2945 if (!lp_unix_extensions()) {
2946 reply_nterror(req,
2947 NT_STATUS_INVALID_LEVEL);
2948 return;
2951 /* There should be 12 bytes of capabilities set. */
2952 if (total_data < 8) {
2953 reply_nterror(
2954 req,
2955 NT_STATUS_INVALID_PARAMETER);
2956 return;
2958 client_unix_major = SVAL(pdata,0);
2959 client_unix_minor = SVAL(pdata,2);
2960 client_unix_cap_low = IVAL(pdata,4);
2961 client_unix_cap_high = IVAL(pdata,8);
2962 /* Just print these values for now. */
2963 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2964 cap_low = 0x%x, cap_high = 0x%x\n",
2965 (unsigned int)client_unix_major,
2966 (unsigned int)client_unix_minor,
2967 (unsigned int)client_unix_cap_low,
2968 (unsigned int)client_unix_cap_high ));
2970 /* Here is where we must switch to posix pathname processing... */
2971 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2972 lp_set_posix_pathnames();
2973 mangle_change_to_posix();
2976 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2977 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2978 /* Client that knows how to do posix locks,
2979 * but not posix open/mkdir operations. Set a
2980 * default type for read/write checks. */
2982 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2985 break;
2987 case SMB_FS_QUOTA_INFORMATION:
2989 files_struct *fsp = NULL;
2990 SMB_NTQUOTA_STRUCT quotas;
2992 ZERO_STRUCT(quotas);
2994 /* access check */
2995 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2996 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2997 lp_servicename(SNUM(conn)),conn->user));
2998 reply_doserror(req, ERRSRV, ERRaccess);
2999 return;
3002 /* note: normaly there're 48 bytes,
3003 * but we didn't use the last 6 bytes for now
3004 * --metze
3006 fsp = file_fsp(SVAL(params,0));
3007 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3008 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3009 reply_nterror(
3010 req, NT_STATUS_INVALID_HANDLE);
3011 return;
3014 if (total_data < 42) {
3015 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3016 total_data));
3017 reply_nterror(
3018 req,
3019 NT_STATUS_INVALID_PARAMETER);
3020 return;
3023 /* unknown_1 24 NULL bytes in pdata*/
3025 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3026 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3027 #ifdef LARGE_SMB_OFF_T
3028 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3029 #else /* LARGE_SMB_OFF_T */
3030 if ((IVAL(pdata,28) != 0)&&
3031 ((quotas.softlim != 0xFFFFFFFF)||
3032 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3033 /* more than 32 bits? */
3034 reply_nterror(
3035 req,
3036 NT_STATUS_INVALID_PARAMETER);
3037 return;
3039 #endif /* LARGE_SMB_OFF_T */
3041 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3042 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3043 #ifdef LARGE_SMB_OFF_T
3044 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3045 #else /* LARGE_SMB_OFF_T */
3046 if ((IVAL(pdata,36) != 0)&&
3047 ((quotas.hardlim != 0xFFFFFFFF)||
3048 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3049 /* more than 32 bits? */
3050 reply_nterror(
3051 req,
3052 NT_STATUS_INVALID_PARAMETER);
3053 return;
3055 #endif /* LARGE_SMB_OFF_T */
3057 /* quota_flags 2 bytes **/
3058 quotas.qflags = SVAL(pdata,40);
3060 /* unknown_2 6 NULL bytes follow*/
3062 /* now set the quotas */
3063 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3064 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3065 reply_doserror(req, ERRSRV, ERRerror);
3066 return;
3069 break;
3071 default:
3072 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3073 info_level));
3074 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3075 return;
3076 break;
3080 * sending this reply works fine,
3081 * but I'm not sure it's the same
3082 * like windows do...
3083 * --metze
3085 reply_outbuf(req, 10, 0);
3088 #if defined(HAVE_POSIX_ACLS)
3089 /****************************************************************************
3090 Utility function to count the number of entries in a POSIX acl.
3091 ****************************************************************************/
3093 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3095 unsigned int ace_count = 0;
3096 int entry_id = SMB_ACL_FIRST_ENTRY;
3097 SMB_ACL_ENTRY_T entry;
3099 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3100 /* get_next... */
3101 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3102 entry_id = SMB_ACL_NEXT_ENTRY;
3104 ace_count++;
3106 return ace_count;
3109 /****************************************************************************
3110 Utility function to marshall a POSIX acl into wire format.
3111 ****************************************************************************/
3113 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3115 int entry_id = SMB_ACL_FIRST_ENTRY;
3116 SMB_ACL_ENTRY_T entry;
3118 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3119 SMB_ACL_TAG_T tagtype;
3120 SMB_ACL_PERMSET_T permset;
3121 unsigned char perms = 0;
3122 unsigned int own_grp;
3124 /* get_next... */
3125 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3126 entry_id = SMB_ACL_NEXT_ENTRY;
3129 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3130 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3131 return False;
3134 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3135 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3136 return False;
3139 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3140 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3141 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3143 SCVAL(pdata,1,perms);
3145 switch (tagtype) {
3146 case SMB_ACL_USER_OBJ:
3147 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3148 own_grp = (unsigned int)pst->st_uid;
3149 SIVAL(pdata,2,own_grp);
3150 SIVAL(pdata,6,0);
3151 break;
3152 case SMB_ACL_USER:
3154 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3155 if (!puid) {
3156 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3157 return False;
3159 own_grp = (unsigned int)*puid;
3160 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3161 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3162 SIVAL(pdata,2,own_grp);
3163 SIVAL(pdata,6,0);
3164 break;
3166 case SMB_ACL_GROUP_OBJ:
3167 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3168 own_grp = (unsigned int)pst->st_gid;
3169 SIVAL(pdata,2,own_grp);
3170 SIVAL(pdata,6,0);
3171 break;
3172 case SMB_ACL_GROUP:
3174 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3175 if (!pgid) {
3176 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3177 return False;
3179 own_grp = (unsigned int)*pgid;
3180 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3181 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3182 SIVAL(pdata,2,own_grp);
3183 SIVAL(pdata,6,0);
3184 break;
3186 case SMB_ACL_MASK:
3187 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3188 SIVAL(pdata,2,0xFFFFFFFF);
3189 SIVAL(pdata,6,0xFFFFFFFF);
3190 break;
3191 case SMB_ACL_OTHER:
3192 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3193 SIVAL(pdata,2,0xFFFFFFFF);
3194 SIVAL(pdata,6,0xFFFFFFFF);
3195 break;
3196 default:
3197 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3198 return False;
3200 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3203 return True;
3205 #endif
3207 /****************************************************************************
3208 Store the FILE_UNIX_BASIC info.
3209 ****************************************************************************/
3211 static char *store_file_unix_basic(connection_struct *conn,
3212 char *pdata,
3213 files_struct *fsp,
3214 const SMB_STRUCT_STAT *psbuf)
3216 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3217 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3219 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3220 pdata += 8;
3222 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3223 pdata += 8;
3225 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3226 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3227 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3228 pdata += 24;
3230 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3231 SIVAL(pdata,4,0);
3232 pdata += 8;
3234 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3235 SIVAL(pdata,4,0);
3236 pdata += 8;
3238 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3239 pdata += 4;
3241 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3242 SIVAL(pdata,4,0);
3243 pdata += 8;
3245 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3246 SIVAL(pdata,4,0);
3247 pdata += 8;
3249 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3250 pdata += 8;
3252 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3253 SIVAL(pdata,4,0);
3254 pdata += 8;
3256 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3257 SIVAL(pdata,4,0);
3258 pdata += 8;
3260 return pdata;
3263 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3264 * the chflags(2) (or equivalent) flags.
3266 * XXX: this really should be behind the VFS interface. To do this, we would
3267 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3268 * Each VFS module could then implement it's own mapping as appropriate for the
3269 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3271 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3272 info2_flags_map[] =
3274 #ifdef UF_NODUMP
3275 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3276 #endif
3278 #ifdef UF_IMMUTABLE
3279 { UF_IMMUTABLE, EXT_IMMUTABLE },
3280 #endif
3282 #ifdef UF_APPEND
3283 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3284 #endif
3286 #ifdef UF_HIDDEN
3287 { UF_HIDDEN, EXT_HIDDEN },
3288 #endif
3290 /* Do not remove. We need to guarantee that this array has at least one
3291 * entry to build on HP-UX.
3293 { 0, 0 }
3297 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3298 uint32 *smb_fflags, uint32 *smb_fmask)
3300 #ifdef HAVE_STAT_ST_FLAGS
3301 int i;
3303 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3304 *smb_fmask |= info2_flags_map[i].smb_fflag;
3305 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3306 *smb_fflags |= info2_flags_map[i].smb_fflag;
3309 #endif /* HAVE_STAT_ST_FLAGS */
3312 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3313 const uint32 smb_fflags,
3314 const uint32 smb_fmask,
3315 int *stat_fflags)
3317 #ifdef HAVE_STAT_ST_FLAGS
3318 uint32 max_fmask = 0;
3319 int i;
3321 *stat_fflags = psbuf->st_flags;
3323 /* For each flags requested in smb_fmask, check the state of the
3324 * corresponding flag in smb_fflags and set or clear the matching
3325 * stat flag.
3328 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3329 max_fmask |= info2_flags_map[i].smb_fflag;
3330 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3331 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3332 *stat_fflags |= info2_flags_map[i].stat_fflag;
3333 } else {
3334 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3339 /* If smb_fmask is asking to set any bits that are not supported by
3340 * our flag mappings, we should fail.
3342 if ((smb_fmask & max_fmask) != smb_fmask) {
3343 return False;
3346 return True;
3347 #else
3348 return False;
3349 #endif /* HAVE_STAT_ST_FLAGS */
3353 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3354 * of file flags and birth (create) time.
3356 static char *store_file_unix_basic_info2(connection_struct *conn,
3357 char *pdata,
3358 files_struct *fsp,
3359 const SMB_STRUCT_STAT *psbuf)
3361 uint32 file_flags = 0;
3362 uint32 flags_mask = 0;
3364 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3366 /* Create (birth) time 64 bit */
3367 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3368 pdata += 8;
3370 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3371 SIVAL(pdata, 0, file_flags); /* flags */
3372 SIVAL(pdata, 4, flags_mask); /* mask */
3373 pdata += 8;
3375 return pdata;
3378 /****************************************************************************
3379 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3380 ****************************************************************************/
3382 static void call_trans2qpipeinfo(connection_struct *conn,
3383 struct smb_request *req,
3384 unsigned int tran_call,
3385 char **pparams, int total_params,
3386 char **ppdata, int total_data,
3387 unsigned int max_data_bytes)
3389 char *params = *pparams;
3390 char *pdata = *ppdata;
3391 unsigned int data_size = 0;
3392 unsigned int param_size = 2;
3393 uint16 info_level;
3394 smb_np_struct *p_pipe = NULL;
3396 if (!params) {
3397 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3398 return;
3401 if (total_params < 4) {
3402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3403 return;
3406 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3407 if (p_pipe == NULL) {
3408 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3409 return;
3412 info_level = SVAL(params,2);
3414 *pparams = (char *)SMB_REALLOC(*pparams,2);
3415 if (*pparams == NULL) {
3416 reply_nterror(req, NT_STATUS_NO_MEMORY);
3417 return;
3419 params = *pparams;
3420 SSVAL(params,0,0);
3421 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3422 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3423 if (*ppdata == NULL ) {
3424 reply_nterror(req, NT_STATUS_NO_MEMORY);
3425 return;
3427 pdata = *ppdata;
3429 switch (info_level) {
3430 case SMB_FILE_STANDARD_INFORMATION:
3431 memset(pdata,0,24);
3432 SOFF_T(pdata,0,4096LL);
3433 SIVAL(pdata,16,1);
3434 SIVAL(pdata,20,1);
3435 data_size = 24;
3436 break;
3438 default:
3439 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3440 return;
3443 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3444 max_data_bytes);
3446 return;
3449 /****************************************************************************
3450 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3451 file name or file id).
3452 ****************************************************************************/
3454 static void call_trans2qfilepathinfo(connection_struct *conn,
3455 struct smb_request *req,
3456 unsigned int tran_call,
3457 char **pparams, int total_params,
3458 char **ppdata, int total_data,
3459 unsigned int max_data_bytes)
3461 char *params = *pparams;
3462 char *pdata = *ppdata;
3463 char *dstart, *dend;
3464 uint16 info_level;
3465 int mode=0;
3466 int nlink;
3467 SMB_OFF_T file_size=0;
3468 SMB_BIG_UINT allocation_size=0;
3469 unsigned int data_size = 0;
3470 unsigned int param_size = 2;
3471 SMB_STRUCT_STAT sbuf;
3472 char *dos_fname = NULL;
3473 char *fname = NULL;
3474 char *fullpathname;
3475 char *base_name;
3476 char *p;
3477 SMB_OFF_T pos = 0;
3478 BOOL delete_pending = False;
3479 int len;
3480 time_t create_time, mtime, atime;
3481 struct timespec create_time_ts, mtime_ts, atime_ts;
3482 files_struct *fsp = NULL;
3483 struct file_id fileid;
3484 struct ea_list *ea_list = NULL;
3485 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3486 char *lock_data = NULL;
3487 TALLOC_CTX *ctx = talloc_tos();
3489 if (!params) {
3490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3491 return;
3494 ZERO_STRUCT(sbuf);
3496 if (tran_call == TRANSACT2_QFILEINFO) {
3497 if (total_params < 4) {
3498 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3499 return;
3502 if (IS_IPC(conn)) {
3503 call_trans2qpipeinfo(conn, req, tran_call,
3504 pparams, total_params,
3505 ppdata, total_data,
3506 max_data_bytes);
3507 return;
3510 fsp = file_fsp(SVAL(params,0));
3511 info_level = SVAL(params,2);
3513 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3515 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3516 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3517 return;
3520 /* Initial check for valid fsp ptr. */
3521 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3522 return;
3525 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3526 if (!fname) {
3527 reply_nterror(req, NT_STATUS_NO_MEMORY);
3528 return;
3531 if(fsp->fake_file_handle) {
3533 * This is actually for the QUOTA_FAKE_FILE --metze
3536 /* We know this name is ok, it's already passed the checks. */
3538 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3540 * This is actually a QFILEINFO on a directory
3541 * handle (returned from an NT SMB). NT5.0 seems
3542 * to do this call. JRA.
3545 if (INFO_LEVEL_IS_UNIX(info_level)) {
3546 /* Always do lstat for UNIX calls. */
3547 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3548 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3549 reply_unixerror(req,ERRDOS,ERRbadpath);
3550 return;
3552 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3553 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3554 reply_unixerror(req, ERRDOS, ERRbadpath);
3555 return;
3558 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3559 delete_pending = get_delete_on_close_flag(fileid);
3560 } else {
3562 * Original code - this is an open file.
3564 if (!check_fsp(conn, req, fsp, &current_user)) {
3565 return;
3568 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3569 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3570 reply_unixerror(req, ERRDOS, ERRbadfid);
3571 return;
3573 pos = fsp->fh->position_information;
3574 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3575 delete_pending = get_delete_on_close_flag(fileid);
3576 access_mask = fsp->access_mask;
3579 } else {
3580 NTSTATUS status = NT_STATUS_OK;
3582 /* qpathinfo */
3583 if (total_params < 7) {
3584 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3585 return;
3588 info_level = SVAL(params,0);
3590 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3592 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3593 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3594 return;
3597 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3598 total_params - 6,
3599 STR_TERMINATE, &status);
3600 if (!NT_STATUS_IS_OK(status)) {
3601 reply_nterror(req, status);
3602 return;
3605 status = resolve_dfspath(ctx,
3606 conn,
3607 req->flags2 & FLAGS2_DFS_PATHNAMES,
3608 fname,
3609 &fname);
3610 if (!NT_STATUS_IS_OK(status)) {
3611 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3612 reply_botherror(req,
3613 NT_STATUS_PATH_NOT_COVERED,
3614 ERRSRV, ERRbadpath);
3616 reply_nterror(req, status);
3617 return;
3620 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3621 if (!NT_STATUS_IS_OK(status)) {
3622 reply_nterror(req, status);
3623 return;
3625 status = check_name(conn, fname);
3626 if (!NT_STATUS_IS_OK(status)) {
3627 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3628 reply_nterror(req, status);
3629 return;
3632 if (INFO_LEVEL_IS_UNIX(info_level)) {
3633 /* Always do lstat for UNIX calls. */
3634 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3635 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3636 reply_unixerror(req, ERRDOS, ERRbadpath);
3637 return;
3639 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3640 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3641 reply_unixerror(req, ERRDOS, ERRbadpath);
3642 return;
3645 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3646 delete_pending = get_delete_on_close_flag(fileid);
3647 if (delete_pending) {
3648 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3649 return;
3653 nlink = sbuf.st_nlink;
3655 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3656 /* NTFS does not seem to count ".." */
3657 nlink -= 1;
3660 if ((nlink > 0) && delete_pending) {
3661 nlink -= 1;
3664 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3665 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3666 return;
3669 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3670 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3672 p = strrchr_m(fname,'/');
3673 if (!p)
3674 base_name = fname;
3675 else
3676 base_name = p+1;
3678 mode = dos_mode(conn,fname,&sbuf);
3679 if (!mode)
3680 mode = FILE_ATTRIBUTE_NORMAL;
3682 fullpathname = fname;
3683 if (!(mode & aDIR))
3684 file_size = get_file_size(sbuf);
3686 /* Pull out any data sent here before we realloc. */
3687 switch (info_level) {
3688 case SMB_INFO_QUERY_EAS_FROM_LIST:
3690 /* Pull any EA list from the data portion. */
3691 uint32 ea_size;
3693 if (total_data < 4) {
3694 reply_nterror(
3695 req, NT_STATUS_INVALID_PARAMETER);
3696 return;
3698 ea_size = IVAL(pdata,0);
3700 if (total_data > 0 && ea_size != total_data) {
3701 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3702 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3703 reply_nterror(
3704 req, NT_STATUS_INVALID_PARAMETER);
3705 return;
3708 if (!lp_ea_support(SNUM(conn))) {
3709 reply_doserror(req, ERRDOS,
3710 ERReasnotsupported);
3711 return;
3714 /* Pull out the list of names. */
3715 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3716 if (!ea_list) {
3717 reply_nterror(
3718 req, NT_STATUS_INVALID_PARAMETER);
3719 return;
3721 break;
3724 case SMB_QUERY_POSIX_LOCK:
3726 if (fsp == NULL || fsp->fh->fd == -1) {
3727 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3728 return;
3731 if (total_data != POSIX_LOCK_DATA_SIZE) {
3732 reply_nterror(
3733 req, NT_STATUS_INVALID_PARAMETER);
3734 return;
3737 /* Copy the lock range data. */
3738 lock_data = (char *)TALLOC_MEMDUP(
3739 ctx, pdata, total_data);
3740 if (!lock_data) {
3741 reply_nterror(req, NT_STATUS_NO_MEMORY);
3742 return;
3745 default:
3746 break;
3749 *pparams = (char *)SMB_REALLOC(*pparams,2);
3750 if (*pparams == NULL) {
3751 reply_nterror(req, NT_STATUS_NO_MEMORY);
3752 return;
3754 params = *pparams;
3755 SSVAL(params,0,0);
3756 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3757 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3758 if (*ppdata == NULL ) {
3759 reply_nterror(req, NT_STATUS_NO_MEMORY);
3760 return;
3762 pdata = *ppdata;
3763 dstart = pdata;
3764 dend = dstart + data_size - 1;
3766 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3767 mtime_ts = get_mtimespec(&sbuf);
3768 atime_ts = get_atimespec(&sbuf);
3770 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3772 if (fsp) {
3773 if (!null_timespec(fsp->pending_modtime)) {
3774 /* the pending modtime overrides the current modtime */
3775 mtime_ts = fsp->pending_modtime;
3777 } else {
3778 files_struct *fsp1;
3779 /* Do we have this path open ? */
3780 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3781 fsp1 = file_find_di_first(fileid);
3782 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3783 /* the pending modtime overrides the current modtime */
3784 mtime_ts = fsp1->pending_modtime;
3786 if (fsp1 && fsp1->initial_allocation_size) {
3787 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3791 if (lp_dos_filetime_resolution(SNUM(conn))) {
3792 dos_filetime_timespec(&create_time_ts);
3793 dos_filetime_timespec(&mtime_ts);
3794 dos_filetime_timespec(&atime_ts);
3797 create_time = convert_timespec_to_time_t(create_time_ts);
3798 mtime = convert_timespec_to_time_t(mtime_ts);
3799 atime = convert_timespec_to_time_t(atime_ts);
3801 /* NT expects the name to be in an exact form of the *full*
3802 filename. See the trans2 torture test */
3803 if (ISDOT(base_name)) {
3804 dos_fname = talloc_strdup(ctx, "\\");
3805 if (!dos_fname) {
3806 reply_nterror(req, NT_STATUS_NO_MEMORY);
3807 return;
3809 } else {
3810 dos_fname = talloc_asprintf(ctx,
3811 "\\%s",
3812 fname);
3813 if (!dos_fname) {
3814 reply_nterror(req, NT_STATUS_NO_MEMORY);
3815 return;
3817 string_replace(dos_fname, '/', '\\');
3820 switch (info_level) {
3821 case SMB_INFO_STANDARD:
3822 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3823 data_size = 22;
3824 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3825 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3826 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3827 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3828 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3829 SSVAL(pdata,l1_attrFile,mode);
3830 break;
3832 case SMB_INFO_QUERY_EA_SIZE:
3834 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3835 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3836 data_size = 26;
3837 srv_put_dos_date2(pdata,0,create_time);
3838 srv_put_dos_date2(pdata,4,atime);
3839 srv_put_dos_date2(pdata,8,mtime); /* write time */
3840 SIVAL(pdata,12,(uint32)file_size);
3841 SIVAL(pdata,16,(uint32)allocation_size);
3842 SSVAL(pdata,20,mode);
3843 SIVAL(pdata,22,ea_size);
3844 break;
3847 case SMB_INFO_IS_NAME_VALID:
3848 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3849 if (tran_call == TRANSACT2_QFILEINFO) {
3850 /* os/2 needs this ? really ?*/
3851 reply_doserror(req, ERRDOS, ERRbadfunc);
3852 return;
3854 data_size = 0;
3855 param_size = 0;
3856 break;
3858 case SMB_INFO_QUERY_EAS_FROM_LIST:
3860 size_t total_ea_len = 0;
3861 struct ea_list *ea_file_list = NULL;
3863 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3865 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3866 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3868 if (!ea_list || (total_ea_len > data_size)) {
3869 data_size = 4;
3870 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3871 break;
3874 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3875 break;
3878 case SMB_INFO_QUERY_ALL_EAS:
3880 /* We have data_size bytes to put EA's into. */
3881 size_t total_ea_len = 0;
3883 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3885 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3886 if (!ea_list || (total_ea_len > data_size)) {
3887 data_size = 4;
3888 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3889 break;
3892 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3893 break;
3896 case SMB_FILE_BASIC_INFORMATION:
3897 case SMB_QUERY_FILE_BASIC_INFO:
3899 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3900 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3901 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3902 } else {
3903 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3904 data_size = 40;
3905 SIVAL(pdata,36,0);
3907 put_long_date_timespec(pdata,create_time_ts);
3908 put_long_date_timespec(pdata+8,atime_ts);
3909 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3910 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3911 SIVAL(pdata,32,mode);
3913 DEBUG(5,("SMB_QFBI - "));
3914 DEBUG(5,("create: %s ", ctime(&create_time)));
3915 DEBUG(5,("access: %s ", ctime(&atime)));
3916 DEBUG(5,("write: %s ", ctime(&mtime)));
3917 DEBUG(5,("change: %s ", ctime(&mtime)));
3918 DEBUG(5,("mode: %x\n", mode));
3919 break;
3921 case SMB_FILE_STANDARD_INFORMATION:
3922 case SMB_QUERY_FILE_STANDARD_INFO:
3924 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3925 data_size = 24;
3926 SOFF_T(pdata,0,allocation_size);
3927 SOFF_T(pdata,8,file_size);
3928 SIVAL(pdata,16,nlink);
3929 SCVAL(pdata,20,delete_pending?1:0);
3930 SCVAL(pdata,21,(mode&aDIR)?1:0);
3931 SSVAL(pdata,22,0); /* Padding. */
3932 break;
3934 case SMB_FILE_EA_INFORMATION:
3935 case SMB_QUERY_FILE_EA_INFO:
3937 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3938 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3939 data_size = 4;
3940 SIVAL(pdata,0,ea_size);
3941 break;
3944 /* Get the 8.3 name - used if NT SMB was negotiated. */
3945 case SMB_QUERY_FILE_ALT_NAME_INFO:
3946 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3948 char mangled_name[13];
3949 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3950 if (!name_to_8_3(base_name,mangled_name,
3951 True,conn->params)) {
3952 reply_nterror(
3953 req,
3954 NT_STATUS_NO_MEMORY);
3956 len = srvstr_push(dstart, req->flags2,
3957 pdata+4, mangled_name,
3958 PTR_DIFF(dend, pdata+4),
3959 STR_UNICODE);
3960 data_size = 4 + len;
3961 SIVAL(pdata,0,len);
3962 break;
3965 case SMB_QUERY_FILE_NAME_INFO:
3967 this must be *exactly* right for ACLs on mapped drives to work
3969 len = srvstr_push(dstart, req->flags2,
3970 pdata+4, dos_fname,
3971 PTR_DIFF(dend, pdata+4),
3972 STR_UNICODE);
3973 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3974 data_size = 4 + len;
3975 SIVAL(pdata,0,len);
3976 break;
3978 case SMB_FILE_ALLOCATION_INFORMATION:
3979 case SMB_QUERY_FILE_ALLOCATION_INFO:
3980 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3981 data_size = 8;
3982 SOFF_T(pdata,0,allocation_size);
3983 break;
3985 case SMB_FILE_END_OF_FILE_INFORMATION:
3986 case SMB_QUERY_FILE_END_OF_FILEINFO:
3987 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3988 data_size = 8;
3989 SOFF_T(pdata,0,file_size);
3990 break;
3992 case SMB_QUERY_FILE_ALL_INFO:
3993 case SMB_FILE_ALL_INFORMATION:
3995 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3996 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3997 put_long_date_timespec(pdata,create_time_ts);
3998 put_long_date_timespec(pdata+8,atime_ts);
3999 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4000 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4001 SIVAL(pdata,32,mode);
4002 SIVAL(pdata,36,0); /* padding. */
4003 pdata += 40;
4004 SOFF_T(pdata,0,allocation_size);
4005 SOFF_T(pdata,8,file_size);
4006 SIVAL(pdata,16,nlink);
4007 SCVAL(pdata,20,delete_pending);
4008 SCVAL(pdata,21,(mode&aDIR)?1:0);
4009 SSVAL(pdata,22,0);
4010 pdata += 24;
4011 SIVAL(pdata,0,ea_size);
4012 pdata += 4; /* EA info */
4013 len = srvstr_push(dstart, req->flags2,
4014 pdata+4, dos_fname,
4015 PTR_DIFF(dend, pdata+4),
4016 STR_UNICODE);
4017 SIVAL(pdata,0,len);
4018 pdata += 4 + len;
4019 data_size = PTR_DIFF(pdata,(*ppdata));
4020 break;
4022 case SMB_FILE_INTERNAL_INFORMATION:
4023 /* This should be an index number - looks like
4024 dev/ino to me :-)
4026 I think this causes us to fail the IFSKIT
4027 BasicFileInformationTest. -tpot */
4029 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4030 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4031 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4032 data_size = 8;
4033 break;
4035 case SMB_FILE_ACCESS_INFORMATION:
4036 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4037 SIVAL(pdata,0,access_mask);
4038 data_size = 4;
4039 break;
4041 case SMB_FILE_NAME_INFORMATION:
4042 /* Pathname with leading '\'. */
4044 size_t byte_len;
4045 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4046 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4047 SIVAL(pdata,0,byte_len);
4048 data_size = 4 + byte_len;
4049 break;
4052 case SMB_FILE_DISPOSITION_INFORMATION:
4053 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4054 data_size = 1;
4055 SCVAL(pdata,0,delete_pending);
4056 break;
4058 case SMB_FILE_POSITION_INFORMATION:
4059 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4060 data_size = 8;
4061 SOFF_T(pdata,0,pos);
4062 break;
4064 case SMB_FILE_MODE_INFORMATION:
4065 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4066 SIVAL(pdata,0,mode);
4067 data_size = 4;
4068 break;
4070 case SMB_FILE_ALIGNMENT_INFORMATION:
4071 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4072 SIVAL(pdata,0,0); /* No alignment needed. */
4073 data_size = 4;
4074 break;
4076 #if 0
4078 * NT4 server just returns "invalid query" to this - if we try to answer
4079 * it then NTws gets a BSOD! (tridge).
4080 * W2K seems to want this. JRA.
4082 case SMB_QUERY_FILE_STREAM_INFO:
4083 #endif
4084 case SMB_FILE_STREAM_INFORMATION:
4085 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4086 if (mode & aDIR) {
4087 data_size = 0;
4088 } else {
4089 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4090 SIVAL(pdata,0,0); /* ??? */
4091 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4092 SOFF_T(pdata,8,file_size);
4093 SOFF_T(pdata,16,allocation_size);
4094 data_size = 24 + byte_len;
4096 break;
4098 case SMB_QUERY_COMPRESSION_INFO:
4099 case SMB_FILE_COMPRESSION_INFORMATION:
4100 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4101 SOFF_T(pdata,0,file_size);
4102 SIVAL(pdata,8,0); /* ??? */
4103 SIVAL(pdata,12,0); /* ??? */
4104 data_size = 16;
4105 break;
4107 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4108 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4109 put_long_date_timespec(pdata,create_time_ts);
4110 put_long_date_timespec(pdata+8,atime_ts);
4111 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4112 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4113 SOFF_T(pdata,32,allocation_size);
4114 SOFF_T(pdata,40,file_size);
4115 SIVAL(pdata,48,mode);
4116 SIVAL(pdata,52,0); /* ??? */
4117 data_size = 56;
4118 break;
4120 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4121 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4122 SIVAL(pdata,0,mode);
4123 SIVAL(pdata,4,0);
4124 data_size = 8;
4125 break;
4128 * CIFS UNIX Extensions.
4131 case SMB_QUERY_FILE_UNIX_BASIC:
4133 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4134 data_size = PTR_DIFF(pdata,(*ppdata));
4137 int i;
4138 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4140 for (i=0; i<100; i++)
4141 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4142 DEBUG(4,("\n"));
4145 break;
4147 case SMB_QUERY_FILE_UNIX_INFO2:
4149 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4150 data_size = PTR_DIFF(pdata,(*ppdata));
4153 int i;
4154 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4156 for (i=0; i<100; i++)
4157 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4158 DEBUG(4,("\n"));
4161 break;
4163 case SMB_QUERY_FILE_UNIX_LINK:
4165 char *buffer = TALLOC_ARRAY(ctx, char, 1024);
4167 if (!buffer) {
4168 reply_nterror(req, NT_STATUS_NO_MEMORY);
4169 return;
4172 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4173 #ifdef S_ISLNK
4174 if(!S_ISLNK(sbuf.st_mode)) {
4175 reply_unixerror(req, ERRSRV,
4176 ERRbadlink);
4177 return;
4179 #else
4180 reply_unixerror(req, ERRDOS, ERRbadlink);
4181 return;
4182 #endif
4183 len = SMB_VFS_READLINK(conn,fullpathname,
4184 buffer, 1023);
4185 if (len == -1) {
4186 reply_unixerror(req, ERRDOS,
4187 ERRnoaccess);
4188 return;
4190 buffer[len] = 0;
4191 len = srvstr_push(dstart, req->flags2,
4192 pdata, buffer,
4193 PTR_DIFF(dend, pdata),
4194 STR_TERMINATE);
4195 pdata += len;
4196 data_size = PTR_DIFF(pdata,(*ppdata));
4198 break;
4201 #if defined(HAVE_POSIX_ACLS)
4202 case SMB_QUERY_POSIX_ACL:
4204 SMB_ACL_T file_acl = NULL;
4205 SMB_ACL_T def_acl = NULL;
4206 uint16 num_file_acls = 0;
4207 uint16 num_def_acls = 0;
4209 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4210 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4211 } else {
4212 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4215 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4216 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4217 fname ));
4218 reply_nterror(
4219 req,
4220 NT_STATUS_NOT_IMPLEMENTED);
4221 return;
4224 if (S_ISDIR(sbuf.st_mode)) {
4225 if (fsp && fsp->is_directory) {
4226 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4227 } else {
4228 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4230 def_acl = free_empty_sys_acl(conn, def_acl);
4233 num_file_acls = count_acl_entries(conn, file_acl);
4234 num_def_acls = count_acl_entries(conn, def_acl);
4236 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4237 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4238 data_size,
4239 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4240 SMB_POSIX_ACL_HEADER_SIZE) ));
4241 if (file_acl) {
4242 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4244 if (def_acl) {
4245 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4247 reply_nterror(
4248 req,
4249 NT_STATUS_BUFFER_TOO_SMALL);
4250 return;
4253 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4254 SSVAL(pdata,2,num_file_acls);
4255 SSVAL(pdata,4,num_def_acls);
4256 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4257 if (file_acl) {
4258 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4260 if (def_acl) {
4261 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4263 reply_nterror(
4264 req, NT_STATUS_INTERNAL_ERROR);
4265 return;
4267 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4268 if (file_acl) {
4269 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4271 if (def_acl) {
4272 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4274 reply_nterror(
4275 req,
4276 NT_STATUS_INTERNAL_ERROR);
4277 return;
4280 if (file_acl) {
4281 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4283 if (def_acl) {
4284 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4286 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4287 break;
4289 #endif
4292 case SMB_QUERY_POSIX_LOCK:
4294 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4295 SMB_BIG_UINT count;
4296 SMB_BIG_UINT offset;
4297 uint32 lock_pid;
4298 enum brl_type lock_type;
4300 if (total_data != POSIX_LOCK_DATA_SIZE) {
4301 reply_nterror(
4302 req, NT_STATUS_INVALID_PARAMETER);
4303 return;
4306 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4307 case POSIX_LOCK_TYPE_READ:
4308 lock_type = READ_LOCK;
4309 break;
4310 case POSIX_LOCK_TYPE_WRITE:
4311 lock_type = WRITE_LOCK;
4312 break;
4313 case POSIX_LOCK_TYPE_UNLOCK:
4314 default:
4315 /* There's no point in asking for an unlock... */
4316 reply_nterror(
4317 req,
4318 NT_STATUS_INVALID_PARAMETER);
4319 return;
4322 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4323 #if defined(HAVE_LONGLONG)
4324 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4325 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4326 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4327 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4328 #else /* HAVE_LONGLONG */
4329 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4330 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4331 #endif /* HAVE_LONGLONG */
4333 status = query_lock(fsp,
4334 &lock_pid,
4335 &count,
4336 &offset,
4337 &lock_type,
4338 POSIX_LOCK);
4340 if (ERROR_WAS_LOCK_DENIED(status)) {
4341 /* Here we need to report who has it locked... */
4342 data_size = POSIX_LOCK_DATA_SIZE;
4344 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4345 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4346 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4347 #if defined(HAVE_LONGLONG)
4348 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4349 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4350 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4351 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4352 #else /* HAVE_LONGLONG */
4353 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4354 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4355 #endif /* HAVE_LONGLONG */
4357 } else if (NT_STATUS_IS_OK(status)) {
4358 /* For success we just return a copy of what we sent
4359 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4360 data_size = POSIX_LOCK_DATA_SIZE;
4361 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4362 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4363 } else {
4364 reply_nterror(req, status);
4365 return;
4367 break;
4370 default:
4371 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4372 return;
4375 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4376 max_data_bytes);
4378 return;
4381 /****************************************************************************
4382 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4383 code.
4384 ****************************************************************************/
4386 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4387 connection_struct *conn,
4388 const char *oldname_in,
4389 const char *newname_in)
4391 SMB_STRUCT_STAT sbuf1, sbuf2;
4392 char *last_component_oldname = NULL;
4393 char *last_component_newname = NULL;
4394 char *oldname = NULL;
4395 char *newname = NULL;
4396 NTSTATUS status = NT_STATUS_OK;
4398 ZERO_STRUCT(sbuf1);
4399 ZERO_STRUCT(sbuf2);
4401 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4402 &last_component_oldname, &sbuf1);
4403 if (!NT_STATUS_IS_OK(status)) {
4404 return status;
4407 status = check_name(conn, oldname);
4408 if (!NT_STATUS_IS_OK(status)) {
4409 return status;
4412 /* source must already exist. */
4413 if (!VALID_STAT(sbuf1)) {
4414 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4417 status = unix_convert(ctx, conn, newname_in, False, &newname,
4418 &last_component_newname, &sbuf2);
4419 if (!NT_STATUS_IS_OK(status)) {
4420 return status;
4423 status = check_name(conn, newname);
4424 if (!NT_STATUS_IS_OK(status)) {
4425 return status;
4428 /* Disallow if newname already exists. */
4429 if (VALID_STAT(sbuf2)) {
4430 return NT_STATUS_OBJECT_NAME_COLLISION;
4433 /* No links from a directory. */
4434 if (S_ISDIR(sbuf1.st_mode)) {
4435 return NT_STATUS_FILE_IS_A_DIRECTORY;
4438 /* Ensure this is within the share. */
4439 status = check_reduced_name(conn, oldname);
4440 if (!NT_STATUS_IS_OK(status)) {
4441 return status;
4444 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4446 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4447 status = map_nt_error_from_unix(errno);
4448 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4449 nt_errstr(status), newname, oldname));
4452 return status;
4455 /****************************************************************************
4456 Deal with setting the time from any of the setfilepathinfo functions.
4457 ****************************************************************************/
4459 static NTSTATUS smb_set_file_time(connection_struct *conn,
4460 files_struct *fsp,
4461 const char *fname,
4462 const SMB_STRUCT_STAT *psbuf,
4463 struct timespec ts[2])
4465 uint32 action =
4466 FILE_NOTIFY_CHANGE_LAST_ACCESS
4467 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4470 if (!VALID_STAT(*psbuf)) {
4471 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4474 /* get some defaults (no modifications) if any info is zero or -1. */
4475 if (null_timespec(ts[0])) {
4476 ts[0] = get_atimespec(psbuf);
4477 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4480 if (null_timespec(ts[1])) {
4481 ts[1] = get_mtimespec(psbuf);
4482 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4485 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4486 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4489 * Try and set the times of this file if
4490 * they are different from the current values.
4494 struct timespec mts = get_mtimespec(psbuf);
4495 struct timespec ats = get_atimespec(psbuf);
4496 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4497 return NT_STATUS_OK;
4501 if(fsp != NULL) {
4503 * This was a setfileinfo on an open file.
4504 * NT does this a lot. We also need to
4505 * set the time here, as it can be read by
4506 * FindFirst/FindNext and with the patch for bug #2045
4507 * in smbd/fileio.c it ensures that this timestamp is
4508 * kept sticky even after a write. We save the request
4509 * away and will set it on file close and after a write. JRA.
4512 if (!null_timespec(ts[1])) {
4513 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4514 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4515 fsp_set_pending_modtime(fsp, ts[1]);
4519 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4521 if(file_ntimes(conn, fname, ts)!=0) {
4522 return map_nt_error_from_unix(errno);
4524 if (action != 0) {
4525 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4527 return NT_STATUS_OK;
4530 /****************************************************************************
4531 Deal with setting the dosmode from any of the setfilepathinfo functions.
4532 ****************************************************************************/
4534 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4535 const char *fname,
4536 SMB_STRUCT_STAT *psbuf,
4537 uint32 dosmode)
4539 if (!VALID_STAT(*psbuf)) {
4540 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4543 if (dosmode) {
4544 if (S_ISDIR(psbuf->st_mode)) {
4545 dosmode |= aDIR;
4546 } else {
4547 dosmode &= ~aDIR;
4551 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4553 /* check the mode isn't different, before changing it */
4554 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4556 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4557 fname, (unsigned int)dosmode ));
4559 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4560 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4561 fname, strerror(errno)));
4562 return map_nt_error_from_unix(errno);
4565 return NT_STATUS_OK;
4568 /****************************************************************************
4569 Deal with setting the size from any of the setfilepathinfo functions.
4570 ****************************************************************************/
4572 static NTSTATUS smb_set_file_size(connection_struct *conn,
4573 struct smb_request *req,
4574 files_struct *fsp,
4575 const char *fname,
4576 SMB_STRUCT_STAT *psbuf,
4577 SMB_OFF_T size)
4579 NTSTATUS status = NT_STATUS_OK;
4580 files_struct *new_fsp = NULL;
4582 if (!VALID_STAT(*psbuf)) {
4583 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4586 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4588 if (size == get_file_size(*psbuf)) {
4589 return NT_STATUS_OK;
4592 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4593 fname, (double)size ));
4595 if (fsp && fsp->fh->fd != -1) {
4596 /* Handle based call. */
4597 if (vfs_set_filelen(fsp, size) == -1) {
4598 return map_nt_error_from_unix(errno);
4600 return NT_STATUS_OK;
4603 status = open_file_ntcreate(conn, req, fname, psbuf,
4604 FILE_WRITE_DATA,
4605 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4606 FILE_OPEN,
4608 FILE_ATTRIBUTE_NORMAL,
4609 FORCE_OPLOCK_BREAK_TO_NONE,
4610 NULL, &new_fsp);
4612 if (!NT_STATUS_IS_OK(status)) {
4613 /* NB. We check for open_was_deferred in the caller. */
4614 return status;
4617 if (vfs_set_filelen(new_fsp, size) == -1) {
4618 status = map_nt_error_from_unix(errno);
4619 close_file(new_fsp,NORMAL_CLOSE);
4620 return status;
4623 close_file(new_fsp,NORMAL_CLOSE);
4624 return NT_STATUS_OK;
4627 /****************************************************************************
4628 Deal with SMB_INFO_SET_EA.
4629 ****************************************************************************/
4631 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4632 const char *pdata,
4633 int total_data,
4634 files_struct *fsp,
4635 const char *fname)
4637 struct ea_list *ea_list = NULL;
4638 TALLOC_CTX *ctx = NULL;
4639 NTSTATUS status = NT_STATUS_OK;
4641 if (total_data < 10) {
4643 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4644 length. They seem to have no effect. Bug #3212. JRA */
4646 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4647 /* We're done. We only get EA info in this call. */
4648 return NT_STATUS_OK;
4651 return NT_STATUS_INVALID_PARAMETER;
4654 if (IVAL(pdata,0) > total_data) {
4655 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4656 IVAL(pdata,0), (unsigned int)total_data));
4657 return NT_STATUS_INVALID_PARAMETER;
4660 ctx = talloc_init("SMB_INFO_SET_EA");
4661 if (!ctx) {
4662 return NT_STATUS_NO_MEMORY;
4664 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4665 if (!ea_list) {
4666 talloc_destroy(ctx);
4667 return NT_STATUS_INVALID_PARAMETER;
4669 status = set_ea(conn, fsp, fname, ea_list);
4670 talloc_destroy(ctx);
4672 return status;
4675 /****************************************************************************
4676 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4677 ****************************************************************************/
4679 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4680 const char *pdata,
4681 int total_data,
4682 files_struct *fsp,
4683 const char *fname,
4684 SMB_STRUCT_STAT *psbuf)
4686 NTSTATUS status = NT_STATUS_OK;
4687 BOOL delete_on_close;
4688 uint32 dosmode = 0;
4690 if (total_data < 1) {
4691 return NT_STATUS_INVALID_PARAMETER;
4694 if (fsp == NULL) {
4695 return NT_STATUS_INVALID_HANDLE;
4698 delete_on_close = (CVAL(pdata,0) ? True : False);
4699 dosmode = dos_mode(conn, fname, psbuf);
4701 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4702 "delete_on_close = %u\n",
4703 fsp->fsp_name,
4704 (unsigned int)dosmode,
4705 (unsigned int)delete_on_close ));
4707 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 return status;
4713 /* The set is across all open files on this dev/inode pair. */
4714 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4715 return NT_STATUS_ACCESS_DENIED;
4717 return NT_STATUS_OK;
4720 /****************************************************************************
4721 Deal with SMB_FILE_POSITION_INFORMATION.
4722 ****************************************************************************/
4724 static NTSTATUS smb_file_position_information(connection_struct *conn,
4725 const char *pdata,
4726 int total_data,
4727 files_struct *fsp)
4729 SMB_BIG_UINT position_information;
4731 if (total_data < 8) {
4732 return NT_STATUS_INVALID_PARAMETER;
4735 if (fsp == NULL) {
4736 /* Ignore on pathname based set. */
4737 return NT_STATUS_OK;
4740 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4741 #ifdef LARGE_SMB_OFF_T
4742 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4743 #else /* LARGE_SMB_OFF_T */
4744 if (IVAL(pdata,4) != 0) {
4745 /* more than 32 bits? */
4746 return NT_STATUS_INVALID_PARAMETER;
4748 #endif /* LARGE_SMB_OFF_T */
4750 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4751 fsp->fsp_name, (double)position_information ));
4752 fsp->fh->position_information = position_information;
4753 return NT_STATUS_OK;
4756 /****************************************************************************
4757 Deal with SMB_FILE_MODE_INFORMATION.
4758 ****************************************************************************/
4760 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4761 const char *pdata,
4762 int total_data)
4764 uint32 mode;
4766 if (total_data < 4) {
4767 return NT_STATUS_INVALID_PARAMETER;
4769 mode = IVAL(pdata,0);
4770 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4771 return NT_STATUS_INVALID_PARAMETER;
4773 return NT_STATUS_OK;
4776 /****************************************************************************
4777 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4778 ****************************************************************************/
4780 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4781 struct smb_request *req,
4782 const char *pdata,
4783 int total_data,
4784 const char *fname)
4786 char *link_target = NULL;
4787 const char *newname = fname;
4788 NTSTATUS status = NT_STATUS_OK;
4789 TALLOC_CTX *ctx = talloc_tos();
4791 /* Set a symbolic link. */
4792 /* Don't allow this if follow links is false. */
4794 if (total_data == 0) {
4795 return NT_STATUS_INVALID_PARAMETER;
4798 if (!lp_symlinks(SNUM(conn))) {
4799 return NT_STATUS_ACCESS_DENIED;
4802 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4803 total_data, STR_TERMINATE);
4805 if (!link_target) {
4806 return NT_STATUS_INVALID_PARAMETER;
4809 /* !widelinks forces the target path to be within the share. */
4810 /* This means we can interpret the target as a pathname. */
4811 if (!lp_widelinks(SNUM(conn))) {
4812 char *rel_name = NULL;
4813 char *last_dirp = NULL;
4815 if (*link_target == '/') {
4816 /* No absolute paths allowed. */
4817 return NT_STATUS_ACCESS_DENIED;
4819 rel_name = talloc_strdup(ctx,newname);
4820 if (!rel_name) {
4821 return NT_STATUS_NO_MEMORY;
4823 last_dirp = strrchr_m(rel_name, '/');
4824 if (last_dirp) {
4825 last_dirp[1] = '\0';
4826 } else {
4827 rel_name = talloc_strdup(ctx,"./");
4828 if (!rel_name) {
4829 return NT_STATUS_NO_MEMORY;
4832 rel_name = talloc_asprintf_append(rel_name,
4833 "%s",
4834 link_target);
4835 if (!rel_name) {
4836 return NT_STATUS_NO_MEMORY;
4839 status = check_name(conn, rel_name);
4840 if (!NT_STATUS_IS_OK(status)) {
4841 return status;
4845 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4846 newname, link_target ));
4848 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4849 return map_nt_error_from_unix(errno);
4852 return NT_STATUS_OK;
4855 /****************************************************************************
4856 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4857 ****************************************************************************/
4859 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4860 struct smb_request *req,
4861 const char *pdata, int total_data,
4862 const char *fname)
4864 char *oldname = NULL;
4865 TALLOC_CTX *ctx = talloc_tos();
4866 NTSTATUS status = NT_STATUS_OK;
4868 /* Set a hard link. */
4869 if (total_data == 0) {
4870 return NT_STATUS_INVALID_PARAMETER;
4873 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4874 total_data, STR_TERMINATE, &status);
4875 if (!NT_STATUS_IS_OK(status)) {
4876 return status;
4879 status = resolve_dfspath(ctx, conn,
4880 req->flags2 & FLAGS2_DFS_PATHNAMES,
4881 oldname,
4882 &oldname);
4883 if (!NT_STATUS_IS_OK(status)) {
4884 return status;
4887 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4888 fname, oldname));
4890 return hardlink_internals(ctx, conn, oldname, fname);
4893 /****************************************************************************
4894 Deal with SMB_FILE_RENAME_INFORMATION.
4895 ****************************************************************************/
4897 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4898 struct smb_request *req,
4899 const char *pdata,
4900 int total_data,
4901 files_struct *fsp,
4902 const char *fname)
4904 BOOL overwrite;
4905 uint32 root_fid;
4906 uint32 len;
4907 char *newname = NULL;
4908 char *base_name = NULL;
4909 BOOL dest_has_wcard = False;
4910 NTSTATUS status = NT_STATUS_OK;
4911 char *p;
4912 TALLOC_CTX *ctx = talloc_tos();
4914 if (total_data < 13) {
4915 return NT_STATUS_INVALID_PARAMETER;
4918 overwrite = (CVAL(pdata,0) ? True : False);
4919 root_fid = IVAL(pdata,4);
4920 len = IVAL(pdata,8);
4922 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4923 return NT_STATUS_INVALID_PARAMETER;
4926 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
4927 len, 0, &status,
4928 &dest_has_wcard);
4929 if (!NT_STATUS_IS_OK(status)) {
4930 return status;
4933 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4934 newname));
4936 status = resolve_dfspath_wcard(ctx, conn,
4937 req->flags2 & FLAGS2_DFS_PATHNAMES,
4938 newname,
4939 &newname,
4940 &dest_has_wcard);
4941 if (!NT_STATUS_IS_OK(status)) {
4942 return status;
4945 /* Check the new name has no '/' characters. */
4946 if (strchr_m(newname, '/')) {
4947 return NT_STATUS_NOT_SUPPORTED;
4950 /* Create the base directory. */
4951 base_name = talloc_strdup(ctx, fname);
4952 if (!base_name) {
4953 return NT_STATUS_NO_MEMORY;
4955 p = strrchr_m(base_name, '/');
4956 if (p) {
4957 p[1] = '\0';
4958 } else {
4959 base_name = talloc_strdup(ctx, "./");
4960 if (!base_name) {
4961 return NT_STATUS_NO_MEMORY;
4964 /* Append the new name. */
4965 base_name = talloc_asprintf_append(base_name,
4966 "%s",
4967 newname);
4968 if (!base_name) {
4969 return NT_STATUS_NO_MEMORY;
4972 if (fsp) {
4973 SMB_STRUCT_STAT sbuf;
4974 char *newname_last_component = NULL;
4976 ZERO_STRUCT(sbuf);
4978 status = unix_convert(ctx, conn, newname, False,
4979 &newname,
4980 &newname_last_component,
4981 &sbuf);
4983 /* If an error we expect this to be
4984 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
4986 if (!NT_STATUS_IS_OK(status)
4987 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
4988 status)) {
4989 return status;
4992 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4993 fsp->fnum, fsp->fsp_name, base_name ));
4994 status = rename_internals_fsp(conn, fsp, base_name,
4995 newname_last_component, 0,
4996 overwrite);
4997 } else {
4998 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4999 fname, base_name ));
5000 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5001 overwrite, False, dest_has_wcard);
5004 return status;
5007 /****************************************************************************
5008 Deal with SMB_SET_POSIX_ACL.
5009 ****************************************************************************/
5011 #if defined(HAVE_POSIX_ACLS)
5012 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5013 const char *pdata,
5014 int total_data,
5015 files_struct *fsp,
5016 const char *fname,
5017 SMB_STRUCT_STAT *psbuf)
5019 uint16 posix_acl_version;
5020 uint16 num_file_acls;
5021 uint16 num_def_acls;
5022 BOOL valid_file_acls = True;
5023 BOOL valid_def_acls = True;
5025 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5026 return NT_STATUS_INVALID_PARAMETER;
5028 posix_acl_version = SVAL(pdata,0);
5029 num_file_acls = SVAL(pdata,2);
5030 num_def_acls = SVAL(pdata,4);
5032 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5033 valid_file_acls = False;
5034 num_file_acls = 0;
5037 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5038 valid_def_acls = False;
5039 num_def_acls = 0;
5042 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5043 return NT_STATUS_INVALID_PARAMETER;
5046 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5047 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5048 return NT_STATUS_INVALID_PARAMETER;
5051 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5052 fname ? fname : fsp->fsp_name,
5053 (unsigned int)num_file_acls,
5054 (unsigned int)num_def_acls));
5056 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5057 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5058 return map_nt_error_from_unix(errno);
5061 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5062 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5063 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5064 return map_nt_error_from_unix(errno);
5066 return NT_STATUS_OK;
5068 #endif
5070 /****************************************************************************
5071 Deal with SMB_SET_POSIX_LOCK.
5072 ****************************************************************************/
5074 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5075 const uint8 *inbuf,
5076 int length,
5077 const char *pdata,
5078 int total_data,
5079 files_struct *fsp)
5081 SMB_BIG_UINT count;
5082 SMB_BIG_UINT offset;
5083 uint32 lock_pid;
5084 BOOL blocking_lock = False;
5085 enum brl_type lock_type;
5086 NTSTATUS status = NT_STATUS_OK;
5088 if (fsp == NULL || fsp->fh->fd == -1) {
5089 return NT_STATUS_INVALID_HANDLE;
5092 if (total_data != POSIX_LOCK_DATA_SIZE) {
5093 return NT_STATUS_INVALID_PARAMETER;
5096 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5097 case POSIX_LOCK_TYPE_READ:
5098 lock_type = READ_LOCK;
5099 break;
5100 case POSIX_LOCK_TYPE_WRITE:
5101 /* Return the right POSIX-mappable error code for files opened read-only. */
5102 if (!fsp->can_write) {
5103 return NT_STATUS_INVALID_HANDLE;
5105 lock_type = WRITE_LOCK;
5106 break;
5107 case POSIX_LOCK_TYPE_UNLOCK:
5108 lock_type = UNLOCK_LOCK;
5109 break;
5110 default:
5111 return NT_STATUS_INVALID_PARAMETER;
5114 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5115 blocking_lock = False;
5116 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5117 blocking_lock = True;
5118 } else {
5119 return NT_STATUS_INVALID_PARAMETER;
5122 if (!lp_blocking_locks(SNUM(conn))) {
5123 blocking_lock = False;
5126 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5127 #if defined(HAVE_LONGLONG)
5128 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5129 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5130 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5131 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5132 #else /* HAVE_LONGLONG */
5133 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5134 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5135 #endif /* HAVE_LONGLONG */
5137 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5138 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5139 fsp->fsp_name,
5140 (unsigned int)lock_type,
5141 (unsigned int)lock_pid,
5142 (double)count,
5143 (double)offset ));
5145 if (lock_type == UNLOCK_LOCK) {
5146 status = do_unlock(smbd_messaging_context(),
5147 fsp,
5148 lock_pid,
5149 count,
5150 offset,
5151 POSIX_LOCK);
5152 } else {
5153 uint32 block_smbpid;
5155 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5156 fsp,
5157 lock_pid,
5158 count,
5159 offset,
5160 lock_type,
5161 POSIX_LOCK,
5162 blocking_lock,
5163 &status,
5164 &block_smbpid);
5166 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5168 * A blocking lock was requested. Package up
5169 * this smb into a queued request and push it
5170 * onto the blocking lock queue.
5172 if(push_blocking_lock_request(br_lck,
5173 (char *)inbuf, length,
5174 fsp,
5175 -1, /* infinite timeout. */
5177 lock_pid,
5178 lock_type,
5179 POSIX_LOCK,
5180 offset,
5181 count,
5182 block_smbpid)) {
5183 TALLOC_FREE(br_lck);
5184 return status;
5187 TALLOC_FREE(br_lck);
5190 return status;
5193 /****************************************************************************
5194 Deal with SMB_INFO_STANDARD.
5195 ****************************************************************************/
5197 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5198 const char *pdata,
5199 int total_data,
5200 files_struct *fsp,
5201 const char *fname,
5202 const SMB_STRUCT_STAT *psbuf)
5204 struct timespec ts[2];
5206 if (total_data < 12) {
5207 return NT_STATUS_INVALID_PARAMETER;
5210 /* access time */
5211 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5212 /* write time */
5213 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5215 DEBUG(10,("smb_set_info_standard: file %s\n",
5216 fname ? fname : fsp->fsp_name ));
5218 return smb_set_file_time(conn,
5219 fsp,
5220 fname,
5221 psbuf,
5222 ts);
5225 /****************************************************************************
5226 Deal with SMB_SET_FILE_BASIC_INFO.
5227 ****************************************************************************/
5229 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5230 const char *pdata,
5231 int total_data,
5232 files_struct *fsp,
5233 const char *fname,
5234 SMB_STRUCT_STAT *psbuf)
5236 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5237 struct timespec write_time;
5238 struct timespec changed_time;
5239 uint32 dosmode = 0;
5240 struct timespec ts[2];
5241 NTSTATUS status = NT_STATUS_OK;
5243 if (total_data < 36) {
5244 return NT_STATUS_INVALID_PARAMETER;
5247 /* Set the attributes */
5248 dosmode = IVAL(pdata,32);
5249 status = smb_set_file_dosmode(conn,
5250 fname,
5251 psbuf,
5252 dosmode);
5253 if (!NT_STATUS_IS_OK(status)) {
5254 return status;
5257 /* Ignore create time at offset pdata. */
5259 /* access time */
5260 ts[0] = interpret_long_date(pdata+8);
5262 write_time = interpret_long_date(pdata+16);
5263 changed_time = interpret_long_date(pdata+24);
5265 /* mtime */
5266 ts[1] = timespec_min(&write_time, &changed_time);
5268 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5269 ts[1] = write_time;
5272 /* Prefer a defined time to an undefined one. */
5273 if (null_timespec(ts[1])) {
5274 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5277 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5278 fname ? fname : fsp->fsp_name ));
5280 return smb_set_file_time(conn,
5281 fsp,
5282 fname,
5283 psbuf,
5284 ts);
5287 /****************************************************************************
5288 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5289 ****************************************************************************/
5291 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5292 struct smb_request *req,
5293 const char *pdata,
5294 int total_data,
5295 files_struct *fsp,
5296 const char *fname,
5297 SMB_STRUCT_STAT *psbuf)
5299 SMB_BIG_UINT allocation_size = 0;
5300 NTSTATUS status = NT_STATUS_OK;
5301 files_struct *new_fsp = NULL;
5303 if (!VALID_STAT(*psbuf)) {
5304 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5307 if (total_data < 8) {
5308 return NT_STATUS_INVALID_PARAMETER;
5311 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5312 #ifdef LARGE_SMB_OFF_T
5313 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5314 #else /* LARGE_SMB_OFF_T */
5315 if (IVAL(pdata,4) != 0) {
5316 /* more than 32 bits? */
5317 return NT_STATUS_INVALID_PARAMETER;
5319 #endif /* LARGE_SMB_OFF_T */
5321 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5322 fname, (double)allocation_size ));
5324 if (allocation_size) {
5325 allocation_size = smb_roundup(conn, allocation_size);
5328 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5329 fname, (double)allocation_size ));
5331 if (fsp && fsp->fh->fd != -1) {
5332 /* Open file handle. */
5333 /* Only change if needed. */
5334 if (allocation_size != get_file_size(*psbuf)) {
5335 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5336 return map_nt_error_from_unix(errno);
5339 /* But always update the time. */
5340 if (null_timespec(fsp->pending_modtime)) {
5342 * This is equivalent to a write. Ensure it's seen immediately
5343 * if there are no pending writes.
5345 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5347 return NT_STATUS_OK;
5350 /* Pathname or stat or directory file. */
5352 status = open_file_ntcreate(conn, req, fname, psbuf,
5353 FILE_WRITE_DATA,
5354 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5355 FILE_OPEN,
5357 FILE_ATTRIBUTE_NORMAL,
5358 FORCE_OPLOCK_BREAK_TO_NONE,
5359 NULL, &new_fsp);
5361 if (!NT_STATUS_IS_OK(status)) {
5362 /* NB. We check for open_was_deferred in the caller. */
5363 return status;
5366 /* Only change if needed. */
5367 if (allocation_size != get_file_size(*psbuf)) {
5368 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5369 status = map_nt_error_from_unix(errno);
5370 close_file(new_fsp,NORMAL_CLOSE);
5371 return status;
5375 /* Changing the allocation size should set the last mod time. */
5376 /* Don't need to call set_filetime as this will be flushed on
5377 * close. */
5379 fsp_set_pending_modtime(new_fsp, timespec_current());
5381 close_file(new_fsp,NORMAL_CLOSE);
5382 return NT_STATUS_OK;
5385 /****************************************************************************
5386 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5387 ****************************************************************************/
5389 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5390 struct smb_request *req,
5391 const char *pdata,
5392 int total_data,
5393 files_struct *fsp,
5394 const char *fname,
5395 SMB_STRUCT_STAT *psbuf)
5397 SMB_OFF_T size;
5399 if (total_data < 8) {
5400 return NT_STATUS_INVALID_PARAMETER;
5403 size = IVAL(pdata,0);
5404 #ifdef LARGE_SMB_OFF_T
5405 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5406 #else /* LARGE_SMB_OFF_T */
5407 if (IVAL(pdata,4) != 0) {
5408 /* more than 32 bits? */
5409 return NT_STATUS_INVALID_PARAMETER;
5411 #endif /* LARGE_SMB_OFF_T */
5412 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5413 "file %s to %.0f\n", fname, (double)size ));
5415 return smb_set_file_size(conn, req,
5416 fsp,
5417 fname,
5418 psbuf,
5419 size);
5422 /****************************************************************************
5423 Allow a UNIX info mknod.
5424 ****************************************************************************/
5426 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5427 const char *pdata,
5428 int total_data,
5429 const char *fname,
5430 SMB_STRUCT_STAT *psbuf)
5432 uint32 file_type = IVAL(pdata,56);
5433 #if defined(HAVE_MAKEDEV)
5434 uint32 dev_major = IVAL(pdata,60);
5435 uint32 dev_minor = IVAL(pdata,68);
5436 #endif
5437 SMB_DEV_T dev = (SMB_DEV_T)0;
5438 uint32 raw_unixmode = IVAL(pdata,84);
5439 NTSTATUS status;
5440 mode_t unixmode;
5442 if (total_data < 100) {
5443 return NT_STATUS_INVALID_PARAMETER;
5446 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5447 if (!NT_STATUS_IS_OK(status)) {
5448 return status;
5451 #if defined(HAVE_MAKEDEV)
5452 dev = makedev(dev_major, dev_minor);
5453 #endif
5455 switch (file_type) {
5456 #if defined(S_IFIFO)
5457 case UNIX_TYPE_FIFO:
5458 unixmode |= S_IFIFO;
5459 break;
5460 #endif
5461 #if defined(S_IFSOCK)
5462 case UNIX_TYPE_SOCKET:
5463 unixmode |= S_IFSOCK;
5464 break;
5465 #endif
5466 #if defined(S_IFCHR)
5467 case UNIX_TYPE_CHARDEV:
5468 unixmode |= S_IFCHR;
5469 break;
5470 #endif
5471 #if defined(S_IFBLK)
5472 case UNIX_TYPE_BLKDEV:
5473 unixmode |= S_IFBLK;
5474 break;
5475 #endif
5476 default:
5477 return NT_STATUS_INVALID_PARAMETER;
5480 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5481 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5483 /* Ok - do the mknod. */
5484 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5485 return map_nt_error_from_unix(errno);
5488 /* If any of the other "set" calls fail we
5489 * don't want to end up with a half-constructed mknod.
5492 if (lp_inherit_perms(SNUM(conn))) {
5493 inherit_access_acl(
5494 conn, parent_dirname(fname),
5495 fname, unixmode);
5498 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5499 status = map_nt_error_from_unix(errno);
5500 SMB_VFS_UNLINK(conn,fname);
5501 return status;
5503 return NT_STATUS_OK;
5506 /****************************************************************************
5507 Deal with SMB_SET_FILE_UNIX_BASIC.
5508 ****************************************************************************/
5510 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5511 struct smb_request *req,
5512 const char *pdata,
5513 int total_data,
5514 files_struct *fsp,
5515 const char *fname,
5516 SMB_STRUCT_STAT *psbuf)
5518 struct timespec ts[2];
5519 uint32 raw_unixmode;
5520 mode_t unixmode;
5521 SMB_OFF_T size = 0;
5522 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5523 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5524 NTSTATUS status = NT_STATUS_OK;
5525 BOOL delete_on_fail = False;
5526 enum perm_type ptype;
5528 if (total_data < 100) {
5529 return NT_STATUS_INVALID_PARAMETER;
5532 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5533 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5534 size=IVAL(pdata,0); /* first 8 Bytes are size */
5535 #ifdef LARGE_SMB_OFF_T
5536 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5537 #else /* LARGE_SMB_OFF_T */
5538 if (IVAL(pdata,4) != 0) {
5539 /* more than 32 bits? */
5540 return NT_STATUS_INVALID_PARAMETER;
5542 #endif /* LARGE_SMB_OFF_T */
5545 ts[0] = interpret_long_date(pdata+24); /* access_time */
5546 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5547 set_owner = (uid_t)IVAL(pdata,40);
5548 set_grp = (gid_t)IVAL(pdata,48);
5549 raw_unixmode = IVAL(pdata,84);
5551 if (VALID_STAT(*psbuf)) {
5552 if (S_ISDIR(psbuf->st_mode)) {
5553 ptype = PERM_EXISTING_DIR;
5554 } else {
5555 ptype = PERM_EXISTING_FILE;
5557 } else {
5558 ptype = PERM_NEW_FILE;
5561 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5562 if (!NT_STATUS_IS_OK(status)) {
5563 return status;
5566 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5567 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5568 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5570 if (!VALID_STAT(*psbuf)) {
5572 * The only valid use of this is to create character and block
5573 * devices, and named pipes. This is deprecated (IMHO) and
5574 * a new info level should be used for mknod. JRA.
5577 status = smb_unix_mknod(conn,
5578 pdata,
5579 total_data,
5580 fname,
5581 psbuf);
5582 if (!NT_STATUS_IS_OK(status)) {
5583 return status;
5586 /* Ensure we don't try and change anything else. */
5587 raw_unixmode = SMB_MODE_NO_CHANGE;
5588 size = get_file_size(*psbuf);
5589 ts[0] = get_atimespec(psbuf);
5590 ts[1] = get_mtimespec(psbuf);
5592 * We continue here as we might want to change the
5593 * owner uid/gid.
5595 delete_on_fail = True;
5598 #if 1
5599 /* Horrible backwards compatibility hack as an old server bug
5600 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5601 * */
5603 if (!size) {
5604 size = get_file_size(*psbuf);
5606 #endif
5609 * Deal with the UNIX specific mode set.
5612 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5613 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5614 (unsigned int)unixmode, fname ));
5615 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5616 return map_nt_error_from_unix(errno);
5621 * Deal with the UNIX specific uid set.
5624 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5625 int ret;
5627 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5628 (unsigned int)set_owner, fname ));
5630 if (S_ISLNK(psbuf->st_mode)) {
5631 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5632 } else {
5633 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5636 if (ret != 0) {
5637 status = map_nt_error_from_unix(errno);
5638 if (delete_on_fail) {
5639 SMB_VFS_UNLINK(conn,fname);
5641 return status;
5646 * Deal with the UNIX specific gid set.
5649 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5650 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5651 (unsigned int)set_owner, fname ));
5652 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5653 status = map_nt_error_from_unix(errno);
5654 if (delete_on_fail) {
5655 SMB_VFS_UNLINK(conn,fname);
5657 return status;
5661 /* Deal with any size changes. */
5663 status = smb_set_file_size(conn, req,
5664 fsp,
5665 fname,
5666 psbuf,
5667 size);
5668 if (!NT_STATUS_IS_OK(status)) {
5669 return status;
5672 /* Deal with any time changes. */
5674 return smb_set_file_time(conn,
5675 fsp,
5676 fname,
5677 psbuf,
5678 ts);
5681 /****************************************************************************
5682 Deal with SMB_SET_FILE_UNIX_INFO2.
5683 ****************************************************************************/
5685 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5686 struct smb_request *req,
5687 const char *pdata,
5688 int total_data,
5689 files_struct *fsp,
5690 const char *fname,
5691 SMB_STRUCT_STAT *psbuf)
5693 NTSTATUS status;
5694 uint32 smb_fflags;
5695 uint32 smb_fmask;
5697 if (total_data < 116) {
5698 return NT_STATUS_INVALID_PARAMETER;
5701 /* Start by setting all the fields that are common between UNIX_BASIC
5702 * and UNIX_INFO2.
5704 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5705 fsp, fname, psbuf);
5706 if (!NT_STATUS_IS_OK(status)) {
5707 return status;
5710 smb_fflags = IVAL(pdata, 108);
5711 smb_fmask = IVAL(pdata, 112);
5713 /* NB: We should only attempt to alter the file flags if the client
5714 * sends a non-zero mask.
5716 if (smb_fmask != 0) {
5717 int stat_fflags = 0;
5719 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5720 &stat_fflags)) {
5721 /* Client asked to alter a flag we don't understand. */
5722 return NT_STATUS_INVALID_PARAMETER;
5725 if (fsp && fsp->fh->fd != -1) {
5726 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5727 return NT_STATUS_NOT_SUPPORTED;
5728 } else {
5729 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5730 return map_nt_error_from_unix(errno);
5735 /* XXX: need to add support for changing the create_time here. You
5736 * can do this for paths on Darwin with setattrlist(2). The right way
5737 * to hook this up is probably by extending the VFS utimes interface.
5740 return NT_STATUS_OK;
5743 /****************************************************************************
5744 Create a directory with POSIX semantics.
5745 ****************************************************************************/
5747 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5748 struct smb_request *req,
5749 char **ppdata,
5750 int total_data,
5751 const char *fname,
5752 SMB_STRUCT_STAT *psbuf,
5753 int *pdata_return_size)
5755 NTSTATUS status = NT_STATUS_OK;
5756 uint32 raw_unixmode = 0;
5757 uint32 mod_unixmode = 0;
5758 mode_t unixmode = (mode_t)0;
5759 files_struct *fsp = NULL;
5760 uint16 info_level_return = 0;
5761 int info;
5762 char *pdata = *ppdata;
5764 if (total_data < 18) {
5765 return NT_STATUS_INVALID_PARAMETER;
5768 raw_unixmode = IVAL(pdata,8);
5769 /* Next 4 bytes are not yet defined. */
5771 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5772 if (!NT_STATUS_IS_OK(status)) {
5773 return status;
5776 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5778 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5779 fname, (unsigned int)unixmode ));
5781 status = open_directory(conn, req,
5782 fname,
5783 psbuf,
5784 FILE_READ_ATTRIBUTES, /* Just a stat open */
5785 FILE_SHARE_NONE, /* Ignored for stat opens */
5786 FILE_CREATE,
5788 mod_unixmode,
5789 &info,
5790 &fsp);
5792 if (NT_STATUS_IS_OK(status)) {
5793 close_file(fsp, NORMAL_CLOSE);
5796 info_level_return = SVAL(pdata,16);
5798 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5799 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5800 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5801 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5802 } else {
5803 *pdata_return_size = 12;
5806 /* Realloc the data size */
5807 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5808 if (*ppdata == NULL) {
5809 *pdata_return_size = 0;
5810 return NT_STATUS_NO_MEMORY;
5812 pdata = *ppdata;
5814 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5815 SSVAL(pdata,2,0); /* No fnum. */
5816 SIVAL(pdata,4,info); /* Was directory created. */
5818 switch (info_level_return) {
5819 case SMB_QUERY_FILE_UNIX_BASIC:
5820 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5821 SSVAL(pdata,10,0); /* Padding. */
5822 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5823 break;
5824 case SMB_QUERY_FILE_UNIX_INFO2:
5825 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5826 SSVAL(pdata,10,0); /* Padding. */
5827 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5828 break;
5829 default:
5830 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5831 SSVAL(pdata,10,0); /* Padding. */
5832 break;
5835 return status;
5838 /****************************************************************************
5839 Open/Create a file with POSIX semantics.
5840 ****************************************************************************/
5842 static NTSTATUS smb_posix_open(connection_struct *conn,
5843 struct smb_request *req,
5844 char **ppdata,
5845 int total_data,
5846 const char *fname,
5847 SMB_STRUCT_STAT *psbuf,
5848 int *pdata_return_size)
5850 BOOL extended_oplock_granted = False;
5851 char *pdata = *ppdata;
5852 uint32 flags = 0;
5853 uint32 wire_open_mode = 0;
5854 uint32 raw_unixmode = 0;
5855 uint32 mod_unixmode = 0;
5856 uint32 create_disp = 0;
5857 uint32 access_mask = 0;
5858 uint32 create_options = 0;
5859 NTSTATUS status = NT_STATUS_OK;
5860 mode_t unixmode = (mode_t)0;
5861 files_struct *fsp = NULL;
5862 int oplock_request = 0;
5863 int info = 0;
5864 uint16 info_level_return = 0;
5866 if (total_data < 18) {
5867 return NT_STATUS_INVALID_PARAMETER;
5870 flags = IVAL(pdata,0);
5871 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5872 if (oplock_request) {
5873 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5876 wire_open_mode = IVAL(pdata,4);
5878 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5879 return smb_posix_mkdir(conn, req,
5880 ppdata,
5881 total_data,
5882 fname,
5883 psbuf,
5884 pdata_return_size);
5887 switch (wire_open_mode & SMB_ACCMODE) {
5888 case SMB_O_RDONLY:
5889 access_mask = FILE_READ_DATA;
5890 break;
5891 case SMB_O_WRONLY:
5892 access_mask = FILE_WRITE_DATA;
5893 break;
5894 case SMB_O_RDWR:
5895 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5896 break;
5897 default:
5898 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5899 (unsigned int)wire_open_mode ));
5900 return NT_STATUS_INVALID_PARAMETER;
5903 wire_open_mode &= ~SMB_ACCMODE;
5905 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5906 create_disp = FILE_CREATE;
5907 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5908 create_disp = FILE_OVERWRITE_IF;
5909 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5910 create_disp = FILE_OPEN_IF;
5911 } else {
5912 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5913 (unsigned int)wire_open_mode ));
5914 return NT_STATUS_INVALID_PARAMETER;
5917 raw_unixmode = IVAL(pdata,8);
5918 /* Next 4 bytes are not yet defined. */
5920 status = unix_perms_from_wire(conn,
5921 psbuf,
5922 raw_unixmode,
5923 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5924 &unixmode);
5926 if (!NT_STATUS_IS_OK(status)) {
5927 return status;
5930 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5932 if (wire_open_mode & SMB_O_SYNC) {
5933 create_options |= FILE_WRITE_THROUGH;
5935 if (wire_open_mode & SMB_O_APPEND) {
5936 access_mask |= FILE_APPEND_DATA;
5938 if (wire_open_mode & SMB_O_DIRECT) {
5939 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5942 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5943 fname,
5944 (unsigned int)wire_open_mode,
5945 (unsigned int)unixmode ));
5947 status = open_file_ntcreate(conn, req,
5948 fname,
5949 psbuf,
5950 access_mask,
5951 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5952 create_disp,
5953 0, /* no create options yet. */
5954 mod_unixmode,
5955 oplock_request,
5956 &info,
5957 &fsp);
5959 if (!NT_STATUS_IS_OK(status)) {
5960 return status;
5963 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5964 extended_oplock_granted = True;
5967 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5968 extended_oplock_granted = True;
5971 info_level_return = SVAL(pdata,16);
5973 /* Allocate the correct return size. */
5975 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5976 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5977 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5978 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5979 } else {
5980 *pdata_return_size = 12;
5983 /* Realloc the data size */
5984 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5985 if (*ppdata == NULL) {
5986 close_file(fsp,ERROR_CLOSE);
5987 *pdata_return_size = 0;
5988 return NT_STATUS_NO_MEMORY;
5990 pdata = *ppdata;
5992 if (extended_oplock_granted) {
5993 if (flags & REQUEST_BATCH_OPLOCK) {
5994 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5995 } else {
5996 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5998 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5999 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6000 } else {
6001 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6004 SSVAL(pdata,2,fsp->fnum);
6005 SIVAL(pdata,4,info); /* Was file created etc. */
6007 switch (info_level_return) {
6008 case SMB_QUERY_FILE_UNIX_BASIC:
6009 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6010 SSVAL(pdata,10,0); /* padding. */
6011 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6012 break;
6013 case SMB_QUERY_FILE_UNIX_INFO2:
6014 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6015 SSVAL(pdata,10,0); /* padding. */
6016 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6017 break;
6018 default:
6019 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6020 SSVAL(pdata,10,0); /* padding. */
6021 break;
6023 return NT_STATUS_OK;
6026 /****************************************************************************
6027 Delete a file with POSIX semantics.
6028 ****************************************************************************/
6030 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6031 struct smb_request *req,
6032 const char *pdata,
6033 int total_data,
6034 const char *fname,
6035 SMB_STRUCT_STAT *psbuf)
6037 NTSTATUS status = NT_STATUS_OK;
6038 files_struct *fsp = NULL;
6039 uint16 flags = 0;
6040 char del = 1;
6041 int info = 0;
6042 int i;
6043 struct share_mode_lock *lck = NULL;
6045 if (total_data < 2) {
6046 return NT_STATUS_INVALID_PARAMETER;
6049 flags = SVAL(pdata,0);
6051 if (!VALID_STAT(*psbuf)) {
6052 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6055 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6056 !VALID_STAT_OF_DIR(*psbuf)) {
6057 return NT_STATUS_NOT_A_DIRECTORY;
6060 DEBUG(10,("smb_posix_unlink: %s %s\n",
6061 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6062 fname));
6064 if (VALID_STAT_OF_DIR(*psbuf)) {
6065 status = open_directory(conn, req,
6066 fname,
6067 psbuf,
6068 DELETE_ACCESS,
6069 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6070 FILE_OPEN,
6072 FILE_FLAG_POSIX_SEMANTICS|0777,
6073 &info,
6074 &fsp);
6075 } else {
6077 status = open_file_ntcreate(conn, req,
6078 fname,
6079 psbuf,
6080 DELETE_ACCESS,
6081 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6082 FILE_OPEN,
6084 FILE_FLAG_POSIX_SEMANTICS|0777,
6085 0, /* No oplock, but break existing ones. */
6086 &info,
6087 &fsp);
6090 if (!NT_STATUS_IS_OK(status)) {
6091 return status;
6095 * Don't lie to client. If we can't really delete due to
6096 * non-POSIX opens return SHARING_VIOLATION.
6099 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6100 if (lck == NULL) {
6101 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6102 "lock for file %s\n", fsp->fsp_name));
6103 close_file(fsp, NORMAL_CLOSE);
6104 return NT_STATUS_INVALID_PARAMETER;
6108 * See if others still have the file open. If this is the case, then
6109 * don't delete. If all opens are POSIX delete we can set the delete
6110 * on close disposition.
6112 for (i=0; i<lck->num_share_modes; i++) {
6113 struct share_mode_entry *e = &lck->share_modes[i];
6114 if (is_valid_share_mode_entry(e)) {
6115 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6116 continue;
6118 /* Fail with sharing violation. */
6119 close_file(fsp, NORMAL_CLOSE);
6120 TALLOC_FREE(lck);
6121 return NT_STATUS_SHARING_VIOLATION;
6126 * Set the delete on close.
6128 status = smb_set_file_disposition_info(conn,
6129 &del,
6131 fsp,
6132 fname,
6133 psbuf);
6135 if (!NT_STATUS_IS_OK(status)) {
6136 close_file(fsp, NORMAL_CLOSE);
6137 TALLOC_FREE(lck);
6138 return status;
6140 TALLOC_FREE(lck);
6141 return close_file(fsp, NORMAL_CLOSE);
6144 /****************************************************************************
6145 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6146 ****************************************************************************/
6148 static void call_trans2setfilepathinfo(connection_struct *conn,
6149 struct smb_request *req,
6150 unsigned int tran_call,
6151 char **pparams, int total_params,
6152 char **ppdata, int total_data,
6153 unsigned int max_data_bytes)
6155 char *params = *pparams;
6156 char *pdata = *ppdata;
6157 uint16 info_level;
6158 SMB_STRUCT_STAT sbuf;
6159 char *fname = NULL;
6160 files_struct *fsp = NULL;
6161 NTSTATUS status = NT_STATUS_OK;
6162 int data_return_size = 0;
6163 TALLOC_CTX *ctx = talloc_tos();
6165 if (!params) {
6166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6167 return;
6170 ZERO_STRUCT(sbuf);
6172 if (tran_call == TRANSACT2_SETFILEINFO) {
6173 if (total_params < 4) {
6174 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6175 return;
6178 fsp = file_fsp(SVAL(params,0));
6179 /* Basic check for non-null fsp. */
6180 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6181 return;
6183 info_level = SVAL(params,2);
6185 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6186 if (!fname) {
6187 reply_nterror(req, NT_STATUS_NO_MEMORY);
6188 return;
6191 if(fsp->is_directory || fsp->fh->fd == -1) {
6193 * This is actually a SETFILEINFO on a directory
6194 * handle (returned from an NT SMB). NT5.0 seems
6195 * to do this call. JRA.
6197 if (INFO_LEVEL_IS_UNIX(info_level)) {
6198 /* Always do lstat for UNIX calls. */
6199 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6200 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6201 reply_unixerror(req,ERRDOS,ERRbadpath);
6202 return;
6204 } else {
6205 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6206 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6207 reply_unixerror(req,ERRDOS,ERRbadpath);
6208 return;
6211 } else if (fsp->print_file) {
6213 * Doing a DELETE_ON_CLOSE should cancel a print job.
6215 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6216 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6218 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6220 SSVAL(params,0,0);
6221 send_trans2_replies(req, params, 2,
6222 *ppdata, 0,
6223 max_data_bytes);
6224 return;
6225 } else {
6226 reply_unixerror(req, ERRDOS, ERRbadpath);
6227 return;
6229 } else {
6231 * Original code - this is an open file.
6233 if (!check_fsp(conn, req, fsp, &current_user)) {
6234 return;
6237 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6238 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6239 reply_unixerror(req, ERRDOS, ERRbadfid);
6240 return;
6243 } else {
6244 /* set path info */
6245 if (total_params < 7) {
6246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6247 return;
6250 info_level = SVAL(params,0);
6251 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6252 total_params - 6, STR_TERMINATE,
6253 &status);
6254 if (!NT_STATUS_IS_OK(status)) {
6255 reply_nterror(req, status);
6256 return;
6259 status = resolve_dfspath(ctx, conn,
6260 req->flags2 & FLAGS2_DFS_PATHNAMES,
6261 fname,
6262 &fname);
6263 if (!NT_STATUS_IS_OK(status)) {
6264 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6265 reply_botherror(req,
6266 NT_STATUS_PATH_NOT_COVERED,
6267 ERRSRV, ERRbadpath);
6268 return;
6270 reply_nterror(req, status);
6271 return;
6274 status = unix_convert(ctx, conn, fname, False,
6275 &fname, NULL, &sbuf);
6276 if (!NT_STATUS_IS_OK(status)) {
6277 reply_nterror(req, status);
6278 return;
6281 status = check_name(conn, fname);
6282 if (!NT_STATUS_IS_OK(status)) {
6283 reply_nterror(req, status);
6284 return;
6287 if (INFO_LEVEL_IS_UNIX(info_level)) {
6289 * For CIFS UNIX extensions the target name may not exist.
6292 /* Always do lstat for UNIX calls. */
6293 SMB_VFS_LSTAT(conn,fname,&sbuf);
6295 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6296 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6297 reply_unixerror(req, ERRDOS, ERRbadpath);
6298 return;
6302 if (!CAN_WRITE(conn)) {
6303 reply_doserror(req, ERRSRV, ERRaccess);
6304 return;
6307 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6308 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6309 return;
6312 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6313 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6315 /* Realloc the parameter size */
6316 *pparams = (char *)SMB_REALLOC(*pparams,2);
6317 if (*pparams == NULL) {
6318 reply_nterror(req, NT_STATUS_NO_MEMORY);
6319 return;
6321 params = *pparams;
6323 SSVAL(params,0,0);
6325 if (fsp && !null_timespec(fsp->pending_modtime)) {
6326 /* the pending modtime overrides the current modtime */
6327 set_mtimespec(&sbuf, fsp->pending_modtime);
6330 switch (info_level) {
6332 case SMB_INFO_STANDARD:
6334 status = smb_set_info_standard(conn,
6335 pdata,
6336 total_data,
6337 fsp,
6338 fname,
6339 &sbuf);
6340 break;
6343 case SMB_INFO_SET_EA:
6345 status = smb_info_set_ea(conn,
6346 pdata,
6347 total_data,
6348 fsp,
6349 fname);
6350 break;
6353 case SMB_SET_FILE_BASIC_INFO:
6354 case SMB_FILE_BASIC_INFORMATION:
6356 status = smb_set_file_basic_info(conn,
6357 pdata,
6358 total_data,
6359 fsp,
6360 fname,
6361 &sbuf);
6362 break;
6365 case SMB_FILE_ALLOCATION_INFORMATION:
6366 case SMB_SET_FILE_ALLOCATION_INFO:
6368 status = smb_set_file_allocation_info(conn, req,
6369 pdata,
6370 total_data,
6371 fsp,
6372 fname,
6373 &sbuf);
6374 break;
6377 case SMB_FILE_END_OF_FILE_INFORMATION:
6378 case SMB_SET_FILE_END_OF_FILE_INFO:
6380 status = smb_set_file_end_of_file_info(conn, req,
6381 pdata,
6382 total_data,
6383 fsp,
6384 fname,
6385 &sbuf);
6386 break;
6389 case SMB_FILE_DISPOSITION_INFORMATION:
6390 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6392 #if 0
6393 /* JRA - We used to just ignore this on a path ?
6394 * Shouldn't this be invalid level on a pathname
6395 * based call ?
6397 if (tran_call != TRANSACT2_SETFILEINFO) {
6398 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6400 #endif
6401 status = smb_set_file_disposition_info(conn,
6402 pdata,
6403 total_data,
6404 fsp,
6405 fname,
6406 &sbuf);
6407 break;
6410 case SMB_FILE_POSITION_INFORMATION:
6412 status = smb_file_position_information(conn,
6413 pdata,
6414 total_data,
6415 fsp);
6416 break;
6419 /* From tridge Samba4 :
6420 * MODE_INFORMATION in setfileinfo (I have no
6421 * idea what "mode information" on a file is - it takes a value of 0,
6422 * 2, 4 or 6. What could it be?).
6425 case SMB_FILE_MODE_INFORMATION:
6427 status = smb_file_mode_information(conn,
6428 pdata,
6429 total_data);
6430 break;
6434 * CIFS UNIX extensions.
6437 case SMB_SET_FILE_UNIX_BASIC:
6439 status = smb_set_file_unix_basic(conn, req,
6440 pdata,
6441 total_data,
6442 fsp,
6443 fname,
6444 &sbuf);
6445 break;
6448 case SMB_SET_FILE_UNIX_INFO2:
6450 status = smb_set_file_unix_info2(conn, req,
6451 pdata,
6452 total_data,
6453 fsp,
6454 fname,
6455 &sbuf);
6456 break;
6459 case SMB_SET_FILE_UNIX_LINK:
6461 if (tran_call != TRANSACT2_SETPATHINFO) {
6462 /* We must have a pathname for this. */
6463 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6464 return;
6466 status = smb_set_file_unix_link(conn, req, pdata,
6467 total_data, fname);
6468 break;
6471 case SMB_SET_FILE_UNIX_HLINK:
6473 if (tran_call != TRANSACT2_SETPATHINFO) {
6474 /* We must have a pathname for this. */
6475 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6476 return;
6478 status = smb_set_file_unix_hlink(conn, req,
6479 pdata, total_data,
6480 fname);
6481 break;
6484 case SMB_FILE_RENAME_INFORMATION:
6486 status = smb_file_rename_information(conn, req,
6487 pdata, total_data,
6488 fsp, fname);
6489 break;
6492 #if defined(HAVE_POSIX_ACLS)
6493 case SMB_SET_POSIX_ACL:
6495 status = smb_set_posix_acl(conn,
6496 pdata,
6497 total_data,
6498 fsp,
6499 fname,
6500 &sbuf);
6501 break;
6503 #endif
6505 case SMB_SET_POSIX_LOCK:
6507 if (tran_call != TRANSACT2_SETFILEINFO) {
6508 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6509 return;
6511 status = smb_set_posix_lock(conn, req->inbuf,
6512 smb_len(req->inbuf) + 4,
6513 pdata, total_data, fsp);
6514 break;
6517 case SMB_POSIX_PATH_OPEN:
6519 if (tran_call != TRANSACT2_SETPATHINFO) {
6520 /* We must have a pathname for this. */
6521 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6522 return;
6525 status = smb_posix_open(conn, req,
6526 ppdata,
6527 total_data,
6528 fname,
6529 &sbuf,
6530 &data_return_size);
6531 break;
6534 case SMB_POSIX_PATH_UNLINK:
6536 if (tran_call != TRANSACT2_SETPATHINFO) {
6537 /* We must have a pathname for this. */
6538 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6539 return;
6542 status = smb_posix_unlink(conn, req,
6543 pdata,
6544 total_data,
6545 fname,
6546 &sbuf);
6547 break;
6550 default:
6551 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6552 return;
6556 if (!NT_STATUS_IS_OK(status)) {
6557 if (open_was_deferred(req->mid)) {
6558 /* We have re-scheduled this call. */
6559 return;
6561 if (blocking_lock_was_deferred(req->mid)) {
6562 /* We have re-scheduled this call. */
6563 return;
6565 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6566 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6567 ERRSRV, ERRbadpath);
6568 return;
6570 if (info_level == SMB_POSIX_PATH_OPEN) {
6571 reply_openerror(req, status);
6572 return;
6575 reply_nterror(req, status);
6576 return;
6579 SSVAL(params,0,0);
6580 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6581 max_data_bytes);
6583 return;
6586 /****************************************************************************
6587 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6588 ****************************************************************************/
6590 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6591 char **pparams, int total_params,
6592 char **ppdata, int total_data,
6593 unsigned int max_data_bytes)
6595 char *params = *pparams;
6596 char *pdata = *ppdata;
6597 char *directory = NULL;
6598 SMB_STRUCT_STAT sbuf;
6599 NTSTATUS status = NT_STATUS_OK;
6600 struct ea_list *ea_list = NULL;
6601 TALLOC_CTX *ctx = talloc_tos();
6603 if (!CAN_WRITE(conn)) {
6604 reply_doserror(req, ERRSRV, ERRaccess);
6605 return;
6608 if (total_params < 5) {
6609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6610 return;
6613 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
6614 total_params - 4, STR_TERMINATE,
6615 &status);
6616 if (!NT_STATUS_IS_OK(status)) {
6617 reply_nterror(req, status);
6618 return;
6621 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6623 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6624 if (!NT_STATUS_IS_OK(status)) {
6625 reply_nterror(req, status);
6626 return;
6629 status = check_name(conn, directory);
6630 if (!NT_STATUS_IS_OK(status)) {
6631 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6632 reply_nterror(req, status);
6633 return;
6636 /* Any data in this call is an EA list. */
6637 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6638 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6639 return;
6643 * OS/2 workplace shell seems to send SET_EA requests of "null"
6644 * length (4 bytes containing IVAL 4).
6645 * They seem to have no effect. Bug #3212. JRA.
6648 if (total_data != 4) {
6649 if (total_data < 10) {
6650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6651 return;
6654 if (IVAL(pdata,0) > total_data) {
6655 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6656 IVAL(pdata,0), (unsigned int)total_data));
6657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6658 return;
6661 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6662 total_data - 4);
6663 if (!ea_list) {
6664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6665 return;
6667 } else if (IVAL(pdata,0) != 4) {
6668 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6669 return;
6672 status = create_directory(conn, directory);
6674 if (!NT_STATUS_IS_OK(status)) {
6675 reply_nterror(req, status);
6676 return;
6679 /* Try and set any given EA. */
6680 if (ea_list) {
6681 status = set_ea(conn, NULL, directory, ea_list);
6682 if (!NT_STATUS_IS_OK(status)) {
6683 reply_nterror(req, status);
6684 return;
6688 /* Realloc the parameter and data sizes */
6689 *pparams = (char *)SMB_REALLOC(*pparams,2);
6690 if(*pparams == NULL) {
6691 reply_nterror(req, NT_STATUS_NO_MEMORY);
6692 return;
6694 params = *pparams;
6696 SSVAL(params,0,0);
6698 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6700 return;
6703 /****************************************************************************
6704 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6705 We don't actually do this - we just send a null response.
6706 ****************************************************************************/
6708 static void call_trans2findnotifyfirst(connection_struct *conn,
6709 struct smb_request *req,
6710 char **pparams, int total_params,
6711 char **ppdata, int total_data,
6712 unsigned int max_data_bytes)
6714 static uint16 fnf_handle = 257;
6715 char *params = *pparams;
6716 uint16 info_level;
6718 if (total_params < 6) {
6719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6720 return;
6723 info_level = SVAL(params,4);
6724 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6726 switch (info_level) {
6727 case 1:
6728 case 2:
6729 break;
6730 default:
6731 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6732 return;
6735 /* Realloc the parameter and data sizes */
6736 *pparams = (char *)SMB_REALLOC(*pparams,6);
6737 if (*pparams == NULL) {
6738 reply_nterror(req, NT_STATUS_NO_MEMORY);
6739 return;
6741 params = *pparams;
6743 SSVAL(params,0,fnf_handle);
6744 SSVAL(params,2,0); /* No changes */
6745 SSVAL(params,4,0); /* No EA errors */
6747 fnf_handle++;
6749 if(fnf_handle == 0)
6750 fnf_handle = 257;
6752 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6754 return;
6757 /****************************************************************************
6758 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6759 changes). Currently this does nothing.
6760 ****************************************************************************/
6762 static void call_trans2findnotifynext(connection_struct *conn,
6763 struct smb_request *req,
6764 char **pparams, int total_params,
6765 char **ppdata, int total_data,
6766 unsigned int max_data_bytes)
6768 char *params = *pparams;
6770 DEBUG(3,("call_trans2findnotifynext\n"));
6772 /* Realloc the parameter and data sizes */
6773 *pparams = (char *)SMB_REALLOC(*pparams,4);
6774 if (*pparams == NULL) {
6775 reply_nterror(req, NT_STATUS_NO_MEMORY);
6776 return;
6778 params = *pparams;
6780 SSVAL(params,0,0); /* No changes */
6781 SSVAL(params,2,0); /* No EA errors */
6783 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6785 return;
6788 /****************************************************************************
6789 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6790 ****************************************************************************/
6792 static void call_trans2getdfsreferral(connection_struct *conn,
6793 struct smb_request *req,
6794 char **pparams, int total_params,
6795 char **ppdata, int total_data,
6796 unsigned int max_data_bytes)
6798 char *params = *pparams;
6799 char *pathname = NULL;
6800 int reply_size = 0;
6801 int max_referral_level;
6802 NTSTATUS status = NT_STATUS_OK;
6803 TALLOC_CTX *ctx = talloc_tos();
6805 DEBUG(10,("call_trans2getdfsreferral\n"));
6807 if (total_params < 3) {
6808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6809 return;
6812 max_referral_level = SVAL(params,0);
6814 if(!lp_host_msdfs()) {
6815 reply_doserror(req, ERRDOS, ERRbadfunc);
6816 return;
6819 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
6820 total_params - 2, STR_TERMINATE);
6821 if (!pathname) {
6822 reply_nterror(req, NT_STATUS_NOT_FOUND);
6823 return;
6825 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6826 ppdata,&status)) < 0) {
6827 reply_nterror(req, status);
6828 return;
6831 SSVAL(req->inbuf, smb_flg2,
6832 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6833 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6835 return;
6838 #define LMCAT_SPL 0x53
6839 #define LMFUNC_GETJOBID 0x60
6841 /****************************************************************************
6842 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6843 ****************************************************************************/
6845 static void call_trans2ioctl(connection_struct *conn,
6846 struct smb_request *req,
6847 char **pparams, int total_params,
6848 char **ppdata, int total_data,
6849 unsigned int max_data_bytes)
6851 char *pdata = *ppdata;
6852 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6854 /* check for an invalid fid before proceeding */
6856 if (!fsp) {
6857 reply_doserror(req, ERRDOS, ERRbadfid);
6858 return;
6861 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6862 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6863 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6864 if (*ppdata == NULL) {
6865 reply_nterror(req, NT_STATUS_NO_MEMORY);
6866 return;
6868 pdata = *ppdata;
6870 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6871 CAN ACCEPT THIS IN UNICODE. JRA. */
6873 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6874 srvstr_push(pdata, req->flags2, pdata + 2,
6875 global_myname(), 15,
6876 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6877 srvstr_push(pdata, req->flags2, pdata+18,
6878 lp_servicename(SNUM(conn)), 13,
6879 STR_ASCII|STR_TERMINATE); /* Service name */
6880 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6881 max_data_bytes);
6882 return;
6885 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6886 reply_doserror(req, ERRSRV, ERRerror);
6889 /****************************************************************************
6890 Reply to a SMBfindclose (stop trans2 directory search).
6891 ****************************************************************************/
6893 void reply_findclose(connection_struct *conn, struct smb_request *req)
6895 int dptr_num;
6897 START_PROFILE(SMBfindclose);
6899 if (req->wct < 1) {
6900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6901 END_PROFILE(SMBfindclose);
6902 return;
6905 dptr_num = SVALS(req->inbuf,smb_vwv0);
6907 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6909 dptr_close(&dptr_num);
6911 reply_outbuf(req, 0, 0);
6913 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6915 END_PROFILE(SMBfindclose);
6916 return;
6919 /****************************************************************************
6920 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6921 ****************************************************************************/
6923 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6925 int dptr_num;
6927 START_PROFILE(SMBfindnclose);
6929 if (req->wct < 1) {
6930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6931 END_PROFILE(SMBfindnclose);
6932 return;
6935 dptr_num = SVAL(req->inbuf,smb_vwv0);
6937 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6939 /* We never give out valid handles for a
6940 findnotifyfirst - so any dptr_num is ok here.
6941 Just ignore it. */
6943 reply_outbuf(req, 0, 0);
6945 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6947 END_PROFILE(SMBfindnclose);
6948 return;
6951 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6952 struct trans_state *state)
6954 if (Protocol >= PROTOCOL_NT1) {
6955 req->flags2 |= 0x40; /* IS_LONG_NAME */
6956 SSVAL(req->inbuf,smb_flg2,req->flags2);
6959 /* Now we must call the relevant TRANS2 function */
6960 switch(state->call) {
6961 case TRANSACT2_OPEN:
6963 START_PROFILE(Trans2_open);
6964 call_trans2open(conn, req,
6965 &state->param, state->total_param,
6966 &state->data, state->total_data,
6967 state->max_data_return);
6968 END_PROFILE(Trans2_open);
6969 break;
6972 case TRANSACT2_FINDFIRST:
6974 START_PROFILE(Trans2_findfirst);
6975 call_trans2findfirst(conn, req,
6976 &state->param, state->total_param,
6977 &state->data, state->total_data,
6978 state->max_data_return);
6979 END_PROFILE(Trans2_findfirst);
6980 break;
6983 case TRANSACT2_FINDNEXT:
6985 START_PROFILE(Trans2_findnext);
6986 call_trans2findnext(conn, req,
6987 &state->param, state->total_param,
6988 &state->data, state->total_data,
6989 state->max_data_return);
6990 END_PROFILE(Trans2_findnext);
6991 break;
6994 case TRANSACT2_QFSINFO:
6996 START_PROFILE(Trans2_qfsinfo);
6997 call_trans2qfsinfo(conn, req,
6998 &state->param, state->total_param,
6999 &state->data, state->total_data,
7000 state->max_data_return);
7001 END_PROFILE(Trans2_qfsinfo);
7002 break;
7005 case TRANSACT2_SETFSINFO:
7007 START_PROFILE(Trans2_setfsinfo);
7008 call_trans2setfsinfo(conn, req,
7009 &state->param, state->total_param,
7010 &state->data, state->total_data,
7011 state->max_data_return);
7012 END_PROFILE(Trans2_setfsinfo);
7013 break;
7016 case TRANSACT2_QPATHINFO:
7017 case TRANSACT2_QFILEINFO:
7019 START_PROFILE(Trans2_qpathinfo);
7020 call_trans2qfilepathinfo(conn, req, state->call,
7021 &state->param, state->total_param,
7022 &state->data, state->total_data,
7023 state->max_data_return);
7024 END_PROFILE(Trans2_qpathinfo);
7025 break;
7028 case TRANSACT2_SETPATHINFO:
7029 case TRANSACT2_SETFILEINFO:
7031 START_PROFILE(Trans2_setpathinfo);
7032 call_trans2setfilepathinfo(conn, req, state->call,
7033 &state->param, state->total_param,
7034 &state->data, state->total_data,
7035 state->max_data_return);
7036 END_PROFILE(Trans2_setpathinfo);
7037 break;
7040 case TRANSACT2_FINDNOTIFYFIRST:
7042 START_PROFILE(Trans2_findnotifyfirst);
7043 call_trans2findnotifyfirst(conn, req,
7044 &state->param, state->total_param,
7045 &state->data, state->total_data,
7046 state->max_data_return);
7047 END_PROFILE(Trans2_findnotifyfirst);
7048 break;
7051 case TRANSACT2_FINDNOTIFYNEXT:
7053 START_PROFILE(Trans2_findnotifynext);
7054 call_trans2findnotifynext(conn, req,
7055 &state->param, state->total_param,
7056 &state->data, state->total_data,
7057 state->max_data_return);
7058 END_PROFILE(Trans2_findnotifynext);
7059 break;
7062 case TRANSACT2_MKDIR:
7064 START_PROFILE(Trans2_mkdir);
7065 call_trans2mkdir(conn, req,
7066 &state->param, state->total_param,
7067 &state->data, state->total_data,
7068 state->max_data_return);
7069 END_PROFILE(Trans2_mkdir);
7070 break;
7073 case TRANSACT2_GET_DFS_REFERRAL:
7075 START_PROFILE(Trans2_get_dfs_referral);
7076 call_trans2getdfsreferral(conn, req,
7077 &state->param, state->total_param,
7078 &state->data, state->total_data,
7079 state->max_data_return);
7080 END_PROFILE(Trans2_get_dfs_referral);
7081 break;
7084 case TRANSACT2_IOCTL:
7086 START_PROFILE(Trans2_ioctl);
7087 call_trans2ioctl(conn, req,
7088 &state->param, state->total_param,
7089 &state->data, state->total_data,
7090 state->max_data_return);
7091 END_PROFILE(Trans2_ioctl);
7092 break;
7095 default:
7096 /* Error in request */
7097 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7098 reply_doserror(req, ERRSRV,ERRerror);
7102 /****************************************************************************
7103 Reply to a SMBtrans2.
7104 ****************************************************************************/
7106 void reply_trans2(connection_struct *conn, struct smb_request *req)
7108 unsigned int dsoff;
7109 unsigned int dscnt;
7110 unsigned int psoff;
7111 unsigned int pscnt;
7112 unsigned int tran_call;
7113 int size;
7114 struct trans_state *state;
7115 NTSTATUS result;
7117 START_PROFILE(SMBtrans2);
7119 if (req->wct < 14) {
7120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7121 END_PROFILE(SMBtrans2);
7122 return;
7125 dsoff = SVAL(req->inbuf, smb_dsoff);
7126 dscnt = SVAL(req->inbuf, smb_dscnt);
7127 psoff = SVAL(req->inbuf, smb_psoff);
7128 pscnt = SVAL(req->inbuf, smb_pscnt);
7129 tran_call = SVAL(req->inbuf, smb_setup0);
7130 size = smb_len(req->inbuf) + 4;
7132 result = allow_new_trans(conn->pending_trans, req->mid);
7133 if (!NT_STATUS_IS_OK(result)) {
7134 DEBUG(2, ("Got invalid trans2 request: %s\n",
7135 nt_errstr(result)));
7136 reply_nterror(req, result);
7137 END_PROFILE(SMBtrans2);
7138 return;
7141 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7142 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7143 && (tran_call != TRANSACT2_QFILEINFO)) {
7144 reply_doserror(req, ERRSRV, ERRaccess);
7145 END_PROFILE(SMBtrans2);
7146 return;
7149 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7150 DEBUG(0, ("talloc failed\n"));
7151 reply_nterror(req, NT_STATUS_NO_MEMORY);
7152 END_PROFILE(SMBtrans2);
7153 return;
7156 state->cmd = SMBtrans2;
7158 state->mid = req->mid;
7159 state->vuid = req->vuid;
7160 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7161 state->setup = NULL;
7162 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7163 state->param = NULL;
7164 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7165 state->data = NULL;
7166 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7167 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7168 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7169 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7170 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7172 state->call = tran_call;
7174 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7175 is so as a sanity check */
7176 if (state->setup_count != 1) {
7178 * Need to have rc=0 for ioctl to get job id for OS/2.
7179 * Network printing will fail if function is not successful.
7180 * Similar function in reply.c will be used if protocol
7181 * is LANMAN1.0 instead of LM1.2X002.
7182 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7183 * outbuf doesn't have to be set(only job id is used).
7185 if ( (state->setup_count == 4)
7186 && (tran_call == TRANSACT2_IOCTL)
7187 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7188 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7189 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7190 } else {
7191 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7192 DEBUG(2,("Transaction is %d\n",tran_call));
7193 TALLOC_FREE(state);
7194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7195 END_PROFILE(SMBtrans2);
7196 return;
7200 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7201 goto bad_param;
7203 if (state->total_data) {
7204 /* Can't use talloc here, the core routines do realloc on the
7205 * params and data. */
7206 state->data = (char *)SMB_MALLOC(state->total_data);
7207 if (state->data == NULL) {
7208 DEBUG(0,("reply_trans2: data malloc fail for %u "
7209 "bytes !\n", (unsigned int)state->total_data));
7210 TALLOC_FREE(state);
7211 reply_nterror(req, NT_STATUS_NO_MEMORY);
7212 END_PROFILE(SMBtrans2);
7213 return;
7215 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7216 goto bad_param;
7217 if ((smb_base(req->inbuf)+dsoff+dscnt
7218 > (char *)req->inbuf + size) ||
7219 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7220 goto bad_param;
7222 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7225 if (state->total_param) {
7226 /* Can't use talloc here, the core routines do realloc on the
7227 * params and data. */
7228 state->param = (char *)SMB_MALLOC(state->total_param);
7229 if (state->param == NULL) {
7230 DEBUG(0,("reply_trans: param malloc fail for %u "
7231 "bytes !\n", (unsigned int)state->total_param));
7232 SAFE_FREE(state->data);
7233 TALLOC_FREE(state);
7234 reply_nterror(req, NT_STATUS_NO_MEMORY);
7235 END_PROFILE(SMBtrans2);
7236 return;
7238 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7239 goto bad_param;
7240 if ((smb_base(req->inbuf)+psoff+pscnt
7241 > (char *)req->inbuf + size) ||
7242 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7243 goto bad_param;
7245 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7248 state->received_data = dscnt;
7249 state->received_param = pscnt;
7251 if ((state->received_param == state->total_param) &&
7252 (state->received_data == state->total_data)) {
7254 handle_trans2(conn, req, state);
7256 SAFE_FREE(state->data);
7257 SAFE_FREE(state->param);
7258 TALLOC_FREE(state);
7259 END_PROFILE(SMBtrans2);
7260 return;
7263 DLIST_ADD(conn->pending_trans, state);
7265 /* We need to send an interim response then receive the rest
7266 of the parameter/data bytes */
7267 reply_outbuf(req, 0, 0);
7268 show_msg((char *)req->outbuf);
7269 END_PROFILE(SMBtrans2);
7270 return;
7272 bad_param:
7274 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7275 SAFE_FREE(state->data);
7276 SAFE_FREE(state->param);
7277 TALLOC_FREE(state);
7278 END_PROFILE(SMBtrans2);
7279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7283 /****************************************************************************
7284 Reply to a SMBtranss2
7285 ****************************************************************************/
7287 void reply_transs2(connection_struct *conn, struct smb_request *req)
7289 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7290 struct trans_state *state;
7291 int size;
7293 START_PROFILE(SMBtranss2);
7295 show_msg((char *)req->inbuf);
7297 if (req->wct < 8) {
7298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7299 END_PROFILE(SMBtranss2);
7300 return;
7303 size = smb_len(req->inbuf)+4;
7305 for (state = conn->pending_trans; state != NULL;
7306 state = state->next) {
7307 if (state->mid == req->mid) {
7308 break;
7312 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7314 END_PROFILE(SMBtranss2);
7315 return;
7318 /* Revise state->total_param and state->total_data in case they have
7319 changed downwards */
7321 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7322 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7323 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7324 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7326 pcnt = SVAL(req->inbuf, smb_spscnt);
7327 poff = SVAL(req->inbuf, smb_spsoff);
7328 pdisp = SVAL(req->inbuf, smb_spsdisp);
7330 dcnt = SVAL(req->inbuf, smb_sdscnt);
7331 doff = SVAL(req->inbuf, smb_sdsoff);
7332 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7334 state->received_param += pcnt;
7335 state->received_data += dcnt;
7337 if ((state->received_data > state->total_data) ||
7338 (state->received_param > state->total_param))
7339 goto bad_param;
7341 if (pcnt) {
7342 if (pdisp+pcnt > state->total_param)
7343 goto bad_param;
7344 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7345 goto bad_param;
7346 if (pdisp > state->total_param)
7347 goto bad_param;
7348 if ((smb_base(req->inbuf) + poff + pcnt
7349 > (char *)req->inbuf + size) ||
7350 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7351 goto bad_param;
7352 if (state->param + pdisp < state->param)
7353 goto bad_param;
7355 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7356 pcnt);
7359 if (dcnt) {
7360 if (ddisp+dcnt > state->total_data)
7361 goto bad_param;
7362 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7363 goto bad_param;
7364 if (ddisp > state->total_data)
7365 goto bad_param;
7366 if ((smb_base(req->inbuf) + doff + dcnt
7367 > (char *)req->inbuf + size) ||
7368 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7369 goto bad_param;
7370 if (state->data + ddisp < state->data)
7371 goto bad_param;
7373 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7374 dcnt);
7377 if ((state->received_param < state->total_param) ||
7378 (state->received_data < state->total_data)) {
7379 END_PROFILE(SMBtranss2);
7380 return;
7384 * construct_reply_common will copy smb_com from inbuf to
7385 * outbuf. SMBtranss2 is wrong here.
7387 SCVAL(req->inbuf,smb_com,SMBtrans2);
7389 handle_trans2(conn, req, state);
7391 DLIST_REMOVE(conn->pending_trans, state);
7392 SAFE_FREE(state->data);
7393 SAFE_FREE(state->param);
7394 TALLOC_FREE(state);
7396 END_PROFILE(SMBtranss2);
7397 return;
7399 bad_param:
7401 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7402 DLIST_REMOVE(conn->pending_trans, state);
7403 SAFE_FREE(state->data);
7404 SAFE_FREE(state->param);
7405 TALLOC_FREE(state);
7406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7407 END_PROFILE(SMBtranss2);
7408 return;