Remove is_remotestorage() call from VFS. We already have statvfs() there to handle...
[Samba/bjacke.git] / source / smbd / trans2.c
blob23d6f129969e34517efcebd732a8eb980610abcc
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 uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
37 char *pdata,
38 files_struct *fsp,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
42 char *pdata,
43 files_struct *fsp,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
60 return val;
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
65 account sparse files.
66 ********************************************************************/
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
70 SMB_BIG_UINT ret;
72 if(S_ISDIR(sbuf->st_mode)) {
73 return 0;
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
78 #else
79 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
80 #endif
82 if (fsp && fsp->initial_allocation_size)
83 ret = MAX(ret,fsp->initial_allocation_size);
85 return smb_roundup(conn, ret);
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name)
98 static const char *prohibited_ea_names[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME,
100 SAMBA_XATTR_DOS_ATTRIB,
101 NULL
104 int i;
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
108 return True;
110 return False;
113 /****************************************************************************
114 Get one EA value. Fill in a struct ea_struct.
115 ****************************************************************************/
117 static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
118 const char *fname, char *ea_name, struct ea_struct *pea)
120 /* Get the value of this xattr. Max size is 64k. */
121 size_t attr_size = 256;
122 char *val = NULL;
123 ssize_t sizeret;
125 again:
127 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
128 if (!val) {
129 return False;
132 if (fsp && fsp->fh->fd != -1) {
133 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
134 } else {
135 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
138 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
139 attr_size = 65536;
140 goto again;
143 if (sizeret == -1) {
144 return False;
147 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
148 dump_data(10, (uint8 *)val, sizeret);
150 pea->flags = 0;
151 if (strnequal(ea_name, "user.", 5)) {
152 pea->name = &ea_name[5];
153 } else {
154 pea->name = ea_name;
156 pea->value.data = (unsigned char *)val;
157 pea->value.length = (size_t)sizeret;
158 return True;
161 /****************************************************************************
162 Return a linked list of the total EA's. Plus the total size
163 ****************************************************************************/
165 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
166 const char *fname, size_t *pea_total_len)
168 /* Get a list of all xattrs. Max namesize is 64k. */
169 size_t ea_namelist_size = 1024;
170 char *ea_namelist;
171 char *p;
172 ssize_t sizeret;
173 int i;
174 struct ea_list *ea_list_head = NULL;
176 *pea_total_len = 0;
178 if (!lp_ea_support(SNUM(conn))) {
179 return NULL;
182 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
183 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
185 if (!ea_namelist) {
186 return NULL;
189 if (fsp && fsp->fh->fd != -1) {
190 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist, ea_namelist_size);
191 } else {
192 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
195 if (sizeret == -1 && errno == ERANGE) {
196 ea_namelist_size *= 2;
197 } else {
198 break;
202 if (sizeret == -1)
203 return NULL;
205 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
207 if (sizeret) {
208 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
209 struct ea_list *listp;
211 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
212 continue;
214 listp = TALLOC_P(mem_ctx, struct ea_list);
215 if (!listp)
216 return NULL;
218 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
219 return NULL;
223 fstring dos_ea_name;
224 push_ascii_fstring(dos_ea_name, listp->ea.name);
225 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
226 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
227 (unsigned int)*pea_total_len, dos_ea_name,
228 (unsigned int)listp->ea.value.length ));
230 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
232 /* Add on 4 for total length. */
233 if (*pea_total_len) {
234 *pea_total_len += 4;
238 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
239 return ea_list_head;
242 /****************************************************************************
243 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
244 that was filled.
245 ****************************************************************************/
247 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
248 connection_struct *conn, struct ea_list *ea_list)
250 unsigned int ret_data_size = 4;
251 char *p = pdata;
253 SMB_ASSERT(total_data_size >= 4);
255 if (!lp_ea_support(SNUM(conn))) {
256 SIVAL(pdata,4,0);
257 return 4;
260 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
261 size_t dos_namelen;
262 fstring dos_ea_name;
263 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
264 dos_namelen = strlen(dos_ea_name);
265 if (dos_namelen > 255 || dos_namelen == 0) {
266 break;
268 if (ea_list->ea.value.length > 65535) {
269 break;
271 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
272 break;
275 /* We know we have room. */
276 SCVAL(p,0,ea_list->ea.flags);
277 SCVAL(p,1,dos_namelen);
278 SSVAL(p,2,ea_list->ea.value.length);
279 fstrcpy(p+4, dos_ea_name);
280 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
282 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
283 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
286 ret_data_size = PTR_DIFF(p, pdata);
287 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
288 SIVAL(pdata,0,ret_data_size);
289 return ret_data_size;
292 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
294 size_t total_ea_len = 0;
295 TALLOC_CTX *mem_ctx = NULL;
297 if (!lp_ea_support(SNUM(conn))) {
298 return 0;
300 mem_ctx = talloc_tos();
301 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
302 return total_ea_len;
305 /****************************************************************************
306 Ensure the EA name is case insensitive by matching any existing EA name.
307 ****************************************************************************/
309 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
311 size_t total_ea_len;
312 TALLOC_CTX *mem_ctx = talloc_tos();
313 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
315 for (; ea_list; ea_list = ea_list->next) {
316 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
317 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
318 &unix_ea_name[5], ea_list->ea.name));
319 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
320 break;
325 /****************************************************************************
326 Set or delete an extended attribute.
327 ****************************************************************************/
329 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
331 if (!lp_ea_support(SNUM(conn))) {
332 return NT_STATUS_EAS_NOT_SUPPORTED;
335 for (;ea_list; ea_list = ea_list->next) {
336 int ret;
337 fstring unix_ea_name;
339 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
340 fstrcat(unix_ea_name, ea_list->ea.name);
342 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
344 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
346 if (samba_private_attr_name(unix_ea_name)) {
347 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
348 return NT_STATUS_ACCESS_DENIED;
351 if (ea_list->ea.value.length == 0) {
352 /* Remove the attribute. */
353 if (fsp && (fsp->fh->fd != -1)) {
354 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
355 unix_ea_name, fsp->fsp_name));
356 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
357 } else {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
359 unix_ea_name, fname));
360 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
362 #ifdef ENOATTR
363 /* Removing a non existent attribute always succeeds. */
364 if (ret == -1 && errno == ENOATTR) {
365 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
366 unix_ea_name));
367 ret = 0;
369 #endif
370 } else {
371 if (fsp && (fsp->fh->fd != -1)) {
372 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
373 unix_ea_name, fsp->fsp_name));
374 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
375 ea_list->ea.value.data, ea_list->ea.value.length, 0);
376 } else {
377 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
378 unix_ea_name, fname));
379 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
380 ea_list->ea.value.data, ea_list->ea.value.length, 0);
384 if (ret == -1) {
385 #ifdef ENOTSUP
386 if (errno == ENOTSUP) {
387 return NT_STATUS_EAS_NOT_SUPPORTED;
389 #endif
390 return map_nt_error_from_unix(errno);
394 return NT_STATUS_OK;
396 /****************************************************************************
397 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
398 ****************************************************************************/
400 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
402 struct ea_list *ea_list_head = NULL;
403 size_t offset = 0;
405 while (offset + 2 < data_size) {
406 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
407 unsigned int namelen = CVAL(pdata,offset);
409 offset++; /* Go past the namelen byte. */
411 /* integer wrap paranioa. */
412 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
413 (offset > data_size) || (namelen > data_size) ||
414 (offset + namelen >= data_size)) {
415 break;
417 /* Ensure the name is null terminated. */
418 if (pdata[offset + namelen] != '\0') {
419 return NULL;
421 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
422 if (!eal->ea.name) {
423 return NULL;
426 offset += (namelen + 1); /* Go past the name + terminating zero. */
427 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
428 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
431 return ea_list_head;
434 /****************************************************************************
435 Read one EA list entry from the buffer.
436 ****************************************************************************/
438 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
440 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
441 uint16 val_len;
442 unsigned int namelen;
444 if (!eal) {
445 return NULL;
448 if (data_size < 6) {
449 return NULL;
452 eal->ea.flags = CVAL(pdata,0);
453 namelen = CVAL(pdata,1);
454 val_len = SVAL(pdata,2);
456 if (4 + namelen + 1 + val_len > data_size) {
457 return NULL;
460 /* Ensure the name is null terminated. */
461 if (pdata[namelen + 4] != '\0') {
462 return NULL;
464 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
465 if (!eal->ea.name) {
466 return NULL;
469 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
470 if (!eal->ea.value.data) {
471 return NULL;
474 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
476 /* Ensure we're null terminated just in case we print the value. */
477 eal->ea.value.data[val_len] = '\0';
478 /* But don't count the null. */
479 eal->ea.value.length--;
481 if (pbytes_used) {
482 *pbytes_used = 4 + namelen + 1 + val_len;
485 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
486 dump_data(10, eal->ea.value.data, eal->ea.value.length);
488 return eal;
491 /****************************************************************************
492 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
493 ****************************************************************************/
495 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
497 struct ea_list *ea_list_head = NULL;
498 size_t offset = 0;
499 size_t bytes_used = 0;
501 while (offset < data_size) {
502 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
504 if (!eal) {
505 return NULL;
508 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
509 offset += bytes_used;
512 return ea_list_head;
515 /****************************************************************************
516 Count the total EA size needed.
517 ****************************************************************************/
519 static size_t ea_list_size(struct ea_list *ealist)
521 fstring dos_ea_name;
522 struct ea_list *listp;
523 size_t ret = 0;
525 for (listp = ealist; listp; listp = listp->next) {
526 push_ascii_fstring(dos_ea_name, listp->ea.name);
527 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
529 /* Add on 4 for total length. */
530 if (ret) {
531 ret += 4;
534 return ret;
537 /****************************************************************************
538 Return a union of EA's from a file list and a list of names.
539 The TALLOC context for the two lists *MUST* be identical as we steal
540 memory from one list to add to another. JRA.
541 ****************************************************************************/
543 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
545 struct ea_list *nlistp, *flistp;
547 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
548 for (flistp = file_list; flistp; flistp = flistp->next) {
549 if (strequal(nlistp->ea.name, flistp->ea.name)) {
550 break;
554 if (flistp) {
555 /* Copy the data from this entry. */
556 nlistp->ea.flags = flistp->ea.flags;
557 nlistp->ea.value = flistp->ea.value;
558 } else {
559 /* Null entry. */
560 nlistp->ea.flags = 0;
561 ZERO_STRUCT(nlistp->ea.value);
565 *total_ea_len = ea_list_size(name_list);
566 return name_list;
569 /****************************************************************************
570 Send the required number of replies back.
571 We assume all fields other than the data fields are
572 set correctly for the type of call.
573 HACK ! Always assumes smb_setup field is zero.
574 ****************************************************************************/
576 void send_trans2_replies(connection_struct *conn,
577 struct smb_request *req,
578 const char *params,
579 int paramsize,
580 const char *pdata,
581 int datasize,
582 int max_data_bytes)
584 /* As we are using a protocol > LANMAN1 then the max_send
585 variable must have been set in the sessetupX call.
586 This takes precedence over the max_xmit field in the
587 global struct. These different max_xmit variables should
588 be merged as this is now too confusing */
590 int data_to_send = datasize;
591 int params_to_send = paramsize;
592 int useable_space;
593 const char *pp = params;
594 const char *pd = pdata;
595 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
596 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
597 int data_alignment_offset = 0;
598 bool overflow = False;
600 /* Modify the data_to_send and datasize and set the error if
601 we're trying to send more than max_data_bytes. We still send
602 the part of the packet(s) that fit. Strange, but needed
603 for OS/2. */
605 if (max_data_bytes > 0 && datasize > max_data_bytes) {
606 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
607 max_data_bytes, datasize ));
608 datasize = data_to_send = max_data_bytes;
609 overflow = True;
612 /* If there genuinely are no parameters or data to send just send the empty packet */
614 if(params_to_send == 0 && data_to_send == 0) {
615 reply_outbuf(req, 10, 0);
616 show_msg((char *)req->outbuf);
617 return;
620 /* When sending params and data ensure that both are nicely aligned */
621 /* Only do this alignment when there is also data to send - else
622 can cause NT redirector problems. */
624 if (((params_to_send % 4) != 0) && (data_to_send != 0))
625 data_alignment_offset = 4 - (params_to_send % 4);
627 /* Space is bufsize minus Netbios over TCP header minus SMB header */
628 /* The alignment_offset is to align the param bytes on an even byte
629 boundary. NT 4.0 Beta needs this to work correctly. */
631 useable_space = max_send - (smb_size
632 + 2 * 10 /* wct */
633 + alignment_offset
634 + data_alignment_offset);
636 /* useable_space can never be more than max_send minus the alignment offset. */
638 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
640 while (params_to_send || data_to_send) {
641 /* Calculate whether we will totally or partially fill this packet */
643 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
645 /* We can never send more than useable_space */
647 * Note that 'useable_space' does not include the alignment offsets,
648 * but we must include the alignment offsets in the calculation of
649 * the length of the data we send over the wire, as the alignment offsets
650 * are sent here. Fix from Marc_Jacobsen@hp.com.
653 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
655 reply_outbuf(req, 10, total_sent_thistime);
657 /* Set total params and data to be sent */
658 SSVAL(req->outbuf,smb_tprcnt,paramsize);
659 SSVAL(req->outbuf,smb_tdrcnt,datasize);
661 /* Calculate how many parameters and data we can fit into
662 * this packet. Parameters get precedence
665 params_sent_thistime = MIN(params_to_send,useable_space);
666 data_sent_thistime = useable_space - params_sent_thistime;
667 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
669 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
671 /* smb_proff is the offset from the start of the SMB header to the
672 parameter bytes, however the first 4 bytes of outbuf are
673 the Netbios over TCP header. Thus use smb_base() to subtract
674 them from the calculation */
676 SSVAL(req->outbuf,smb_proff,
677 ((smb_buf(req->outbuf)+alignment_offset)
678 - smb_base(req->outbuf)));
680 if(params_sent_thistime == 0)
681 SSVAL(req->outbuf,smb_prdisp,0);
682 else
683 /* Absolute displacement of param bytes sent in this packet */
684 SSVAL(req->outbuf,smb_prdisp,pp - params);
686 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
687 if(data_sent_thistime == 0) {
688 SSVAL(req->outbuf,smb_droff,0);
689 SSVAL(req->outbuf,smb_drdisp, 0);
690 } else {
691 /* The offset of the data bytes is the offset of the
692 parameter bytes plus the number of parameters being sent this time */
693 SSVAL(req->outbuf, smb_droff,
694 ((smb_buf(req->outbuf)+alignment_offset)
695 - smb_base(req->outbuf))
696 + params_sent_thistime + data_alignment_offset);
697 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
700 /* Initialize the padding for alignment */
702 if (alignment_offset != 0) {
703 memset(smb_buf(req->outbuf), 0, alignment_offset);
706 /* Copy the param bytes into the packet */
708 if(params_sent_thistime) {
709 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
710 params_sent_thistime);
713 /* Copy in the data bytes */
714 if(data_sent_thistime) {
715 if (data_alignment_offset != 0) {
716 memset((smb_buf(req->outbuf)+alignment_offset+
717 params_sent_thistime), 0,
718 data_alignment_offset);
720 memcpy(smb_buf(req->outbuf)+alignment_offset
721 +params_sent_thistime+data_alignment_offset,
722 pd,data_sent_thistime);
725 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
726 params_sent_thistime, data_sent_thistime, useable_space));
727 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
728 params_to_send, data_to_send, paramsize, datasize));
730 if (overflow) {
731 error_packet_set((char *)req->outbuf,
732 ERRDOS,ERRbufferoverflow,
733 STATUS_BUFFER_OVERFLOW,
734 __LINE__,__FILE__);
737 /* Send the packet */
738 show_msg((char *)req->outbuf);
739 if (!srv_send_smb(smbd_server_fd(),
740 (char *)req->outbuf,
741 IS_CONN_ENCRYPTED(conn)))
742 exit_server_cleanly("send_trans2_replies: srv_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 if (open_ofun == 0) {
846 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
847 return;
850 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
851 &access_mask,
852 &share_mode,
853 &create_disposition,
854 &create_options)) {
855 reply_doserror(req, ERRDOS, ERRbadaccess);
856 return;
859 /* Any data in this call is an EA list. */
860 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
861 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
862 return;
865 if (total_data != 4) {
866 if (total_data < 10) {
867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
868 return;
871 if (IVAL(pdata,0) > total_data) {
872 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
873 IVAL(pdata,0), (unsigned int)total_data));
874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
875 return;
878 ea_list = read_ea_list(talloc_tos(), pdata + 4,
879 total_data - 4);
880 if (!ea_list) {
881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
882 return;
884 } else if (IVAL(pdata,0) != 4) {
885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
886 return;
889 status = create_file(conn, /* conn */
890 req, /* req */
891 0, /* root_dir_fid */
892 fname, /* fname */
893 access_mask, /* access_mask */
894 share_mode, /* share_access */
895 create_disposition, /* create_disposition*/
896 create_options, /* create_options */
897 open_attr, /* file_attributes */
898 oplock_request, /* oplock_request */
899 open_size, /* allocation_size */
900 NULL, /* sd */
901 ea_list, /* ea_list */
902 &fsp, /* result */
903 &smb_action, /* pinfo */
904 &sbuf); /* psbuf */
906 if (!NT_STATUS_IS_OK(status)) {
907 if (open_was_deferred(req->mid)) {
908 /* We have re-scheduled this call. */
909 return;
911 reply_openerror(req, status);
912 return;
915 size = get_file_size(sbuf);
916 fattr = dos_mode(conn,fname,&sbuf);
917 mtime = sbuf.st_mtime;
918 inode = sbuf.st_ino;
919 if (fattr & aDIR) {
920 close_file(fsp,ERROR_CLOSE);
921 reply_doserror(req, ERRDOS,ERRnoaccess);
922 return;
925 /* Realloc the size of parameters and data we will return */
926 *pparams = (char *)SMB_REALLOC(*pparams, 30);
927 if(*pparams == NULL ) {
928 reply_nterror(req, NT_STATUS_NO_MEMORY);
929 return;
931 params = *pparams;
933 SSVAL(params,0,fsp->fnum);
934 SSVAL(params,2,fattr);
935 srv_put_dos_date2(params,4, mtime);
936 SIVAL(params,8, (uint32)size);
937 SSVAL(params,12,deny_mode);
938 SSVAL(params,14,0); /* open_type - file or directory. */
939 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
941 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
942 smb_action |= EXTENDED_OPLOCK_GRANTED;
945 SSVAL(params,18,smb_action);
948 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
950 SIVAL(params,20,inode);
951 SSVAL(params,24,0); /* Padding. */
952 if (flags & 8) {
953 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
954 SIVAL(params, 26, ea_size);
955 } else {
956 SIVAL(params, 26, 0);
959 /* Send the required number of replies */
960 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
963 /*********************************************************
964 Routine to check if a given string matches exactly.
965 as a special case a mask of "." does NOT match. That
966 is required for correct wildcard semantics
967 Case can be significant or not.
968 **********************************************************/
970 static bool exact_match(connection_struct *conn,
971 const char *str,
972 const char *mask)
974 if (mask[0] == '.' && mask[1] == 0)
975 return False;
976 if (conn->case_sensitive)
977 return strcmp(str,mask)==0;
978 if (StrCaseCmp(str,mask) != 0) {
979 return False;
981 if (dptr_has_wild(conn->dirptr)) {
982 return False;
984 return True;
987 /****************************************************************************
988 Return the filetype for UNIX extensions.
989 ****************************************************************************/
991 static uint32 unix_filetype(mode_t mode)
993 if(S_ISREG(mode))
994 return UNIX_TYPE_FILE;
995 else if(S_ISDIR(mode))
996 return UNIX_TYPE_DIR;
997 #ifdef S_ISLNK
998 else if(S_ISLNK(mode))
999 return UNIX_TYPE_SYMLINK;
1000 #endif
1001 #ifdef S_ISCHR
1002 else if(S_ISCHR(mode))
1003 return UNIX_TYPE_CHARDEV;
1004 #endif
1005 #ifdef S_ISBLK
1006 else if(S_ISBLK(mode))
1007 return UNIX_TYPE_BLKDEV;
1008 #endif
1009 #ifdef S_ISFIFO
1010 else if(S_ISFIFO(mode))
1011 return UNIX_TYPE_FIFO;
1012 #endif
1013 #ifdef S_ISSOCK
1014 else if(S_ISSOCK(mode))
1015 return UNIX_TYPE_SOCKET;
1016 #endif
1018 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1019 return UNIX_TYPE_UNKNOWN;
1022 /****************************************************************************
1023 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1024 ****************************************************************************/
1026 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1028 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1029 SMB_STRUCT_STAT *psbuf,
1030 uint32 perms,
1031 enum perm_type ptype,
1032 mode_t *ret_perms)
1034 mode_t ret = 0;
1036 if (perms == SMB_MODE_NO_CHANGE) {
1037 if (!VALID_STAT(*psbuf)) {
1038 return NT_STATUS_INVALID_PARAMETER;
1039 } else {
1040 *ret_perms = psbuf->st_mode;
1041 return NT_STATUS_OK;
1045 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1046 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1047 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1048 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1049 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1050 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1051 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1052 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1053 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1054 #ifdef S_ISVTX
1055 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1056 #endif
1057 #ifdef S_ISGID
1058 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1059 #endif
1060 #ifdef S_ISUID
1061 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1062 #endif
1064 switch (ptype) {
1065 case PERM_NEW_FILE:
1066 /* Apply mode mask */
1067 ret &= lp_create_mask(SNUM(conn));
1068 /* Add in force bits */
1069 ret |= lp_force_create_mode(SNUM(conn));
1070 break;
1071 case PERM_NEW_DIR:
1072 ret &= lp_dir_mask(SNUM(conn));
1073 /* Add in force bits */
1074 ret |= lp_force_dir_mode(SNUM(conn));
1075 break;
1076 case PERM_EXISTING_FILE:
1077 /* Apply mode mask */
1078 ret &= lp_security_mask(SNUM(conn));
1079 /* Add in force bits */
1080 ret |= lp_force_security_mode(SNUM(conn));
1081 break;
1082 case PERM_EXISTING_DIR:
1083 /* Apply mode mask */
1084 ret &= lp_dir_security_mask(SNUM(conn));
1085 /* Add in force bits */
1086 ret |= lp_force_dir_security_mode(SNUM(conn));
1087 break;
1090 *ret_perms = ret;
1091 return NT_STATUS_OK;
1094 /****************************************************************************
1095 Get a level dependent lanman2 dir entry.
1096 ****************************************************************************/
1098 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1099 connection_struct *conn,
1100 uint16 flags2,
1101 const char *path_mask,
1102 uint32 dirtype,
1103 int info_level,
1104 int requires_resume_key,
1105 bool dont_descend,
1106 char **ppdata,
1107 char *base_data,
1108 char *end_data,
1109 int space_remaining,
1110 bool *out_of_space,
1111 bool *got_exact_match,
1112 int *last_entry_off,
1113 struct ea_list *name_list)
1115 const char *dname;
1116 bool found = False;
1117 SMB_STRUCT_STAT sbuf;
1118 const char *mask = NULL;
1119 char *pathreal = NULL;
1120 const char *fname = NULL;
1121 char *p, *q, *pdata = *ppdata;
1122 uint32 reskey=0;
1123 long prev_dirpos=0;
1124 uint32 mode=0;
1125 SMB_OFF_T file_size = 0;
1126 SMB_BIG_UINT allocation_size = 0;
1127 uint32 len;
1128 struct timespec mdate_ts, adate_ts, create_date_ts;
1129 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1130 char *nameptr;
1131 char *last_entry_ptr;
1132 bool was_8_3;
1133 uint32 nt_extmode; /* Used for NT connections instead of mode */
1134 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1135 bool check_mangled_names = lp_manglednames(conn->params);
1136 char mangled_name[13]; /* mangled 8.3 name. */
1138 *out_of_space = False;
1139 *got_exact_match = False;
1141 ZERO_STRUCT(mdate_ts);
1142 ZERO_STRUCT(adate_ts);
1143 ZERO_STRUCT(create_date_ts);
1145 if (!conn->dirptr) {
1146 return(False);
1149 p = strrchr_m(path_mask,'/');
1150 if(p != NULL) {
1151 if(p[1] == '\0') {
1152 mask = talloc_strdup(ctx,"*.*");
1153 } else {
1154 mask = p+1;
1156 } else {
1157 mask = path_mask;
1160 while (!found) {
1161 bool got_match;
1162 bool ms_dfs_link = False;
1164 /* Needed if we run out of space */
1165 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1166 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1169 * Due to bugs in NT client redirectors we are not using
1170 * resume keys any more - set them to zero.
1171 * Check out the related comments in findfirst/findnext.
1172 * JRA.
1175 reskey = 0;
1177 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1178 (long)conn->dirptr,curr_dirpos));
1180 if (!dname) {
1181 return(False);
1185 * fname may get mangled, dname is never mangled.
1186 * Whenever we're accessing the filesystem we use
1187 * pathreal which is composed from dname.
1190 pathreal = NULL;
1191 fname = dname;
1193 /* Mangle fname if it's an illegal name. */
1194 if (mangle_must_mangle(dname,conn->params)) {
1195 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1196 continue; /* Error - couldn't mangle. */
1198 fname = mangled_name;
1201 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1202 got_match = mask_match(fname, mask, conn->case_sensitive);
1205 if(!got_match && check_mangled_names &&
1206 !mangle_is_8_3(fname, False, conn->params)) {
1208 * It turns out that NT matches wildcards against
1209 * both long *and* short names. This may explain some
1210 * of the wildcard wierdness from old DOS clients
1211 * that some people have been seeing.... JRA.
1213 /* Force the mangling into 8.3. */
1214 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1215 continue; /* Error - couldn't mangle. */
1218 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1219 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1223 if (got_match) {
1224 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1226 if (dont_descend && !isdots) {
1227 continue;
1230 if (needslash) {
1231 pathreal = NULL;
1232 pathreal = talloc_asprintf(ctx,
1233 "%s/%s",
1234 conn->dirpath,
1235 dname);
1236 } else {
1237 pathreal = talloc_asprintf(ctx,
1238 "%s%s",
1239 conn->dirpath,
1240 dname);
1243 if (!pathreal) {
1244 return False;
1247 if (INFO_LEVEL_IS_UNIX(info_level)) {
1248 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1249 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1250 pathreal,strerror(errno)));
1251 TALLOC_FREE(pathreal);
1252 continue;
1254 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1255 /* Needed to show the msdfs symlinks as
1256 * directories */
1258 if(lp_host_msdfs() &&
1259 lp_msdfs_root(SNUM(conn)) &&
1260 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1261 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1262 "as a directory\n",
1263 pathreal));
1264 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1266 } else {
1268 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1269 pathreal,strerror(errno)));
1270 TALLOC_FREE(pathreal);
1271 continue;
1275 if (ms_dfs_link) {
1276 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1277 } else {
1278 mode = dos_mode(conn,pathreal,&sbuf);
1281 if (!dir_check_ftype(conn,mode,dirtype)) {
1282 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1283 TALLOC_FREE(pathreal);
1284 continue;
1287 if (!(mode & aDIR)) {
1288 file_size = get_file_size(sbuf);
1290 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1292 mdate_ts = get_mtimespec(&sbuf);
1293 adate_ts = get_atimespec(&sbuf);
1294 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1296 if (lp_dos_filetime_resolution(SNUM(conn))) {
1297 dos_filetime_timespec(&create_date_ts);
1298 dos_filetime_timespec(&mdate_ts);
1299 dos_filetime_timespec(&adate_ts);
1302 create_date = convert_timespec_to_time_t(create_date_ts);
1303 mdate = convert_timespec_to_time_t(mdate_ts);
1304 adate = convert_timespec_to_time_t(adate_ts);
1306 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1308 found = True;
1310 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1314 p = pdata;
1315 last_entry_ptr = p;
1317 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1319 switch (info_level) {
1320 case SMB_FIND_INFO_STANDARD:
1321 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1322 if(requires_resume_key) {
1323 SIVAL(p,0,reskey);
1324 p += 4;
1326 srv_put_dos_date2(p,0,create_date);
1327 srv_put_dos_date2(p,4,adate);
1328 srv_put_dos_date2(p,8,mdate);
1329 SIVAL(p,12,(uint32)file_size);
1330 SIVAL(p,16,(uint32)allocation_size);
1331 SSVAL(p,20,mode);
1332 p += 23;
1333 nameptr = p;
1334 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1335 p += ucs2_align(base_data, p, 0);
1337 len = srvstr_push(base_data, flags2, p,
1338 fname, PTR_DIFF(end_data, p),
1339 STR_TERMINATE);
1340 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1341 if (len > 2) {
1342 SCVAL(nameptr, -1, len - 2);
1343 } else {
1344 SCVAL(nameptr, -1, 0);
1346 } else {
1347 if (len > 1) {
1348 SCVAL(nameptr, -1, len - 1);
1349 } else {
1350 SCVAL(nameptr, -1, 0);
1353 p += len;
1354 break;
1356 case SMB_FIND_EA_SIZE:
1357 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1358 if(requires_resume_key) {
1359 SIVAL(p,0,reskey);
1360 p += 4;
1362 srv_put_dos_date2(p,0,create_date);
1363 srv_put_dos_date2(p,4,adate);
1364 srv_put_dos_date2(p,8,mdate);
1365 SIVAL(p,12,(uint32)file_size);
1366 SIVAL(p,16,(uint32)allocation_size);
1367 SSVAL(p,20,mode);
1369 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1370 SIVAL(p,22,ea_size); /* Extended attributes */
1372 p += 27;
1373 nameptr = p - 1;
1374 len = srvstr_push(base_data, flags2,
1375 p, fname, PTR_DIFF(end_data, p),
1376 STR_TERMINATE | STR_NOALIGN);
1377 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1378 if (len > 2) {
1379 len -= 2;
1380 } else {
1381 len = 0;
1383 } else {
1384 if (len > 1) {
1385 len -= 1;
1386 } else {
1387 len = 0;
1390 SCVAL(nameptr,0,len);
1391 p += len;
1392 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1393 break;
1395 case SMB_FIND_EA_LIST:
1397 struct ea_list *file_list = NULL;
1398 size_t ea_len = 0;
1400 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1401 if (!name_list) {
1402 return False;
1404 if(requires_resume_key) {
1405 SIVAL(p,0,reskey);
1406 p += 4;
1408 srv_put_dos_date2(p,0,create_date);
1409 srv_put_dos_date2(p,4,adate);
1410 srv_put_dos_date2(p,8,mdate);
1411 SIVAL(p,12,(uint32)file_size);
1412 SIVAL(p,16,(uint32)allocation_size);
1413 SSVAL(p,20,mode);
1414 p += 22; /* p now points to the EA area. */
1416 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1417 name_list = ea_list_union(name_list, file_list, &ea_len);
1419 /* We need to determine if this entry will fit in the space available. */
1420 /* Max string size is 255 bytes. */
1421 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1422 /* Move the dirptr back to prev_dirpos */
1423 dptr_SeekDir(conn->dirptr, prev_dirpos);
1424 *out_of_space = True;
1425 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1426 return False; /* Not finished - just out of space */
1429 /* Push the ea_data followed by the name. */
1430 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1431 nameptr = p;
1432 len = srvstr_push(base_data, flags2,
1433 p + 1, fname, PTR_DIFF(end_data, p+1),
1434 STR_TERMINATE | STR_NOALIGN);
1435 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1436 if (len > 2) {
1437 len -= 2;
1438 } else {
1439 len = 0;
1441 } else {
1442 if (len > 1) {
1443 len -= 1;
1444 } else {
1445 len = 0;
1448 SCVAL(nameptr,0,len);
1449 p += len + 1;
1450 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1451 break;
1454 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1455 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1456 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1457 p += 4;
1458 SIVAL(p,0,reskey); p += 4;
1459 put_long_date_timespec(p,create_date_ts); p += 8;
1460 put_long_date_timespec(p,adate_ts); p += 8;
1461 put_long_date_timespec(p,mdate_ts); p += 8;
1462 put_long_date_timespec(p,mdate_ts); p += 8;
1463 SOFF_T(p,0,file_size); p += 8;
1464 SOFF_T(p,0,allocation_size); p += 8;
1465 SIVAL(p,0,nt_extmode); p += 4;
1466 q = p; p += 4; /* q is placeholder for name length. */
1468 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1469 SIVAL(p,0,ea_size); /* Extended attributes */
1470 p += 4;
1472 /* Clear the short name buffer. This is
1473 * IMPORTANT as not doing so will trigger
1474 * a Win2k client bug. JRA.
1476 if (!was_8_3 && check_mangled_names) {
1477 if (!name_to_8_3(fname,mangled_name,True,
1478 conn->params)) {
1479 /* Error - mangle failed ! */
1480 memset(mangled_name,'\0',12);
1482 mangled_name[12] = 0;
1483 len = srvstr_push(base_data, flags2,
1484 p+2, mangled_name, 24,
1485 STR_UPPER|STR_UNICODE);
1486 if (len < 24) {
1487 memset(p + 2 + len,'\0',24 - len);
1489 SSVAL(p, 0, len);
1490 } else {
1491 memset(p,'\0',26);
1493 p += 2 + 24;
1494 len = srvstr_push(base_data, flags2, p,
1495 fname, PTR_DIFF(end_data, p),
1496 STR_TERMINATE_ASCII);
1497 SIVAL(q,0,len);
1498 p += len;
1499 SIVAL(p,0,0); /* Ensure any padding is null. */
1500 len = PTR_DIFF(p, pdata);
1501 len = (len + 3) & ~3;
1502 SIVAL(pdata,0,len);
1503 p = pdata + len;
1504 break;
1506 case SMB_FIND_FILE_DIRECTORY_INFO:
1507 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1508 p += 4;
1509 SIVAL(p,0,reskey); p += 4;
1510 put_long_date_timespec(p,create_date_ts); p += 8;
1511 put_long_date_timespec(p,adate_ts); p += 8;
1512 put_long_date_timespec(p,mdate_ts); p += 8;
1513 put_long_date_timespec(p,mdate_ts); p += 8;
1514 SOFF_T(p,0,file_size); p += 8;
1515 SOFF_T(p,0,allocation_size); p += 8;
1516 SIVAL(p,0,nt_extmode); p += 4;
1517 len = srvstr_push(base_data, flags2,
1518 p + 4, fname, PTR_DIFF(end_data, p+4),
1519 STR_TERMINATE_ASCII);
1520 SIVAL(p,0,len);
1521 p += 4 + len;
1522 SIVAL(p,0,0); /* Ensure any padding is null. */
1523 len = PTR_DIFF(p, pdata);
1524 len = (len + 3) & ~3;
1525 SIVAL(pdata,0,len);
1526 p = pdata + len;
1527 break;
1529 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1530 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1531 p += 4;
1532 SIVAL(p,0,reskey); p += 4;
1533 put_long_date_timespec(p,create_date_ts); p += 8;
1534 put_long_date_timespec(p,adate_ts); p += 8;
1535 put_long_date_timespec(p,mdate_ts); p += 8;
1536 put_long_date_timespec(p,mdate_ts); p += 8;
1537 SOFF_T(p,0,file_size); p += 8;
1538 SOFF_T(p,0,allocation_size); p += 8;
1539 SIVAL(p,0,nt_extmode); p += 4;
1540 q = p; p += 4; /* q is placeholder for name length. */
1542 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1543 SIVAL(p,0,ea_size); /* Extended attributes */
1544 p +=4;
1546 len = srvstr_push(base_data, flags2, p,
1547 fname, PTR_DIFF(end_data, p),
1548 STR_TERMINATE_ASCII);
1549 SIVAL(q, 0, len);
1550 p += len;
1552 SIVAL(p,0,0); /* Ensure any padding is null. */
1553 len = PTR_DIFF(p, pdata);
1554 len = (len + 3) & ~3;
1555 SIVAL(pdata,0,len);
1556 p = pdata + len;
1557 break;
1559 case SMB_FIND_FILE_NAMES_INFO:
1560 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1561 p += 4;
1562 SIVAL(p,0,reskey); p += 4;
1563 p += 4;
1564 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1565 acl on a dir (tridge) */
1566 len = srvstr_push(base_data, flags2, p,
1567 fname, PTR_DIFF(end_data, p),
1568 STR_TERMINATE_ASCII);
1569 SIVAL(p, -4, len);
1570 p += len;
1571 SIVAL(p,0,0); /* Ensure any padding is null. */
1572 len = PTR_DIFF(p, pdata);
1573 len = (len + 3) & ~3;
1574 SIVAL(pdata,0,len);
1575 p = pdata + len;
1576 break;
1578 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1579 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1580 p += 4;
1581 SIVAL(p,0,reskey); p += 4;
1582 put_long_date_timespec(p,create_date_ts); p += 8;
1583 put_long_date_timespec(p,adate_ts); p += 8;
1584 put_long_date_timespec(p,mdate_ts); p += 8;
1585 put_long_date_timespec(p,mdate_ts); p += 8;
1586 SOFF_T(p,0,file_size); p += 8;
1587 SOFF_T(p,0,allocation_size); p += 8;
1588 SIVAL(p,0,nt_extmode); p += 4;
1589 q = p; p += 4; /* q is placeholder for name length. */
1591 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1592 SIVAL(p,0,ea_size); /* Extended attributes */
1593 p +=4;
1595 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1596 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1597 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1598 len = srvstr_push(base_data, flags2, p,
1599 fname, PTR_DIFF(end_data, p),
1600 STR_TERMINATE_ASCII);
1601 SIVAL(q, 0, len);
1602 p += len;
1603 SIVAL(p,0,0); /* Ensure any padding is null. */
1604 len = PTR_DIFF(p, pdata);
1605 len = (len + 3) & ~3;
1606 SIVAL(pdata,0,len);
1607 p = pdata + len;
1608 break;
1610 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1611 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1612 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1613 p += 4;
1614 SIVAL(p,0,reskey); p += 4;
1615 put_long_date_timespec(p,create_date_ts); p += 8;
1616 put_long_date_timespec(p,adate_ts); p += 8;
1617 put_long_date_timespec(p,mdate_ts); p += 8;
1618 put_long_date_timespec(p,mdate_ts); p += 8;
1619 SOFF_T(p,0,file_size); p += 8;
1620 SOFF_T(p,0,allocation_size); p += 8;
1621 SIVAL(p,0,nt_extmode); p += 4;
1622 q = p; p += 4; /* q is placeholder for name length */
1624 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1625 SIVAL(p,0,ea_size); /* Extended attributes */
1626 p +=4;
1628 /* Clear the short name buffer. This is
1629 * IMPORTANT as not doing so will trigger
1630 * a Win2k client bug. JRA.
1632 if (!was_8_3 && check_mangled_names) {
1633 if (!name_to_8_3(fname,mangled_name,True,
1634 conn->params)) {
1635 /* Error - mangle failed ! */
1636 memset(mangled_name,'\0',12);
1638 mangled_name[12] = 0;
1639 len = srvstr_push(base_data, flags2,
1640 p+2, mangled_name, 24,
1641 STR_UPPER|STR_UNICODE);
1642 SSVAL(p, 0, len);
1643 if (len < 24) {
1644 memset(p + 2 + len,'\0',24 - len);
1646 SSVAL(p, 0, len);
1647 } else {
1648 memset(p,'\0',26);
1650 p += 26;
1651 SSVAL(p,0,0); p += 2; /* Reserved ? */
1652 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1653 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1654 len = srvstr_push(base_data, flags2, p,
1655 fname, PTR_DIFF(end_data, p),
1656 STR_TERMINATE_ASCII);
1657 SIVAL(q,0,len);
1658 p += len;
1659 SIVAL(p,0,0); /* Ensure any padding is null. */
1660 len = PTR_DIFF(p, pdata);
1661 len = (len + 3) & ~3;
1662 SIVAL(pdata,0,len);
1663 p = pdata + len;
1664 break;
1666 /* CIFS UNIX Extension. */
1668 case SMB_FIND_FILE_UNIX:
1669 case SMB_FIND_FILE_UNIX_INFO2:
1670 p+= 4;
1671 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1673 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1675 if (info_level == SMB_FIND_FILE_UNIX) {
1676 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1677 p = store_file_unix_basic(conn, p,
1678 NULL, &sbuf);
1679 len = srvstr_push(base_data, flags2, p,
1680 fname, PTR_DIFF(end_data, p),
1681 STR_TERMINATE);
1682 } else {
1683 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1684 p = store_file_unix_basic_info2(conn, p,
1685 NULL, &sbuf);
1686 nameptr = p;
1687 p += 4;
1688 len = srvstr_push(base_data, flags2, p, fname,
1689 PTR_DIFF(end_data, p), 0);
1690 SIVAL(nameptr, 0, len);
1693 p += len;
1694 SIVAL(p,0,0); /* Ensure any padding is null. */
1696 len = PTR_DIFF(p, pdata);
1697 len = (len + 3) & ~3;
1698 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1699 p = pdata + len;
1700 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1702 break;
1704 default:
1705 return(False);
1709 if (PTR_DIFF(p,pdata) > space_remaining) {
1710 /* Move the dirptr back to prev_dirpos */
1711 dptr_SeekDir(conn->dirptr, prev_dirpos);
1712 *out_of_space = True;
1713 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1714 return False; /* Not finished - just out of space */
1717 /* Setup the last entry pointer, as an offset from base_data */
1718 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1719 /* Advance the data pointer to the next slot */
1720 *ppdata = p;
1722 return(found);
1725 /****************************************************************************
1726 Reply to a TRANS2_FINDFIRST.
1727 ****************************************************************************/
1729 static void call_trans2findfirst(connection_struct *conn,
1730 struct smb_request *req,
1731 char **pparams, int total_params,
1732 char **ppdata, int total_data,
1733 unsigned int max_data_bytes)
1735 /* We must be careful here that we don't return more than the
1736 allowed number of data bytes. If this means returning fewer than
1737 maxentries then so be it. We assume that the redirector has
1738 enough room for the fixed number of parameter bytes it has
1739 requested. */
1740 char *params = *pparams;
1741 char *pdata = *ppdata;
1742 char *data_end;
1743 uint32 dirtype;
1744 int maxentries;
1745 uint16 findfirst_flags;
1746 bool close_after_first;
1747 bool close_if_end;
1748 bool requires_resume_key;
1749 int info_level;
1750 char *directory = NULL;
1751 const char *mask = NULL;
1752 char *p;
1753 int last_entry_off=0;
1754 int dptr_num = -1;
1755 int numentries = 0;
1756 int i;
1757 bool finished = False;
1758 bool dont_descend = False;
1759 bool out_of_space = False;
1760 int space_remaining;
1761 bool mask_contains_wcard = False;
1762 SMB_STRUCT_STAT sbuf;
1763 struct ea_list *ea_list = NULL;
1764 NTSTATUS ntstatus = NT_STATUS_OK;
1765 TALLOC_CTX *ctx = talloc_tos();
1767 if (total_params < 13) {
1768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1769 return;
1772 dirtype = SVAL(params,0);
1773 maxentries = SVAL(params,2);
1774 findfirst_flags = SVAL(params,4);
1775 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1776 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1777 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1778 info_level = SVAL(params,6);
1780 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1781 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1782 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1783 info_level, max_data_bytes));
1785 if (!maxentries) {
1786 /* W2K3 seems to treat zero as 1. */
1787 maxentries = 1;
1790 switch (info_level) {
1791 case SMB_FIND_INFO_STANDARD:
1792 case SMB_FIND_EA_SIZE:
1793 case SMB_FIND_EA_LIST:
1794 case SMB_FIND_FILE_DIRECTORY_INFO:
1795 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1796 case SMB_FIND_FILE_NAMES_INFO:
1797 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1798 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1799 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1800 break;
1801 case SMB_FIND_FILE_UNIX:
1802 case SMB_FIND_FILE_UNIX_INFO2:
1803 if (!lp_unix_extensions()) {
1804 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1805 return;
1807 break;
1808 default:
1809 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1810 return;
1813 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1814 params+12, total_params - 12,
1815 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1816 if (!NT_STATUS_IS_OK(ntstatus)) {
1817 reply_nterror(req, ntstatus);
1818 return;
1821 ntstatus = resolve_dfspath_wcard(ctx, conn,
1822 req->flags2 & FLAGS2_DFS_PATHNAMES,
1823 directory,
1824 &directory,
1825 &mask_contains_wcard);
1826 if (!NT_STATUS_IS_OK(ntstatus)) {
1827 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1828 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1829 ERRSRV, ERRbadpath);
1830 return;
1832 reply_nterror(req, ntstatus);
1833 return;
1836 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1837 if (!NT_STATUS_IS_OK(ntstatus)) {
1838 reply_nterror(req, ntstatus);
1839 return;
1842 ntstatus = check_name(conn, directory);
1843 if (!NT_STATUS_IS_OK(ntstatus)) {
1844 reply_nterror(req, ntstatus);
1845 return;
1848 p = strrchr_m(directory,'/');
1849 if(p == NULL) {
1850 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1851 if((directory[0] == '.') && (directory[1] == '\0')) {
1852 mask = "*";
1853 mask_contains_wcard = True;
1854 } else {
1855 mask = directory;
1857 directory = talloc_strdup(talloc_tos(), "./");
1858 if (!directory) {
1859 reply_nterror(req, NT_STATUS_NO_MEMORY);
1860 return;
1862 } else {
1863 mask = p+1;
1864 *p = 0;
1867 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1869 if (info_level == SMB_FIND_EA_LIST) {
1870 uint32 ea_size;
1872 if (total_data < 4) {
1873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1874 return;
1877 ea_size = IVAL(pdata,0);
1878 if (ea_size != total_data) {
1879 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1880 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1882 return;
1885 if (!lp_ea_support(SNUM(conn))) {
1886 reply_doserror(req, ERRDOS, ERReasnotsupported);
1887 return;
1890 /* Pull out the list of names. */
1891 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1892 if (!ea_list) {
1893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1894 return;
1898 *ppdata = (char *)SMB_REALLOC(
1899 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1900 if(*ppdata == NULL ) {
1901 reply_nterror(req, NT_STATUS_NO_MEMORY);
1902 return;
1904 pdata = *ppdata;
1905 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1907 /* Realloc the params space */
1908 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1909 if (*pparams == NULL) {
1910 reply_nterror(req, NT_STATUS_NO_MEMORY);
1911 return;
1913 params = *pparams;
1915 /* Save the wildcard match and attribs we are using on this directory -
1916 needed as lanman2 assumes these are being saved between calls */
1918 ntstatus = dptr_create(conn,
1919 directory,
1920 False,
1921 True,
1922 req->smbpid,
1923 mask,
1924 mask_contains_wcard,
1925 dirtype,
1926 &conn->dirptr);
1928 if (!NT_STATUS_IS_OK(ntstatus)) {
1929 reply_nterror(req, ntstatus);
1930 return;
1933 dptr_num = dptr_dnum(conn->dirptr);
1934 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1936 /* We don't need to check for VOL here as this is returned by
1937 a different TRANS2 call. */
1939 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1940 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1941 dont_descend = True;
1943 p = pdata;
1944 space_remaining = max_data_bytes;
1945 out_of_space = False;
1947 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1948 bool got_exact_match = False;
1950 /* this is a heuristic to avoid seeking the dirptr except when
1951 absolutely necessary. It allows for a filename of about 40 chars */
1952 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1953 out_of_space = True;
1954 finished = False;
1955 } else {
1956 finished = !get_lanman2_dir_entry(ctx,
1957 conn,
1958 req->flags2,
1959 mask,dirtype,info_level,
1960 requires_resume_key,dont_descend,
1961 &p,pdata,data_end,
1962 space_remaining, &out_of_space,
1963 &got_exact_match,
1964 &last_entry_off, ea_list);
1967 if (finished && out_of_space)
1968 finished = False;
1970 if (!finished && !out_of_space)
1971 numentries++;
1974 * As an optimisation if we know we aren't looking
1975 * for a wildcard name (ie. the name matches the wildcard exactly)
1976 * then we can finish on any (first) match.
1977 * This speeds up large directory searches. JRA.
1980 if(got_exact_match)
1981 finished = True;
1983 /* Ensure space_remaining never goes -ve. */
1984 if (PTR_DIFF(p,pdata) > max_data_bytes) {
1985 space_remaining = 0;
1986 out_of_space = true;
1987 } else {
1988 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1992 /* Check if we can close the dirptr */
1993 if(close_after_first || (finished && close_if_end)) {
1994 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1995 dptr_close(&dptr_num);
1999 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2000 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2001 * the protocol level is less than NT1. Tested with smbclient. JRA.
2002 * This should fix the OS/2 client bug #2335.
2005 if(numentries == 0) {
2006 dptr_close(&dptr_num);
2007 if (Protocol < PROTOCOL_NT1) {
2008 reply_doserror(req, ERRDOS, ERRnofiles);
2009 return;
2010 } else {
2011 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2012 ERRDOS, ERRbadfile);
2013 return;
2017 /* At this point pdata points to numentries directory entries. */
2019 /* Set up the return parameter block */
2020 SSVAL(params,0,dptr_num);
2021 SSVAL(params,2,numentries);
2022 SSVAL(params,4,finished);
2023 SSVAL(params,6,0); /* Never an EA error */
2024 SSVAL(params,8,last_entry_off);
2026 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2027 max_data_bytes);
2029 if ((! *directory) && dptr_path(dptr_num)) {
2030 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2031 if (!directory) {
2032 reply_nterror(req, NT_STATUS_NO_MEMORY);
2036 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2037 smb_fn_name(CVAL(req->inbuf,smb_com)),
2038 mask, directory, dirtype, numentries ) );
2041 * Force a name mangle here to ensure that the
2042 * mask as an 8.3 name is top of the mangled cache.
2043 * The reasons for this are subtle. Don't remove
2044 * this code unless you know what you are doing
2045 * (see PR#13758). JRA.
2048 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2049 char mangled_name[13];
2050 name_to_8_3(mask, mangled_name, True, conn->params);
2053 return;
2056 /****************************************************************************
2057 Reply to a TRANS2_FINDNEXT.
2058 ****************************************************************************/
2060 static void call_trans2findnext(connection_struct *conn,
2061 struct smb_request *req,
2062 char **pparams, int total_params,
2063 char **ppdata, int total_data,
2064 unsigned int max_data_bytes)
2066 /* We must be careful here that we don't return more than the
2067 allowed number of data bytes. If this means returning fewer than
2068 maxentries then so be it. We assume that the redirector has
2069 enough room for the fixed number of parameter bytes it has
2070 requested. */
2071 char *params = *pparams;
2072 char *pdata = *ppdata;
2073 char *data_end;
2074 int dptr_num;
2075 int maxentries;
2076 uint16 info_level;
2077 uint32 resume_key;
2078 uint16 findnext_flags;
2079 bool close_after_request;
2080 bool close_if_end;
2081 bool requires_resume_key;
2082 bool continue_bit;
2083 bool mask_contains_wcard = False;
2084 char *resume_name = NULL;
2085 const char *mask = NULL;
2086 const char *directory = NULL;
2087 char *p = NULL;
2088 uint16 dirtype;
2089 int numentries = 0;
2090 int i, last_entry_off=0;
2091 bool finished = False;
2092 bool dont_descend = False;
2093 bool out_of_space = False;
2094 int space_remaining;
2095 struct ea_list *ea_list = NULL;
2096 NTSTATUS ntstatus = NT_STATUS_OK;
2097 TALLOC_CTX *ctx = talloc_tos();
2099 if (total_params < 13) {
2100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2101 return;
2104 dptr_num = SVAL(params,0);
2105 maxentries = SVAL(params,2);
2106 info_level = SVAL(params,4);
2107 resume_key = IVAL(params,6);
2108 findnext_flags = SVAL(params,10);
2109 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2110 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2111 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2112 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2114 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2115 params+12,
2116 total_params - 12, STR_TERMINATE, &ntstatus,
2117 &mask_contains_wcard);
2118 if (!NT_STATUS_IS_OK(ntstatus)) {
2119 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2120 complain (it thinks we're asking for the directory above the shared
2121 path or an invalid name). Catch this as the resume name is only compared, never used in
2122 a file access. JRA. */
2123 srvstr_pull_talloc(ctx, params, req->flags2,
2124 &resume_name, params+12,
2125 total_params - 12,
2126 STR_TERMINATE);
2128 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2129 reply_nterror(req, ntstatus);
2130 return;
2134 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2135 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2136 resume_key = %d resume name = %s continue=%d level = %d\n",
2137 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2138 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2140 if (!maxentries) {
2141 /* W2K3 seems to treat zero as 1. */
2142 maxentries = 1;
2145 switch (info_level) {
2146 case SMB_FIND_INFO_STANDARD:
2147 case SMB_FIND_EA_SIZE:
2148 case SMB_FIND_EA_LIST:
2149 case SMB_FIND_FILE_DIRECTORY_INFO:
2150 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2151 case SMB_FIND_FILE_NAMES_INFO:
2152 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2153 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2154 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2155 break;
2156 case SMB_FIND_FILE_UNIX:
2157 case SMB_FIND_FILE_UNIX_INFO2:
2158 if (!lp_unix_extensions()) {
2159 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2160 return;
2162 break;
2163 default:
2164 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2165 return;
2168 if (info_level == SMB_FIND_EA_LIST) {
2169 uint32 ea_size;
2171 if (total_data < 4) {
2172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2173 return;
2176 ea_size = IVAL(pdata,0);
2177 if (ea_size != total_data) {
2178 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2179 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2181 return;
2184 if (!lp_ea_support(SNUM(conn))) {
2185 reply_doserror(req, ERRDOS, ERReasnotsupported);
2186 return;
2189 /* Pull out the list of names. */
2190 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2191 if (!ea_list) {
2192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2193 return;
2197 *ppdata = (char *)SMB_REALLOC(
2198 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2199 if(*ppdata == NULL) {
2200 reply_nterror(req, NT_STATUS_NO_MEMORY);
2201 return;
2204 pdata = *ppdata;
2205 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2207 /* Realloc the params space */
2208 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2209 if(*pparams == NULL ) {
2210 reply_nterror(req, NT_STATUS_NO_MEMORY);
2211 return;
2214 params = *pparams;
2216 /* Check that the dptr is valid */
2217 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2218 reply_doserror(req, ERRDOS, ERRnofiles);
2219 return;
2222 string_set(&conn->dirpath,dptr_path(dptr_num));
2224 /* Get the wildcard mask from the dptr */
2225 if((p = dptr_wcard(dptr_num))== NULL) {
2226 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2227 reply_doserror(req, ERRDOS, ERRnofiles);
2228 return;
2231 mask = p;
2232 directory = conn->dirpath;
2234 /* Get the attr mask from the dptr */
2235 dirtype = dptr_attr(dptr_num);
2237 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2238 dptr_num, mask, dirtype,
2239 (long)conn->dirptr,
2240 dptr_TellDir(conn->dirptr)));
2242 /* We don't need to check for VOL here as this is returned by
2243 a different TRANS2 call. */
2245 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2246 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2247 dont_descend = True;
2249 p = pdata;
2250 space_remaining = max_data_bytes;
2251 out_of_space = False;
2254 * Seek to the correct position. We no longer use the resume key but
2255 * depend on the last file name instead.
2258 if(*resume_name && !continue_bit) {
2259 SMB_STRUCT_STAT st;
2261 long current_pos = 0;
2263 * Remember, name_to_8_3 is called by
2264 * get_lanman2_dir_entry(), so the resume name
2265 * could be mangled. Ensure we check the unmangled name.
2268 if (mangle_is_mangled(resume_name, conn->params)) {
2269 char *new_resume_name = NULL;
2270 mangle_lookup_name_from_8_3(ctx,
2271 resume_name,
2272 &new_resume_name,
2273 conn->params);
2274 if (new_resume_name) {
2275 resume_name = new_resume_name;
2280 * Fix for NT redirector problem triggered by resume key indexes
2281 * changing between directory scans. We now return a resume key of 0
2282 * and instead look for the filename to continue from (also given
2283 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2284 * findfirst/findnext (as is usual) then the directory pointer
2285 * should already be at the correct place.
2288 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2289 } /* end if resume_name && !continue_bit */
2291 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2292 bool got_exact_match = False;
2294 /* this is a heuristic to avoid seeking the dirptr except when
2295 absolutely necessary. It allows for a filename of about 40 chars */
2296 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2297 out_of_space = True;
2298 finished = False;
2299 } else {
2300 finished = !get_lanman2_dir_entry(ctx,
2301 conn,
2302 req->flags2,
2303 mask,dirtype,info_level,
2304 requires_resume_key,dont_descend,
2305 &p,pdata,data_end,
2306 space_remaining, &out_of_space,
2307 &got_exact_match,
2308 &last_entry_off, ea_list);
2311 if (finished && out_of_space)
2312 finished = False;
2314 if (!finished && !out_of_space)
2315 numentries++;
2318 * As an optimisation if we know we aren't looking
2319 * for a wildcard name (ie. the name matches the wildcard exactly)
2320 * then we can finish on any (first) match.
2321 * This speeds up large directory searches. JRA.
2324 if(got_exact_match)
2325 finished = True;
2327 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2330 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2331 smb_fn_name(CVAL(req->inbuf,smb_com)),
2332 mask, directory, dirtype, numentries ) );
2334 /* Check if we can close the dirptr */
2335 if(close_after_request || (finished && close_if_end)) {
2336 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2337 dptr_close(&dptr_num); /* This frees up the saved mask */
2340 /* Set up the return parameter block */
2341 SSVAL(params,0,numentries);
2342 SSVAL(params,2,finished);
2343 SSVAL(params,4,0); /* Never an EA error */
2344 SSVAL(params,6,last_entry_off);
2346 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2347 max_data_bytes);
2349 return;
2352 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2354 E_md4hash(lp_servicename(SNUM(conn)),objid);
2355 return objid;
2358 /****************************************************************************
2359 Reply to a TRANS2_QFSINFO (query filesystem info).
2360 ****************************************************************************/
2362 static void call_trans2qfsinfo(connection_struct *conn,
2363 struct smb_request *req,
2364 char **pparams, int total_params,
2365 char **ppdata, int total_data,
2366 unsigned int max_data_bytes)
2368 char *pdata, *end_data;
2369 char *params = *pparams;
2370 uint16 info_level;
2371 int data_len, len;
2372 SMB_STRUCT_STAT st;
2373 const char *vname = volume_label(SNUM(conn));
2374 int snum = SNUM(conn);
2375 char *fstype = lp_fstype(SNUM(conn));
2376 uint32 additional_flags = 0;
2378 if (total_params < 2) {
2379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2380 return;
2383 info_level = SVAL(params,0);
2385 if (IS_IPC(conn)) {
2386 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2387 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2388 "info level (0x%x) on IPC$.\n",
2389 (unsigned int)info_level));
2390 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2391 return;
2395 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2396 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2397 DEBUG(0,("call_trans2qfsinfo: encryption required "
2398 "and info level 0x%x sent.\n",
2399 (unsigned int)info_level));
2400 exit_server_cleanly("encryption required "
2401 "on connection");
2402 return;
2406 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2408 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2409 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2410 reply_doserror(req, ERRSRV, ERRinvdevice);
2411 return;
2414 *ppdata = (char *)SMB_REALLOC(
2415 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2416 if (*ppdata == NULL ) {
2417 reply_nterror(req, NT_STATUS_NO_MEMORY);
2418 return;
2421 pdata = *ppdata;
2422 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2423 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2425 switch (info_level) {
2426 case SMB_INFO_ALLOCATION:
2428 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2429 data_len = 18;
2430 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2431 reply_unixerror(req, ERRHRD, ERRgeneral);
2432 return;
2435 block_size = lp_block_size(snum);
2436 if (bsize < block_size) {
2437 SMB_BIG_UINT factor = block_size/bsize;
2438 bsize = block_size;
2439 dsize /= factor;
2440 dfree /= factor;
2442 if (bsize > block_size) {
2443 SMB_BIG_UINT factor = bsize/block_size;
2444 bsize = block_size;
2445 dsize *= factor;
2446 dfree *= factor;
2448 bytes_per_sector = 512;
2449 sectors_per_unit = bsize/bytes_per_sector;
2451 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2452 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2453 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2455 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2456 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2457 SIVAL(pdata,l1_cUnit,dsize);
2458 SIVAL(pdata,l1_cUnitAvail,dfree);
2459 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2460 break;
2463 case SMB_INFO_VOLUME:
2464 /* Return volume name */
2466 * Add volume serial number - hash of a combination of
2467 * the called hostname and the service name.
2469 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2471 * Win2k3 and previous mess this up by sending a name length
2472 * one byte short. I believe only older clients (OS/2 Win9x) use
2473 * this call so try fixing this by adding a terminating null to
2474 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2476 len = srvstr_push(
2477 pdata, req->flags2,
2478 pdata+l2_vol_szVolLabel, vname,
2479 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2480 STR_NOALIGN|STR_TERMINATE);
2481 SCVAL(pdata,l2_vol_cch,len);
2482 data_len = l2_vol_szVolLabel + len;
2483 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2484 (unsigned)st.st_ctime, len, vname));
2485 break;
2487 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2488 case SMB_FS_ATTRIBUTE_INFORMATION:
2490 additional_flags = 0;
2491 #if defined(HAVE_SYS_QUOTAS)
2492 additional_flags |= FILE_VOLUME_QUOTAS;
2493 #endif
2495 if(lp_nt_acl_support(SNUM(conn))) {
2496 additional_flags |= FILE_PERSISTENT_ACLS;
2499 /* Capabilities are filled in at connection time through STATVFS call */
2500 additional_flags |= conn->fs_capabilities;
2502 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2503 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2504 additional_flags); /* FS ATTRIBUTES */
2506 SIVAL(pdata,4,255); /* Max filename component length */
2507 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2508 and will think we can't do long filenames */
2509 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2510 PTR_DIFF(end_data, pdata+12),
2511 STR_UNICODE);
2512 SIVAL(pdata,8,len);
2513 data_len = 12 + len;
2514 break;
2516 case SMB_QUERY_FS_LABEL_INFO:
2517 case SMB_FS_LABEL_INFORMATION:
2518 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2519 PTR_DIFF(end_data, pdata+4), 0);
2520 data_len = 4 + len;
2521 SIVAL(pdata,0,len);
2522 break;
2524 case SMB_QUERY_FS_VOLUME_INFO:
2525 case SMB_FS_VOLUME_INFORMATION:
2528 * Add volume serial number - hash of a combination of
2529 * the called hostname and the service name.
2531 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2532 (str_checksum(get_local_machine_name())<<16));
2534 /* Max label len is 32 characters. */
2535 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2536 PTR_DIFF(end_data, pdata+18),
2537 STR_UNICODE);
2538 SIVAL(pdata,12,len);
2539 data_len = 18+len;
2541 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2542 (int)strlen(vname),vname, lp_servicename(snum)));
2543 break;
2545 case SMB_QUERY_FS_SIZE_INFO:
2546 case SMB_FS_SIZE_INFORMATION:
2548 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2549 data_len = 24;
2550 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2551 reply_unixerror(req, ERRHRD, ERRgeneral);
2552 return;
2554 block_size = lp_block_size(snum);
2555 if (bsize < block_size) {
2556 SMB_BIG_UINT factor = block_size/bsize;
2557 bsize = block_size;
2558 dsize /= factor;
2559 dfree /= factor;
2561 if (bsize > block_size) {
2562 SMB_BIG_UINT factor = bsize/block_size;
2563 bsize = block_size;
2564 dsize *= factor;
2565 dfree *= factor;
2567 bytes_per_sector = 512;
2568 sectors_per_unit = bsize/bytes_per_sector;
2569 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2570 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2571 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2572 SBIG_UINT(pdata,0,dsize);
2573 SBIG_UINT(pdata,8,dfree);
2574 SIVAL(pdata,16,sectors_per_unit);
2575 SIVAL(pdata,20,bytes_per_sector);
2576 break;
2579 case SMB_FS_FULL_SIZE_INFORMATION:
2581 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2582 data_len = 32;
2583 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2584 reply_unixerror(req, ERRHRD, ERRgeneral);
2585 return;
2587 block_size = lp_block_size(snum);
2588 if (bsize < block_size) {
2589 SMB_BIG_UINT factor = block_size/bsize;
2590 bsize = block_size;
2591 dsize /= factor;
2592 dfree /= factor;
2594 if (bsize > block_size) {
2595 SMB_BIG_UINT factor = bsize/block_size;
2596 bsize = block_size;
2597 dsize *= factor;
2598 dfree *= factor;
2600 bytes_per_sector = 512;
2601 sectors_per_unit = bsize/bytes_per_sector;
2602 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2603 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2604 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2605 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2606 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2607 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2608 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2609 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2610 break;
2613 case SMB_QUERY_FS_DEVICE_INFO:
2614 case SMB_FS_DEVICE_INFORMATION:
2615 data_len = 8;
2616 SIVAL(pdata,0,0); /* dev type */
2617 SIVAL(pdata,4,0); /* characteristics */
2618 break;
2620 #ifdef HAVE_SYS_QUOTAS
2621 case SMB_FS_QUOTA_INFORMATION:
2623 * what we have to send --metze:
2625 * Unknown1: 24 NULL bytes
2626 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2627 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2628 * Quota Flags: 2 byte :
2629 * Unknown3: 6 NULL bytes
2631 * 48 bytes total
2633 * details for Quota Flags:
2635 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2636 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2637 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2638 * 0x0001 Enable Quotas: enable quota for this fs
2642 /* we need to fake up a fsp here,
2643 * because its not send in this call
2645 files_struct fsp;
2646 SMB_NTQUOTA_STRUCT quotas;
2648 ZERO_STRUCT(fsp);
2649 ZERO_STRUCT(quotas);
2651 fsp.conn = conn;
2652 fsp.fnum = -1;
2654 /* access check */
2655 if (current_user.ut.uid != 0) {
2656 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2657 lp_servicename(SNUM(conn)),conn->user));
2658 reply_doserror(req, ERRDOS, ERRnoaccess);
2659 return;
2662 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2663 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2664 reply_doserror(req, ERRSRV, ERRerror);
2665 return;
2668 data_len = 48;
2670 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2672 /* Unknown1 24 NULL bytes*/
2673 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2674 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2675 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2677 /* Default Soft Quota 8 bytes */
2678 SBIG_UINT(pdata,24,quotas.softlim);
2680 /* Default Hard Quota 8 bytes */
2681 SBIG_UINT(pdata,32,quotas.hardlim);
2683 /* Quota flag 2 bytes */
2684 SSVAL(pdata,40,quotas.qflags);
2686 /* Unknown3 6 NULL bytes */
2687 SSVAL(pdata,42,0);
2688 SIVAL(pdata,44,0);
2690 break;
2692 #endif /* HAVE_SYS_QUOTAS */
2693 case SMB_FS_OBJECTID_INFORMATION:
2695 unsigned char objid[16];
2696 memcpy(pdata,create_volume_objectid(conn, objid),16);
2697 data_len = 64;
2698 break;
2702 * Query the version and capabilities of the CIFS UNIX extensions
2703 * in use.
2706 case SMB_QUERY_CIFS_UNIX_INFO:
2708 bool large_write = lp_min_receive_file_size() &&
2709 !srv_is_signing_active();
2710 bool large_read = !srv_is_signing_active();
2711 int encrypt_caps = 0;
2713 if (!lp_unix_extensions()) {
2714 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2715 return;
2718 switch (conn->encrypt_level) {
2719 case 0:
2720 encrypt_caps = 0;
2721 break;
2722 case 1:
2723 case Auto:
2724 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2725 break;
2726 case Required:
2727 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2728 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2729 large_write = false;
2730 large_read = false;
2731 break;
2734 data_len = 12;
2735 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2736 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2738 /* We have POSIX ACLs, pathname, encryption,
2739 * large read/write, and locking capability. */
2741 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2742 CIFS_UNIX_POSIX_ACLS_CAP|
2743 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2744 CIFS_UNIX_FCNTL_LOCKS_CAP|
2745 CIFS_UNIX_EXTATTR_CAP|
2746 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2747 encrypt_caps|
2748 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2749 (large_write ?
2750 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2751 break;
2754 case SMB_QUERY_POSIX_FS_INFO:
2756 int rc;
2757 vfs_statvfs_struct svfs;
2759 if (!lp_unix_extensions()) {
2760 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2761 return;
2764 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2766 if (!rc) {
2767 data_len = 56;
2768 SIVAL(pdata,0,svfs.OptimalTransferSize);
2769 SIVAL(pdata,4,svfs.BlockSize);
2770 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2771 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2772 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2773 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2774 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2775 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2776 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2777 #ifdef EOPNOTSUPP
2778 } else if (rc == EOPNOTSUPP) {
2779 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2780 return;
2781 #endif /* EOPNOTSUPP */
2782 } else {
2783 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2784 reply_doserror(req, ERRSRV, ERRerror);
2785 return;
2787 break;
2790 case SMB_QUERY_POSIX_WHOAMI:
2792 uint32_t flags = 0;
2793 uint32_t sid_bytes;
2794 int i;
2796 if (!lp_unix_extensions()) {
2797 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2798 return;
2801 if (max_data_bytes < 40) {
2802 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2803 return;
2806 /* We ARE guest if global_sid_Builtin_Guests is
2807 * in our list of SIDs.
2809 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2810 current_user.nt_user_token)) {
2811 flags |= SMB_WHOAMI_GUEST;
2814 /* We are NOT guest if global_sid_Authenticated_Users
2815 * is in our list of SIDs.
2817 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2818 current_user.nt_user_token)) {
2819 flags &= ~SMB_WHOAMI_GUEST;
2822 /* NOTE: 8 bytes for UID/GID, irrespective of native
2823 * platform size. This matches
2824 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2826 data_len = 4 /* flags */
2827 + 4 /* flag mask */
2828 + 8 /* uid */
2829 + 8 /* gid */
2830 + 4 /* ngroups */
2831 + 4 /* num_sids */
2832 + 4 /* SID bytes */
2833 + 4 /* pad/reserved */
2834 + (current_user.ut.ngroups * 8)
2835 /* groups list */
2836 + (current_user.nt_user_token->num_sids *
2837 SID_MAX_SIZE)
2838 /* SID list */;
2840 SIVAL(pdata, 0, flags);
2841 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2842 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2843 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2846 if (data_len >= max_data_bytes) {
2847 /* Potential overflow, skip the GIDs and SIDs. */
2849 SIVAL(pdata, 24, 0); /* num_groups */
2850 SIVAL(pdata, 28, 0); /* num_sids */
2851 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2852 SIVAL(pdata, 36, 0); /* reserved */
2854 data_len = 40;
2855 break;
2858 SIVAL(pdata, 24, current_user.ut.ngroups);
2859 SIVAL(pdata, 28,
2860 current_user.nt_user_token->num_sids);
2862 /* We walk the SID list twice, but this call is fairly
2863 * infrequent, and I don't expect that it's performance
2864 * sensitive -- jpeach
2866 for (i = 0, sid_bytes = 0;
2867 i < current_user.nt_user_token->num_sids; ++i) {
2868 sid_bytes += ndr_size_dom_sid(
2869 &current_user.nt_user_token->user_sids[i], 0);
2872 /* SID list byte count */
2873 SIVAL(pdata, 32, sid_bytes);
2875 /* 4 bytes pad/reserved - must be zero */
2876 SIVAL(pdata, 36, 0);
2877 data_len = 40;
2879 /* GID list */
2880 for (i = 0; i < current_user.ut.ngroups; ++i) {
2881 SBIG_UINT(pdata, data_len,
2882 (SMB_BIG_UINT)current_user.ut.groups[i]);
2883 data_len += 8;
2886 /* SID list */
2887 for (i = 0;
2888 i < current_user.nt_user_token->num_sids; ++i) {
2889 int sid_len = ndr_size_dom_sid(
2890 &current_user.nt_user_token->user_sids[i], 0);
2892 sid_linearize(pdata + data_len, sid_len,
2893 &current_user.nt_user_token->user_sids[i]);
2894 data_len += sid_len;
2897 break;
2900 case SMB_MAC_QUERY_FS_INFO:
2902 * Thursby MAC extension... ONLY on NTFS filesystems
2903 * once we do streams then we don't need this
2905 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2906 data_len = 88;
2907 SIVAL(pdata,84,0x100); /* Don't support mac... */
2908 break;
2910 /* drop through */
2911 default:
2912 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2913 return;
2917 send_trans2_replies(conn, req, params, 0, pdata, data_len,
2918 max_data_bytes);
2920 DEBUG( 4, ( "%s info_level = %d\n",
2921 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2923 return;
2926 /****************************************************************************
2927 Reply to a TRANS2_SETFSINFO (set filesystem info).
2928 ****************************************************************************/
2930 static void call_trans2setfsinfo(connection_struct *conn,
2931 struct smb_request *req,
2932 char **pparams, int total_params,
2933 char **ppdata, int total_data,
2934 unsigned int max_data_bytes)
2936 char *pdata = *ppdata;
2937 char *params = *pparams;
2938 uint16 info_level;
2940 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2942 /* */
2943 if (total_params < 4) {
2944 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2945 total_params));
2946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2947 return;
2950 info_level = SVAL(params,2);
2952 if (IS_IPC(conn)) {
2953 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
2954 info_level != SMB_SET_CIFS_UNIX_INFO) {
2955 DEBUG(0,("call_trans2setfsinfo: not an allowed "
2956 "info level (0x%x) on IPC$.\n",
2957 (unsigned int)info_level));
2958 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2959 return;
2963 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2964 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
2965 DEBUG(0,("call_trans2setfsinfo: encryption required "
2966 "and info level 0x%x sent.\n",
2967 (unsigned int)info_level));
2968 exit_server_cleanly("encryption required "
2969 "on connection");
2970 return;
2974 switch(info_level) {
2975 case SMB_SET_CIFS_UNIX_INFO:
2977 uint16 client_unix_major;
2978 uint16 client_unix_minor;
2979 uint32 client_unix_cap_low;
2980 uint32 client_unix_cap_high;
2982 if (!lp_unix_extensions()) {
2983 reply_nterror(req,
2984 NT_STATUS_INVALID_LEVEL);
2985 return;
2988 /* There should be 12 bytes of capabilities set. */
2989 if (total_data < 8) {
2990 reply_nterror(
2991 req,
2992 NT_STATUS_INVALID_PARAMETER);
2993 return;
2995 client_unix_major = SVAL(pdata,0);
2996 client_unix_minor = SVAL(pdata,2);
2997 client_unix_cap_low = IVAL(pdata,4);
2998 client_unix_cap_high = IVAL(pdata,8);
2999 /* Just print these values for now. */
3000 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3001 cap_low = 0x%x, cap_high = 0x%x\n",
3002 (unsigned int)client_unix_major,
3003 (unsigned int)client_unix_minor,
3004 (unsigned int)client_unix_cap_low,
3005 (unsigned int)client_unix_cap_high ));
3007 /* Here is where we must switch to posix pathname processing... */
3008 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3009 lp_set_posix_pathnames();
3010 mangle_change_to_posix();
3013 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3014 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3015 /* Client that knows how to do posix locks,
3016 * but not posix open/mkdir operations. Set a
3017 * default type for read/write checks. */
3019 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3022 break;
3025 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3027 NTSTATUS status;
3028 size_t param_len = 0;
3029 size_t data_len = total_data;
3031 if (!lp_unix_extensions()) {
3032 reply_nterror(
3033 req,
3034 NT_STATUS_INVALID_LEVEL);
3035 return;
3038 if (lp_smb_encrypt(SNUM(conn)) == false) {
3039 reply_nterror(
3040 req,
3041 NT_STATUS_NOT_SUPPORTED);
3042 return;
3045 DEBUG( 4,("call_trans2setfsinfo: "
3046 "request transport encrption.\n"));
3048 status = srv_request_encryption_setup(conn,
3049 (unsigned char **)ppdata,
3050 &data_len,
3051 (unsigned char **)pparams,
3052 &param_len);
3054 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3055 !NT_STATUS_IS_OK(status)) {
3056 reply_nterror(req, status);
3057 return;
3060 send_trans2_replies(conn, req,
3061 *pparams,
3062 param_len,
3063 *ppdata,
3064 data_len,
3065 max_data_bytes);
3067 if (NT_STATUS_IS_OK(status)) {
3068 /* Server-side transport
3069 * encryption is now *on*. */
3070 status = srv_encryption_start(conn);
3071 if (!NT_STATUS_IS_OK(status)) {
3072 exit_server_cleanly(
3073 "Failure in setting "
3074 "up encrypted transport");
3077 return;
3080 case SMB_FS_QUOTA_INFORMATION:
3082 files_struct *fsp = NULL;
3083 SMB_NTQUOTA_STRUCT quotas;
3085 ZERO_STRUCT(quotas);
3087 /* access check */
3088 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3089 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3090 lp_servicename(SNUM(conn)),conn->user));
3091 reply_doserror(req, ERRSRV, ERRaccess);
3092 return;
3095 /* note: normaly there're 48 bytes,
3096 * but we didn't use the last 6 bytes for now
3097 * --metze
3099 fsp = file_fsp(SVAL(params,0));
3100 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3101 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3102 reply_nterror(
3103 req, NT_STATUS_INVALID_HANDLE);
3104 return;
3107 if (total_data < 42) {
3108 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3109 total_data));
3110 reply_nterror(
3111 req,
3112 NT_STATUS_INVALID_PARAMETER);
3113 return;
3116 /* unknown_1 24 NULL bytes in pdata*/
3118 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3119 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3120 #ifdef LARGE_SMB_OFF_T
3121 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3122 #else /* LARGE_SMB_OFF_T */
3123 if ((IVAL(pdata,28) != 0)&&
3124 ((quotas.softlim != 0xFFFFFFFF)||
3125 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3126 /* more than 32 bits? */
3127 reply_nterror(
3128 req,
3129 NT_STATUS_INVALID_PARAMETER);
3130 return;
3132 #endif /* LARGE_SMB_OFF_T */
3134 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3135 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3136 #ifdef LARGE_SMB_OFF_T
3137 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3138 #else /* LARGE_SMB_OFF_T */
3139 if ((IVAL(pdata,36) != 0)&&
3140 ((quotas.hardlim != 0xFFFFFFFF)||
3141 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3142 /* more than 32 bits? */
3143 reply_nterror(
3144 req,
3145 NT_STATUS_INVALID_PARAMETER);
3146 return;
3148 #endif /* LARGE_SMB_OFF_T */
3150 /* quota_flags 2 bytes **/
3151 quotas.qflags = SVAL(pdata,40);
3153 /* unknown_2 6 NULL bytes follow*/
3155 /* now set the quotas */
3156 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3157 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3158 reply_doserror(req, ERRSRV, ERRerror);
3159 return;
3162 break;
3164 default:
3165 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3166 info_level));
3167 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3168 return;
3169 break;
3173 * sending this reply works fine,
3174 * but I'm not sure it's the same
3175 * like windows do...
3176 * --metze
3178 reply_outbuf(req, 10, 0);
3181 #if defined(HAVE_POSIX_ACLS)
3182 /****************************************************************************
3183 Utility function to count the number of entries in a POSIX acl.
3184 ****************************************************************************/
3186 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3188 unsigned int ace_count = 0;
3189 int entry_id = SMB_ACL_FIRST_ENTRY;
3190 SMB_ACL_ENTRY_T entry;
3192 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3193 /* get_next... */
3194 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3195 entry_id = SMB_ACL_NEXT_ENTRY;
3197 ace_count++;
3199 return ace_count;
3202 /****************************************************************************
3203 Utility function to marshall a POSIX acl into wire format.
3204 ****************************************************************************/
3206 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3208 int entry_id = SMB_ACL_FIRST_ENTRY;
3209 SMB_ACL_ENTRY_T entry;
3211 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3212 SMB_ACL_TAG_T tagtype;
3213 SMB_ACL_PERMSET_T permset;
3214 unsigned char perms = 0;
3215 unsigned int own_grp;
3217 /* get_next... */
3218 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3219 entry_id = SMB_ACL_NEXT_ENTRY;
3222 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3223 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3224 return False;
3227 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3228 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3229 return False;
3232 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3233 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3234 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3236 SCVAL(pdata,1,perms);
3238 switch (tagtype) {
3239 case SMB_ACL_USER_OBJ:
3240 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3241 own_grp = (unsigned int)pst->st_uid;
3242 SIVAL(pdata,2,own_grp);
3243 SIVAL(pdata,6,0);
3244 break;
3245 case SMB_ACL_USER:
3247 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3248 if (!puid) {
3249 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3250 return False;
3252 own_grp = (unsigned int)*puid;
3253 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3254 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3255 SIVAL(pdata,2,own_grp);
3256 SIVAL(pdata,6,0);
3257 break;
3259 case SMB_ACL_GROUP_OBJ:
3260 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3261 own_grp = (unsigned int)pst->st_gid;
3262 SIVAL(pdata,2,own_grp);
3263 SIVAL(pdata,6,0);
3264 break;
3265 case SMB_ACL_GROUP:
3267 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3268 if (!pgid) {
3269 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3270 return False;
3272 own_grp = (unsigned int)*pgid;
3273 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3274 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3275 SIVAL(pdata,2,own_grp);
3276 SIVAL(pdata,6,0);
3277 break;
3279 case SMB_ACL_MASK:
3280 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3281 SIVAL(pdata,2,0xFFFFFFFF);
3282 SIVAL(pdata,6,0xFFFFFFFF);
3283 break;
3284 case SMB_ACL_OTHER:
3285 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3286 SIVAL(pdata,2,0xFFFFFFFF);
3287 SIVAL(pdata,6,0xFFFFFFFF);
3288 break;
3289 default:
3290 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3291 return False;
3293 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3296 return True;
3298 #endif
3300 /****************************************************************************
3301 Store the FILE_UNIX_BASIC info.
3302 ****************************************************************************/
3304 static char *store_file_unix_basic(connection_struct *conn,
3305 char *pdata,
3306 files_struct *fsp,
3307 const SMB_STRUCT_STAT *psbuf)
3309 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3310 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3312 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3313 pdata += 8;
3315 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3316 pdata += 8;
3318 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3319 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3320 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3321 pdata += 24;
3323 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3324 SIVAL(pdata,4,0);
3325 pdata += 8;
3327 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3328 SIVAL(pdata,4,0);
3329 pdata += 8;
3331 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3332 pdata += 4;
3334 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3335 SIVAL(pdata,4,0);
3336 pdata += 8;
3338 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3339 SIVAL(pdata,4,0);
3340 pdata += 8;
3342 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3343 pdata += 8;
3345 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3346 SIVAL(pdata,4,0);
3347 pdata += 8;
3349 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3350 SIVAL(pdata,4,0);
3351 pdata += 8;
3353 return pdata;
3356 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3357 * the chflags(2) (or equivalent) flags.
3359 * XXX: this really should be behind the VFS interface. To do this, we would
3360 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3361 * Each VFS module could then implement its own mapping as appropriate for the
3362 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3364 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3365 info2_flags_map[] =
3367 #ifdef UF_NODUMP
3368 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3369 #endif
3371 #ifdef UF_IMMUTABLE
3372 { UF_IMMUTABLE, EXT_IMMUTABLE },
3373 #endif
3375 #ifdef UF_APPEND
3376 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3377 #endif
3379 #ifdef UF_HIDDEN
3380 { UF_HIDDEN, EXT_HIDDEN },
3381 #endif
3383 /* Do not remove. We need to guarantee that this array has at least one
3384 * entry to build on HP-UX.
3386 { 0, 0 }
3390 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3391 uint32 *smb_fflags, uint32 *smb_fmask)
3393 #ifdef HAVE_STAT_ST_FLAGS
3394 int i;
3396 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3397 *smb_fmask |= info2_flags_map[i].smb_fflag;
3398 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3399 *smb_fflags |= info2_flags_map[i].smb_fflag;
3402 #endif /* HAVE_STAT_ST_FLAGS */
3405 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3406 const uint32 smb_fflags,
3407 const uint32 smb_fmask,
3408 int *stat_fflags)
3410 #ifdef HAVE_STAT_ST_FLAGS
3411 uint32 max_fmask = 0;
3412 int i;
3414 *stat_fflags = psbuf->st_flags;
3416 /* For each flags requested in smb_fmask, check the state of the
3417 * corresponding flag in smb_fflags and set or clear the matching
3418 * stat flag.
3421 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3422 max_fmask |= info2_flags_map[i].smb_fflag;
3423 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3424 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3425 *stat_fflags |= info2_flags_map[i].stat_fflag;
3426 } else {
3427 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3432 /* If smb_fmask is asking to set any bits that are not supported by
3433 * our flag mappings, we should fail.
3435 if ((smb_fmask & max_fmask) != smb_fmask) {
3436 return False;
3439 return True;
3440 #else
3441 return False;
3442 #endif /* HAVE_STAT_ST_FLAGS */
3446 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3447 * of file flags and birth (create) time.
3449 static char *store_file_unix_basic_info2(connection_struct *conn,
3450 char *pdata,
3451 files_struct *fsp,
3452 const SMB_STRUCT_STAT *psbuf)
3454 uint32 file_flags = 0;
3455 uint32 flags_mask = 0;
3457 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3459 /* Create (birth) time 64 bit */
3460 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3461 pdata += 8;
3463 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3464 SIVAL(pdata, 0, file_flags); /* flags */
3465 SIVAL(pdata, 4, flags_mask); /* mask */
3466 pdata += 8;
3468 return pdata;
3471 /****************************************************************************
3472 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3473 ****************************************************************************/
3475 static void call_trans2qpipeinfo(connection_struct *conn,
3476 struct smb_request *req,
3477 unsigned int tran_call,
3478 char **pparams, int total_params,
3479 char **ppdata, int total_data,
3480 unsigned int max_data_bytes)
3482 char *params = *pparams;
3483 char *pdata = *ppdata;
3484 unsigned int data_size = 0;
3485 unsigned int param_size = 2;
3486 uint16 info_level;
3487 smb_np_struct *p_pipe = NULL;
3489 if (!params) {
3490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3491 return;
3494 if (total_params < 4) {
3495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3496 return;
3499 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3500 if (p_pipe == NULL) {
3501 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3502 return;
3505 info_level = SVAL(params,2);
3507 *pparams = (char *)SMB_REALLOC(*pparams,2);
3508 if (*pparams == NULL) {
3509 reply_nterror(req, NT_STATUS_NO_MEMORY);
3510 return;
3512 params = *pparams;
3513 SSVAL(params,0,0);
3514 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3515 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3516 if (*ppdata == NULL ) {
3517 reply_nterror(req, NT_STATUS_NO_MEMORY);
3518 return;
3520 pdata = *ppdata;
3522 switch (info_level) {
3523 case SMB_FILE_STANDARD_INFORMATION:
3524 memset(pdata,0,24);
3525 SOFF_T(pdata,0,4096LL);
3526 SIVAL(pdata,16,1);
3527 SIVAL(pdata,20,1);
3528 data_size = 24;
3529 break;
3531 default:
3532 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3533 return;
3536 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3537 max_data_bytes);
3539 return;
3542 /****************************************************************************
3543 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3544 file name or file id).
3545 ****************************************************************************/
3547 static void call_trans2qfilepathinfo(connection_struct *conn,
3548 struct smb_request *req,
3549 unsigned int tran_call,
3550 char **pparams, int total_params,
3551 char **ppdata, int total_data,
3552 unsigned int max_data_bytes)
3554 char *params = *pparams;
3555 char *pdata = *ppdata;
3556 char *dstart, *dend;
3557 uint16 info_level;
3558 int mode=0;
3559 int nlink;
3560 SMB_OFF_T file_size=0;
3561 SMB_BIG_UINT allocation_size=0;
3562 unsigned int data_size = 0;
3563 unsigned int param_size = 2;
3564 SMB_STRUCT_STAT sbuf;
3565 char *dos_fname = NULL;
3566 char *fname = NULL;
3567 char *fullpathname;
3568 char *base_name;
3569 char *p;
3570 SMB_OFF_T pos = 0;
3571 bool delete_pending = False;
3572 int len;
3573 time_t create_time, mtime, atime;
3574 struct timespec create_time_ts, mtime_ts, atime_ts;
3575 files_struct *fsp = NULL;
3576 struct file_id fileid;
3577 struct ea_list *ea_list = NULL;
3578 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3579 char *lock_data = NULL;
3580 TALLOC_CTX *ctx = talloc_tos();
3582 if (!params) {
3583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3584 return;
3587 ZERO_STRUCT(sbuf);
3589 if (tran_call == TRANSACT2_QFILEINFO) {
3590 if (total_params < 4) {
3591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3592 return;
3595 if (IS_IPC(conn)) {
3596 call_trans2qpipeinfo(conn, req, tran_call,
3597 pparams, total_params,
3598 ppdata, total_data,
3599 max_data_bytes);
3600 return;
3603 fsp = file_fsp(SVAL(params,0));
3604 info_level = SVAL(params,2);
3606 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3608 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3609 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3610 return;
3613 /* Initial check for valid fsp ptr. */
3614 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3615 return;
3618 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3619 if (!fname) {
3620 reply_nterror(req, NT_STATUS_NO_MEMORY);
3621 return;
3624 if(fsp->fake_file_handle) {
3626 * This is actually for the QUOTA_FAKE_FILE --metze
3629 /* We know this name is ok, it's already passed the checks. */
3631 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3633 * This is actually a QFILEINFO on a directory
3634 * handle (returned from an NT SMB). NT5.0 seems
3635 * to do this call. JRA.
3638 if (INFO_LEVEL_IS_UNIX(info_level)) {
3639 /* Always do lstat for UNIX calls. */
3640 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3641 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3642 reply_unixerror(req,ERRDOS,ERRbadpath);
3643 return;
3645 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3646 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3647 reply_unixerror(req, ERRDOS, ERRbadpath);
3648 return;
3651 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3652 delete_pending = get_delete_on_close_flag(fileid);
3653 } else {
3655 * Original code - this is an open file.
3657 if (!check_fsp(conn, req, fsp, &current_user)) {
3658 return;
3661 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3662 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3663 reply_unixerror(req, ERRDOS, ERRbadfid);
3664 return;
3666 pos = fsp->fh->position_information;
3667 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3668 delete_pending = get_delete_on_close_flag(fileid);
3669 access_mask = fsp->access_mask;
3672 } else {
3673 NTSTATUS status = NT_STATUS_OK;
3675 /* qpathinfo */
3676 if (total_params < 7) {
3677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3678 return;
3681 info_level = SVAL(params,0);
3683 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3685 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3686 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3687 return;
3690 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3691 total_params - 6,
3692 STR_TERMINATE, &status);
3693 if (!NT_STATUS_IS_OK(status)) {
3694 reply_nterror(req, status);
3695 return;
3698 status = resolve_dfspath(ctx,
3699 conn,
3700 req->flags2 & FLAGS2_DFS_PATHNAMES,
3701 fname,
3702 &fname);
3703 if (!NT_STATUS_IS_OK(status)) {
3704 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3705 reply_botherror(req,
3706 NT_STATUS_PATH_NOT_COVERED,
3707 ERRSRV, ERRbadpath);
3709 reply_nterror(req, status);
3710 return;
3713 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3714 if (!NT_STATUS_IS_OK(status)) {
3715 reply_nterror(req, status);
3716 return;
3718 status = check_name(conn, fname);
3719 if (!NT_STATUS_IS_OK(status)) {
3720 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3721 reply_nterror(req, status);
3722 return;
3725 if (INFO_LEVEL_IS_UNIX(info_level)) {
3726 /* Always do lstat for UNIX calls. */
3727 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3728 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3729 reply_unixerror(req, ERRDOS, ERRbadpath);
3730 return;
3732 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3733 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3734 reply_unixerror(req, ERRDOS, ERRbadpath);
3735 return;
3738 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3739 delete_pending = get_delete_on_close_flag(fileid);
3740 if (delete_pending) {
3741 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3742 return;
3746 nlink = sbuf.st_nlink;
3748 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3749 /* NTFS does not seem to count ".." */
3750 nlink -= 1;
3753 if ((nlink > 0) && delete_pending) {
3754 nlink -= 1;
3757 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3758 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3759 return;
3762 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3763 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3765 p = strrchr_m(fname,'/');
3766 if (!p)
3767 base_name = fname;
3768 else
3769 base_name = p+1;
3771 mode = dos_mode(conn,fname,&sbuf);
3772 if (!mode)
3773 mode = FILE_ATTRIBUTE_NORMAL;
3775 fullpathname = fname;
3776 if (!(mode & aDIR))
3777 file_size = get_file_size(sbuf);
3779 /* Pull out any data sent here before we realloc. */
3780 switch (info_level) {
3781 case SMB_INFO_QUERY_EAS_FROM_LIST:
3783 /* Pull any EA list from the data portion. */
3784 uint32 ea_size;
3786 if (total_data < 4) {
3787 reply_nterror(
3788 req, NT_STATUS_INVALID_PARAMETER);
3789 return;
3791 ea_size = IVAL(pdata,0);
3793 if (total_data > 0 && ea_size != total_data) {
3794 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3795 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3796 reply_nterror(
3797 req, NT_STATUS_INVALID_PARAMETER);
3798 return;
3801 if (!lp_ea_support(SNUM(conn))) {
3802 reply_doserror(req, ERRDOS,
3803 ERReasnotsupported);
3804 return;
3807 /* Pull out the list of names. */
3808 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3809 if (!ea_list) {
3810 reply_nterror(
3811 req, NT_STATUS_INVALID_PARAMETER);
3812 return;
3814 break;
3817 case SMB_QUERY_POSIX_LOCK:
3819 if (fsp == NULL || fsp->fh->fd == -1) {
3820 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3821 return;
3824 if (total_data != POSIX_LOCK_DATA_SIZE) {
3825 reply_nterror(
3826 req, NT_STATUS_INVALID_PARAMETER);
3827 return;
3830 /* Copy the lock range data. */
3831 lock_data = (char *)TALLOC_MEMDUP(
3832 ctx, pdata, total_data);
3833 if (!lock_data) {
3834 reply_nterror(req, NT_STATUS_NO_MEMORY);
3835 return;
3838 default:
3839 break;
3842 *pparams = (char *)SMB_REALLOC(*pparams,2);
3843 if (*pparams == NULL) {
3844 reply_nterror(req, NT_STATUS_NO_MEMORY);
3845 return;
3847 params = *pparams;
3848 SSVAL(params,0,0);
3849 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3850 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3851 if (*ppdata == NULL ) {
3852 reply_nterror(req, NT_STATUS_NO_MEMORY);
3853 return;
3855 pdata = *ppdata;
3856 dstart = pdata;
3857 dend = dstart + data_size - 1;
3859 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3860 mtime_ts = get_mtimespec(&sbuf);
3861 atime_ts = get_atimespec(&sbuf);
3863 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3865 if (fsp) {
3866 if (!null_timespec(fsp->pending_modtime)) {
3867 /* the pending modtime overrides the current modtime */
3868 mtime_ts = fsp->pending_modtime;
3870 } else {
3871 files_struct *fsp1;
3872 /* Do we have this path open ? */
3873 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3874 fsp1 = file_find_di_first(fileid);
3875 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3876 /* the pending modtime overrides the current modtime */
3877 mtime_ts = fsp1->pending_modtime;
3879 if (fsp1 && fsp1->initial_allocation_size) {
3880 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3884 if (lp_dos_filetime_resolution(SNUM(conn))) {
3885 dos_filetime_timespec(&create_time_ts);
3886 dos_filetime_timespec(&mtime_ts);
3887 dos_filetime_timespec(&atime_ts);
3890 create_time = convert_timespec_to_time_t(create_time_ts);
3891 mtime = convert_timespec_to_time_t(mtime_ts);
3892 atime = convert_timespec_to_time_t(atime_ts);
3894 /* NT expects the name to be in an exact form of the *full*
3895 filename. See the trans2 torture test */
3896 if (ISDOT(base_name)) {
3897 dos_fname = talloc_strdup(ctx, "\\");
3898 if (!dos_fname) {
3899 reply_nterror(req, NT_STATUS_NO_MEMORY);
3900 return;
3902 } else {
3903 dos_fname = talloc_asprintf(ctx,
3904 "\\%s",
3905 fname);
3906 if (!dos_fname) {
3907 reply_nterror(req, NT_STATUS_NO_MEMORY);
3908 return;
3910 string_replace(dos_fname, '/', '\\');
3913 switch (info_level) {
3914 case SMB_INFO_STANDARD:
3915 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3916 data_size = 22;
3917 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3918 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3919 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3920 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3921 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3922 SSVAL(pdata,l1_attrFile,mode);
3923 break;
3925 case SMB_INFO_QUERY_EA_SIZE:
3927 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3928 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3929 data_size = 26;
3930 srv_put_dos_date2(pdata,0,create_time);
3931 srv_put_dos_date2(pdata,4,atime);
3932 srv_put_dos_date2(pdata,8,mtime); /* write time */
3933 SIVAL(pdata,12,(uint32)file_size);
3934 SIVAL(pdata,16,(uint32)allocation_size);
3935 SSVAL(pdata,20,mode);
3936 SIVAL(pdata,22,ea_size);
3937 break;
3940 case SMB_INFO_IS_NAME_VALID:
3941 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3942 if (tran_call == TRANSACT2_QFILEINFO) {
3943 /* os/2 needs this ? really ?*/
3944 reply_doserror(req, ERRDOS, ERRbadfunc);
3945 return;
3947 data_size = 0;
3948 param_size = 0;
3949 break;
3951 case SMB_INFO_QUERY_EAS_FROM_LIST:
3953 size_t total_ea_len = 0;
3954 struct ea_list *ea_file_list = NULL;
3956 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3958 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3959 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3961 if (!ea_list || (total_ea_len > data_size)) {
3962 data_size = 4;
3963 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3964 break;
3967 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3968 break;
3971 case SMB_INFO_QUERY_ALL_EAS:
3973 /* We have data_size bytes to put EA's into. */
3974 size_t total_ea_len = 0;
3976 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3978 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3979 if (!ea_list || (total_ea_len > data_size)) {
3980 data_size = 4;
3981 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3982 break;
3985 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3986 break;
3989 case SMB_FILE_BASIC_INFORMATION:
3990 case SMB_QUERY_FILE_BASIC_INFO:
3992 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3993 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3994 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3995 } else {
3996 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3997 data_size = 40;
3998 SIVAL(pdata,36,0);
4000 put_long_date_timespec(pdata,create_time_ts);
4001 put_long_date_timespec(pdata+8,atime_ts);
4002 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4003 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4004 SIVAL(pdata,32,mode);
4006 DEBUG(5,("SMB_QFBI - "));
4007 DEBUG(5,("create: %s ", ctime(&create_time)));
4008 DEBUG(5,("access: %s ", ctime(&atime)));
4009 DEBUG(5,("write: %s ", ctime(&mtime)));
4010 DEBUG(5,("change: %s ", ctime(&mtime)));
4011 DEBUG(5,("mode: %x\n", mode));
4012 break;
4014 case SMB_FILE_STANDARD_INFORMATION:
4015 case SMB_QUERY_FILE_STANDARD_INFO:
4017 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4018 data_size = 24;
4019 SOFF_T(pdata,0,allocation_size);
4020 SOFF_T(pdata,8,file_size);
4021 SIVAL(pdata,16,nlink);
4022 SCVAL(pdata,20,delete_pending?1:0);
4023 SCVAL(pdata,21,(mode&aDIR)?1:0);
4024 SSVAL(pdata,22,0); /* Padding. */
4025 break;
4027 case SMB_FILE_EA_INFORMATION:
4028 case SMB_QUERY_FILE_EA_INFO:
4030 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4031 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4032 data_size = 4;
4033 SIVAL(pdata,0,ea_size);
4034 break;
4037 /* Get the 8.3 name - used if NT SMB was negotiated. */
4038 case SMB_QUERY_FILE_ALT_NAME_INFO:
4039 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4041 char mangled_name[13];
4042 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4043 if (!name_to_8_3(base_name,mangled_name,
4044 True,conn->params)) {
4045 reply_nterror(
4046 req,
4047 NT_STATUS_NO_MEMORY);
4049 len = srvstr_push(dstart, req->flags2,
4050 pdata+4, mangled_name,
4051 PTR_DIFF(dend, pdata+4),
4052 STR_UNICODE);
4053 data_size = 4 + len;
4054 SIVAL(pdata,0,len);
4055 break;
4058 case SMB_QUERY_FILE_NAME_INFO:
4060 this must be *exactly* right for ACLs on mapped drives to work
4062 len = srvstr_push(dstart, req->flags2,
4063 pdata+4, dos_fname,
4064 PTR_DIFF(dend, pdata+4),
4065 STR_UNICODE);
4066 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4067 data_size = 4 + len;
4068 SIVAL(pdata,0,len);
4069 break;
4071 case SMB_FILE_ALLOCATION_INFORMATION:
4072 case SMB_QUERY_FILE_ALLOCATION_INFO:
4073 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4074 data_size = 8;
4075 SOFF_T(pdata,0,allocation_size);
4076 break;
4078 case SMB_FILE_END_OF_FILE_INFORMATION:
4079 case SMB_QUERY_FILE_END_OF_FILEINFO:
4080 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4081 data_size = 8;
4082 SOFF_T(pdata,0,file_size);
4083 break;
4085 case SMB_QUERY_FILE_ALL_INFO:
4086 case SMB_FILE_ALL_INFORMATION:
4088 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4089 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4090 put_long_date_timespec(pdata,create_time_ts);
4091 put_long_date_timespec(pdata+8,atime_ts);
4092 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4093 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4094 SIVAL(pdata,32,mode);
4095 SIVAL(pdata,36,0); /* padding. */
4096 pdata += 40;
4097 SOFF_T(pdata,0,allocation_size);
4098 SOFF_T(pdata,8,file_size);
4099 SIVAL(pdata,16,nlink);
4100 SCVAL(pdata,20,delete_pending);
4101 SCVAL(pdata,21,(mode&aDIR)?1:0);
4102 SSVAL(pdata,22,0);
4103 pdata += 24;
4104 SIVAL(pdata,0,ea_size);
4105 pdata += 4; /* EA info */
4106 len = srvstr_push(dstart, req->flags2,
4107 pdata+4, dos_fname,
4108 PTR_DIFF(dend, pdata+4),
4109 STR_UNICODE);
4110 SIVAL(pdata,0,len);
4111 pdata += 4 + len;
4112 data_size = PTR_DIFF(pdata,(*ppdata));
4113 break;
4115 case SMB_FILE_INTERNAL_INFORMATION:
4116 /* This should be an index number - looks like
4117 dev/ino to me :-)
4119 I think this causes us to fail the IFSKIT
4120 BasicFileInformationTest. -tpot */
4122 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4123 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4124 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4125 data_size = 8;
4126 break;
4128 case SMB_FILE_ACCESS_INFORMATION:
4129 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4130 SIVAL(pdata,0,access_mask);
4131 data_size = 4;
4132 break;
4134 case SMB_FILE_NAME_INFORMATION:
4135 /* Pathname with leading '\'. */
4137 size_t byte_len;
4138 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4139 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4140 SIVAL(pdata,0,byte_len);
4141 data_size = 4 + byte_len;
4142 break;
4145 case SMB_FILE_DISPOSITION_INFORMATION:
4146 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4147 data_size = 1;
4148 SCVAL(pdata,0,delete_pending);
4149 break;
4151 case SMB_FILE_POSITION_INFORMATION:
4152 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4153 data_size = 8;
4154 SOFF_T(pdata,0,pos);
4155 break;
4157 case SMB_FILE_MODE_INFORMATION:
4158 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4159 SIVAL(pdata,0,mode);
4160 data_size = 4;
4161 break;
4163 case SMB_FILE_ALIGNMENT_INFORMATION:
4164 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4165 SIVAL(pdata,0,0); /* No alignment needed. */
4166 data_size = 4;
4167 break;
4169 #if 0
4171 * NT4 server just returns "invalid query" to this - if we try to answer
4172 * it then NTws gets a BSOD! (tridge).
4173 * W2K seems to want this. JRA.
4175 case SMB_QUERY_FILE_STREAM_INFO:
4176 #endif
4177 case SMB_FILE_STREAM_INFORMATION:
4178 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4179 if (mode & aDIR) {
4180 data_size = 0;
4181 } else {
4182 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4183 SIVAL(pdata,0,0); /* ??? */
4184 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4185 SOFF_T(pdata,8,file_size);
4186 SOFF_T(pdata,16,allocation_size);
4187 data_size = 24 + byte_len;
4189 break;
4191 case SMB_QUERY_COMPRESSION_INFO:
4192 case SMB_FILE_COMPRESSION_INFORMATION:
4193 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4194 SOFF_T(pdata,0,file_size);
4195 SIVAL(pdata,8,0); /* ??? */
4196 SIVAL(pdata,12,0); /* ??? */
4197 data_size = 16;
4198 break;
4200 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4201 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4202 put_long_date_timespec(pdata,create_time_ts);
4203 put_long_date_timespec(pdata+8,atime_ts);
4204 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4205 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4206 SOFF_T(pdata,32,allocation_size);
4207 SOFF_T(pdata,40,file_size);
4208 SIVAL(pdata,48,mode);
4209 SIVAL(pdata,52,0); /* ??? */
4210 data_size = 56;
4211 break;
4213 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4214 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4215 SIVAL(pdata,0,mode);
4216 SIVAL(pdata,4,0);
4217 data_size = 8;
4218 break;
4221 * CIFS UNIX Extensions.
4224 case SMB_QUERY_FILE_UNIX_BASIC:
4226 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4227 data_size = PTR_DIFF(pdata,(*ppdata));
4230 int i;
4231 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4233 for (i=0; i<100; i++)
4234 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4235 DEBUG(4,("\n"));
4238 break;
4240 case SMB_QUERY_FILE_UNIX_INFO2:
4242 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4243 data_size = PTR_DIFF(pdata,(*ppdata));
4246 int i;
4247 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4249 for (i=0; i<100; i++)
4250 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4251 DEBUG(4,("\n"));
4254 break;
4256 case SMB_QUERY_FILE_UNIX_LINK:
4258 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4260 if (!buffer) {
4261 reply_nterror(req, NT_STATUS_NO_MEMORY);
4262 return;
4265 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4266 #ifdef S_ISLNK
4267 if(!S_ISLNK(sbuf.st_mode)) {
4268 reply_unixerror(req, ERRSRV,
4269 ERRbadlink);
4270 return;
4272 #else
4273 reply_unixerror(req, ERRDOS, ERRbadlink);
4274 return;
4275 #endif
4276 len = SMB_VFS_READLINK(conn,fullpathname,
4277 buffer, PATH_MAX);
4278 if (len == -1) {
4279 reply_unixerror(req, ERRDOS,
4280 ERRnoaccess);
4281 return;
4283 buffer[len] = 0;
4284 len = srvstr_push(dstart, req->flags2,
4285 pdata, buffer,
4286 PTR_DIFF(dend, pdata),
4287 STR_TERMINATE);
4288 pdata += len;
4289 data_size = PTR_DIFF(pdata,(*ppdata));
4291 break;
4294 #if defined(HAVE_POSIX_ACLS)
4295 case SMB_QUERY_POSIX_ACL:
4297 SMB_ACL_T file_acl = NULL;
4298 SMB_ACL_T def_acl = NULL;
4299 uint16 num_file_acls = 0;
4300 uint16 num_def_acls = 0;
4302 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4303 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4304 } else {
4305 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4308 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4309 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4310 fname ));
4311 reply_nterror(
4312 req,
4313 NT_STATUS_NOT_IMPLEMENTED);
4314 return;
4317 if (S_ISDIR(sbuf.st_mode)) {
4318 if (fsp && fsp->is_directory) {
4319 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4320 } else {
4321 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4323 def_acl = free_empty_sys_acl(conn, def_acl);
4326 num_file_acls = count_acl_entries(conn, file_acl);
4327 num_def_acls = count_acl_entries(conn, def_acl);
4329 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4330 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4331 data_size,
4332 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4333 SMB_POSIX_ACL_HEADER_SIZE) ));
4334 if (file_acl) {
4335 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4337 if (def_acl) {
4338 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4340 reply_nterror(
4341 req,
4342 NT_STATUS_BUFFER_TOO_SMALL);
4343 return;
4346 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4347 SSVAL(pdata,2,num_file_acls);
4348 SSVAL(pdata,4,num_def_acls);
4349 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4350 if (file_acl) {
4351 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4353 if (def_acl) {
4354 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4356 reply_nterror(
4357 req, NT_STATUS_INTERNAL_ERROR);
4358 return;
4360 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4361 if (file_acl) {
4362 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4364 if (def_acl) {
4365 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4367 reply_nterror(
4368 req,
4369 NT_STATUS_INTERNAL_ERROR);
4370 return;
4373 if (file_acl) {
4374 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4376 if (def_acl) {
4377 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4379 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4380 break;
4382 #endif
4385 case SMB_QUERY_POSIX_LOCK:
4387 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4388 SMB_BIG_UINT count;
4389 SMB_BIG_UINT offset;
4390 uint32 lock_pid;
4391 enum brl_type lock_type;
4393 if (total_data != POSIX_LOCK_DATA_SIZE) {
4394 reply_nterror(
4395 req, NT_STATUS_INVALID_PARAMETER);
4396 return;
4399 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4400 case POSIX_LOCK_TYPE_READ:
4401 lock_type = READ_LOCK;
4402 break;
4403 case POSIX_LOCK_TYPE_WRITE:
4404 lock_type = WRITE_LOCK;
4405 break;
4406 case POSIX_LOCK_TYPE_UNLOCK:
4407 default:
4408 /* There's no point in asking for an unlock... */
4409 reply_nterror(
4410 req,
4411 NT_STATUS_INVALID_PARAMETER);
4412 return;
4415 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4416 #if defined(HAVE_LONGLONG)
4417 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4418 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4419 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4420 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4421 #else /* HAVE_LONGLONG */
4422 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4423 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4424 #endif /* HAVE_LONGLONG */
4426 status = query_lock(fsp,
4427 &lock_pid,
4428 &count,
4429 &offset,
4430 &lock_type,
4431 POSIX_LOCK);
4433 if (ERROR_WAS_LOCK_DENIED(status)) {
4434 /* Here we need to report who has it locked... */
4435 data_size = POSIX_LOCK_DATA_SIZE;
4437 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4438 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4439 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4440 #if defined(HAVE_LONGLONG)
4441 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4442 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4443 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4444 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4445 #else /* HAVE_LONGLONG */
4446 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4447 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4448 #endif /* HAVE_LONGLONG */
4450 } else if (NT_STATUS_IS_OK(status)) {
4451 /* For success we just return a copy of what we sent
4452 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4453 data_size = POSIX_LOCK_DATA_SIZE;
4454 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4455 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4456 } else {
4457 reply_nterror(req, status);
4458 return;
4460 break;
4463 default:
4464 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4465 return;
4468 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4469 max_data_bytes);
4471 return;
4474 /****************************************************************************
4475 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4476 code.
4477 ****************************************************************************/
4479 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4480 connection_struct *conn,
4481 const char *oldname_in,
4482 const char *newname_in)
4484 SMB_STRUCT_STAT sbuf1, sbuf2;
4485 char *last_component_oldname = NULL;
4486 char *last_component_newname = NULL;
4487 char *oldname = NULL;
4488 char *newname = NULL;
4489 NTSTATUS status = NT_STATUS_OK;
4491 ZERO_STRUCT(sbuf1);
4492 ZERO_STRUCT(sbuf2);
4494 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4495 &last_component_oldname, &sbuf1);
4496 if (!NT_STATUS_IS_OK(status)) {
4497 return status;
4500 status = check_name(conn, oldname);
4501 if (!NT_STATUS_IS_OK(status)) {
4502 return status;
4505 /* source must already exist. */
4506 if (!VALID_STAT(sbuf1)) {
4507 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4510 status = unix_convert(ctx, conn, newname_in, False, &newname,
4511 &last_component_newname, &sbuf2);
4512 if (!NT_STATUS_IS_OK(status)) {
4513 return status;
4516 status = check_name(conn, newname);
4517 if (!NT_STATUS_IS_OK(status)) {
4518 return status;
4521 /* Disallow if newname already exists. */
4522 if (VALID_STAT(sbuf2)) {
4523 return NT_STATUS_OBJECT_NAME_COLLISION;
4526 /* No links from a directory. */
4527 if (S_ISDIR(sbuf1.st_mode)) {
4528 return NT_STATUS_FILE_IS_A_DIRECTORY;
4531 /* Ensure this is within the share. */
4532 status = check_reduced_name(conn, oldname);
4533 if (!NT_STATUS_IS_OK(status)) {
4534 return status;
4537 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4539 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4540 status = map_nt_error_from_unix(errno);
4541 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4542 nt_errstr(status), newname, oldname));
4545 return status;
4548 /****************************************************************************
4549 Deal with setting the time from any of the setfilepathinfo functions.
4550 ****************************************************************************/
4552 static NTSTATUS smb_set_file_time(connection_struct *conn,
4553 files_struct *fsp,
4554 const char *fname,
4555 const SMB_STRUCT_STAT *psbuf,
4556 struct timespec ts[2],
4557 bool setting_write_time)
4559 uint32 action =
4560 FILE_NOTIFY_CHANGE_LAST_ACCESS
4561 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4563 if (!VALID_STAT(*psbuf)) {
4564 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4567 /* get some defaults (no modifications) if any info is zero or -1. */
4568 if (null_timespec(ts[0])) {
4569 ts[0] = get_atimespec(psbuf);
4570 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4573 if (null_timespec(ts[1])) {
4574 ts[1] = get_mtimespec(psbuf);
4575 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4578 if (!setting_write_time) {
4579 /* ts[1] comes from change time, not write time. */
4580 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4583 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4584 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4587 * Try and set the times of this file if
4588 * they are different from the current values.
4592 struct timespec mts = get_mtimespec(psbuf);
4593 struct timespec ats = get_atimespec(psbuf);
4594 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4595 return NT_STATUS_OK;
4599 if(fsp != NULL) {
4601 * This was a setfileinfo on an open file.
4602 * NT does this a lot. We also need to
4603 * set the time here, as it can be read by
4604 * FindFirst/FindNext and with the patch for bug #2045
4605 * in smbd/fileio.c it ensures that this timestamp is
4606 * kept sticky even after a write. We save the request
4607 * away and will set it on file close and after a write. JRA.
4610 if (!null_timespec(ts[1])) {
4611 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4612 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4613 fsp_set_pending_modtime(fsp, ts[1]);
4617 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4619 if(file_ntimes(conn, fname, ts)!=0) {
4620 return map_nt_error_from_unix(errno);
4622 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4624 return NT_STATUS_OK;
4627 /****************************************************************************
4628 Deal with setting the dosmode from any of the setfilepathinfo functions.
4629 ****************************************************************************/
4631 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4632 const char *fname,
4633 SMB_STRUCT_STAT *psbuf,
4634 uint32 dosmode)
4636 if (!VALID_STAT(*psbuf)) {
4637 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4640 if (dosmode) {
4641 if (S_ISDIR(psbuf->st_mode)) {
4642 dosmode |= aDIR;
4643 } else {
4644 dosmode &= ~aDIR;
4648 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4650 /* check the mode isn't different, before changing it */
4651 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4653 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4654 fname, (unsigned int)dosmode ));
4656 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4657 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4658 fname, strerror(errno)));
4659 return map_nt_error_from_unix(errno);
4662 return NT_STATUS_OK;
4665 /****************************************************************************
4666 Deal with setting the size from any of the setfilepathinfo functions.
4667 ****************************************************************************/
4669 static NTSTATUS smb_set_file_size(connection_struct *conn,
4670 struct smb_request *req,
4671 files_struct *fsp,
4672 const char *fname,
4673 SMB_STRUCT_STAT *psbuf,
4674 SMB_OFF_T size)
4676 NTSTATUS status = NT_STATUS_OK;
4677 files_struct *new_fsp = NULL;
4679 if (!VALID_STAT(*psbuf)) {
4680 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4683 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4685 if (size == get_file_size(*psbuf)) {
4686 return NT_STATUS_OK;
4689 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4690 fname, (double)size ));
4692 if (fsp && fsp->fh->fd != -1) {
4693 /* Handle based call. */
4694 if (vfs_set_filelen(fsp, size) == -1) {
4695 return map_nt_error_from_unix(errno);
4697 return NT_STATUS_OK;
4700 status = open_file_ntcreate(conn, req, fname, psbuf,
4701 FILE_WRITE_DATA,
4702 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4703 FILE_OPEN,
4705 FILE_ATTRIBUTE_NORMAL,
4706 FORCE_OPLOCK_BREAK_TO_NONE,
4707 NULL, &new_fsp);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 /* NB. We check for open_was_deferred in the caller. */
4711 return status;
4714 if (vfs_set_filelen(new_fsp, size) == -1) {
4715 status = map_nt_error_from_unix(errno);
4716 close_file(new_fsp,NORMAL_CLOSE);
4717 return status;
4720 close_file(new_fsp,NORMAL_CLOSE);
4721 return NT_STATUS_OK;
4724 /****************************************************************************
4725 Deal with SMB_INFO_SET_EA.
4726 ****************************************************************************/
4728 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4729 const char *pdata,
4730 int total_data,
4731 files_struct *fsp,
4732 const char *fname)
4734 struct ea_list *ea_list = NULL;
4735 TALLOC_CTX *ctx = NULL;
4736 NTSTATUS status = NT_STATUS_OK;
4738 if (total_data < 10) {
4740 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4741 length. They seem to have no effect. Bug #3212. JRA */
4743 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4744 /* We're done. We only get EA info in this call. */
4745 return NT_STATUS_OK;
4748 return NT_STATUS_INVALID_PARAMETER;
4751 if (IVAL(pdata,0) > total_data) {
4752 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4753 IVAL(pdata,0), (unsigned int)total_data));
4754 return NT_STATUS_INVALID_PARAMETER;
4757 ctx = talloc_tos();
4758 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4759 if (!ea_list) {
4760 return NT_STATUS_INVALID_PARAMETER;
4762 status = set_ea(conn, fsp, fname, ea_list);
4764 return status;
4767 /****************************************************************************
4768 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4769 ****************************************************************************/
4771 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4772 const char *pdata,
4773 int total_data,
4774 files_struct *fsp,
4775 const char *fname,
4776 SMB_STRUCT_STAT *psbuf)
4778 NTSTATUS status = NT_STATUS_OK;
4779 bool delete_on_close;
4780 uint32 dosmode = 0;
4782 if (total_data < 1) {
4783 return NT_STATUS_INVALID_PARAMETER;
4786 if (fsp == NULL) {
4787 return NT_STATUS_INVALID_HANDLE;
4790 delete_on_close = (CVAL(pdata,0) ? True : False);
4791 dosmode = dos_mode(conn, fname, psbuf);
4793 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4794 "delete_on_close = %u\n",
4795 fsp->fsp_name,
4796 (unsigned int)dosmode,
4797 (unsigned int)delete_on_close ));
4799 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4801 if (!NT_STATUS_IS_OK(status)) {
4802 return status;
4805 /* The set is across all open files on this dev/inode pair. */
4806 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4807 return NT_STATUS_ACCESS_DENIED;
4809 return NT_STATUS_OK;
4812 /****************************************************************************
4813 Deal with SMB_FILE_POSITION_INFORMATION.
4814 ****************************************************************************/
4816 static NTSTATUS smb_file_position_information(connection_struct *conn,
4817 const char *pdata,
4818 int total_data,
4819 files_struct *fsp)
4821 SMB_BIG_UINT position_information;
4823 if (total_data < 8) {
4824 return NT_STATUS_INVALID_PARAMETER;
4827 if (fsp == NULL) {
4828 /* Ignore on pathname based set. */
4829 return NT_STATUS_OK;
4832 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4833 #ifdef LARGE_SMB_OFF_T
4834 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4835 #else /* LARGE_SMB_OFF_T */
4836 if (IVAL(pdata,4) != 0) {
4837 /* more than 32 bits? */
4838 return NT_STATUS_INVALID_PARAMETER;
4840 #endif /* LARGE_SMB_OFF_T */
4842 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4843 fsp->fsp_name, (double)position_information ));
4844 fsp->fh->position_information = position_information;
4845 return NT_STATUS_OK;
4848 /****************************************************************************
4849 Deal with SMB_FILE_MODE_INFORMATION.
4850 ****************************************************************************/
4852 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4853 const char *pdata,
4854 int total_data)
4856 uint32 mode;
4858 if (total_data < 4) {
4859 return NT_STATUS_INVALID_PARAMETER;
4861 mode = IVAL(pdata,0);
4862 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4863 return NT_STATUS_INVALID_PARAMETER;
4865 return NT_STATUS_OK;
4868 /****************************************************************************
4869 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4870 ****************************************************************************/
4872 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4873 struct smb_request *req,
4874 const char *pdata,
4875 int total_data,
4876 const char *fname)
4878 char *link_target = NULL;
4879 const char *newname = fname;
4880 NTSTATUS status = NT_STATUS_OK;
4881 TALLOC_CTX *ctx = talloc_tos();
4883 /* Set a symbolic link. */
4884 /* Don't allow this if follow links is false. */
4886 if (total_data == 0) {
4887 return NT_STATUS_INVALID_PARAMETER;
4890 if (!lp_symlinks(SNUM(conn))) {
4891 return NT_STATUS_ACCESS_DENIED;
4894 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4895 total_data, STR_TERMINATE);
4897 if (!link_target) {
4898 return NT_STATUS_INVALID_PARAMETER;
4901 /* !widelinks forces the target path to be within the share. */
4902 /* This means we can interpret the target as a pathname. */
4903 if (!lp_widelinks(SNUM(conn))) {
4904 char *rel_name = NULL;
4905 char *last_dirp = NULL;
4907 if (*link_target == '/') {
4908 /* No absolute paths allowed. */
4909 return NT_STATUS_ACCESS_DENIED;
4911 rel_name = talloc_strdup(ctx,newname);
4912 if (!rel_name) {
4913 return NT_STATUS_NO_MEMORY;
4915 last_dirp = strrchr_m(rel_name, '/');
4916 if (last_dirp) {
4917 last_dirp[1] = '\0';
4918 } else {
4919 rel_name = talloc_strdup(ctx,"./");
4920 if (!rel_name) {
4921 return NT_STATUS_NO_MEMORY;
4924 rel_name = talloc_asprintf_append(rel_name,
4925 "%s",
4926 link_target);
4927 if (!rel_name) {
4928 return NT_STATUS_NO_MEMORY;
4931 status = check_name(conn, rel_name);
4932 if (!NT_STATUS_IS_OK(status)) {
4933 return status;
4937 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4938 newname, link_target ));
4940 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4941 return map_nt_error_from_unix(errno);
4944 return NT_STATUS_OK;
4947 /****************************************************************************
4948 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4949 ****************************************************************************/
4951 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4952 struct smb_request *req,
4953 const char *pdata, int total_data,
4954 const char *fname)
4956 char *oldname = NULL;
4957 TALLOC_CTX *ctx = talloc_tos();
4958 NTSTATUS status = NT_STATUS_OK;
4960 /* Set a hard link. */
4961 if (total_data == 0) {
4962 return NT_STATUS_INVALID_PARAMETER;
4965 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4966 total_data, STR_TERMINATE, &status);
4967 if (!NT_STATUS_IS_OK(status)) {
4968 return status;
4971 status = resolve_dfspath(ctx, conn,
4972 req->flags2 & FLAGS2_DFS_PATHNAMES,
4973 oldname,
4974 &oldname);
4975 if (!NT_STATUS_IS_OK(status)) {
4976 return status;
4979 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4980 fname, oldname));
4982 return hardlink_internals(ctx, conn, oldname, fname);
4985 /****************************************************************************
4986 Deal with SMB_FILE_RENAME_INFORMATION.
4987 ****************************************************************************/
4989 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4990 struct smb_request *req,
4991 const char *pdata,
4992 int total_data,
4993 files_struct *fsp,
4994 const char *fname)
4996 bool overwrite;
4997 uint32 root_fid;
4998 uint32 len;
4999 char *newname = NULL;
5000 char *base_name = NULL;
5001 bool dest_has_wcard = False;
5002 NTSTATUS status = NT_STATUS_OK;
5003 char *p;
5004 TALLOC_CTX *ctx = talloc_tos();
5006 if (total_data < 13) {
5007 return NT_STATUS_INVALID_PARAMETER;
5010 overwrite = (CVAL(pdata,0) ? True : False);
5011 root_fid = IVAL(pdata,4);
5012 len = IVAL(pdata,8);
5014 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5015 return NT_STATUS_INVALID_PARAMETER;
5018 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5019 len, 0, &status,
5020 &dest_has_wcard);
5021 if (!NT_STATUS_IS_OK(status)) {
5022 return status;
5025 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5026 newname));
5028 status = resolve_dfspath_wcard(ctx, conn,
5029 req->flags2 & FLAGS2_DFS_PATHNAMES,
5030 newname,
5031 &newname,
5032 &dest_has_wcard);
5033 if (!NT_STATUS_IS_OK(status)) {
5034 return status;
5037 /* Check the new name has no '/' characters. */
5038 if (strchr_m(newname, '/')) {
5039 return NT_STATUS_NOT_SUPPORTED;
5042 /* Create the base directory. */
5043 base_name = talloc_strdup(ctx, fname);
5044 if (!base_name) {
5045 return NT_STATUS_NO_MEMORY;
5047 p = strrchr_m(base_name, '/');
5048 if (p) {
5049 p[1] = '\0';
5050 } else {
5051 base_name = talloc_strdup(ctx, "./");
5052 if (!base_name) {
5053 return NT_STATUS_NO_MEMORY;
5056 /* Append the new name. */
5057 base_name = talloc_asprintf_append(base_name,
5058 "%s",
5059 newname);
5060 if (!base_name) {
5061 return NT_STATUS_NO_MEMORY;
5064 if (fsp) {
5065 SMB_STRUCT_STAT sbuf;
5066 char *newname_last_component = NULL;
5068 ZERO_STRUCT(sbuf);
5070 status = unix_convert(ctx, conn, newname, False,
5071 &newname,
5072 &newname_last_component,
5073 &sbuf);
5075 /* If an error we expect this to be
5076 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5078 if (!NT_STATUS_IS_OK(status)
5079 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5080 status)) {
5081 return status;
5084 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5085 fsp->fnum, fsp->fsp_name, base_name ));
5086 status = rename_internals_fsp(conn, fsp, base_name,
5087 newname_last_component, 0,
5088 overwrite);
5089 } else {
5090 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5091 fname, base_name ));
5092 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5093 overwrite, False, dest_has_wcard);
5096 return status;
5099 /****************************************************************************
5100 Deal with SMB_SET_POSIX_ACL.
5101 ****************************************************************************/
5103 #if defined(HAVE_POSIX_ACLS)
5104 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5105 const char *pdata,
5106 int total_data,
5107 files_struct *fsp,
5108 const char *fname,
5109 SMB_STRUCT_STAT *psbuf)
5111 uint16 posix_acl_version;
5112 uint16 num_file_acls;
5113 uint16 num_def_acls;
5114 bool valid_file_acls = True;
5115 bool valid_def_acls = True;
5117 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5118 return NT_STATUS_INVALID_PARAMETER;
5120 posix_acl_version = SVAL(pdata,0);
5121 num_file_acls = SVAL(pdata,2);
5122 num_def_acls = SVAL(pdata,4);
5124 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5125 valid_file_acls = False;
5126 num_file_acls = 0;
5129 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5130 valid_def_acls = False;
5131 num_def_acls = 0;
5134 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5135 return NT_STATUS_INVALID_PARAMETER;
5138 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5139 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5140 return NT_STATUS_INVALID_PARAMETER;
5143 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5144 fname ? fname : fsp->fsp_name,
5145 (unsigned int)num_file_acls,
5146 (unsigned int)num_def_acls));
5148 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5149 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5150 return map_nt_error_from_unix(errno);
5153 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5154 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5155 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5156 return map_nt_error_from_unix(errno);
5158 return NT_STATUS_OK;
5160 #endif
5162 /****************************************************************************
5163 Deal with SMB_SET_POSIX_LOCK.
5164 ****************************************************************************/
5166 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5167 const struct smb_request *req,
5168 const char *pdata,
5169 int total_data,
5170 files_struct *fsp)
5172 SMB_BIG_UINT count;
5173 SMB_BIG_UINT offset;
5174 uint32 lock_pid;
5175 bool blocking_lock = False;
5176 enum brl_type lock_type;
5178 NTSTATUS status = NT_STATUS_OK;
5180 if (fsp == NULL || fsp->fh->fd == -1) {
5181 return NT_STATUS_INVALID_HANDLE;
5184 if (total_data != POSIX_LOCK_DATA_SIZE) {
5185 return NT_STATUS_INVALID_PARAMETER;
5188 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5189 case POSIX_LOCK_TYPE_READ:
5190 lock_type = READ_LOCK;
5191 break;
5192 case POSIX_LOCK_TYPE_WRITE:
5193 /* Return the right POSIX-mappable error code for files opened read-only. */
5194 if (!fsp->can_write) {
5195 return NT_STATUS_INVALID_HANDLE;
5197 lock_type = WRITE_LOCK;
5198 break;
5199 case POSIX_LOCK_TYPE_UNLOCK:
5200 lock_type = UNLOCK_LOCK;
5201 break;
5202 default:
5203 return NT_STATUS_INVALID_PARAMETER;
5206 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5207 blocking_lock = False;
5208 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5209 blocking_lock = True;
5210 } else {
5211 return NT_STATUS_INVALID_PARAMETER;
5214 if (!lp_blocking_locks(SNUM(conn))) {
5215 blocking_lock = False;
5218 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5219 #if defined(HAVE_LONGLONG)
5220 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5221 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5222 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5223 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5224 #else /* HAVE_LONGLONG */
5225 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5226 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5227 #endif /* HAVE_LONGLONG */
5229 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5230 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5231 fsp->fsp_name,
5232 (unsigned int)lock_type,
5233 (unsigned int)lock_pid,
5234 (double)count,
5235 (double)offset ));
5237 if (lock_type == UNLOCK_LOCK) {
5238 status = do_unlock(smbd_messaging_context(),
5239 fsp,
5240 lock_pid,
5241 count,
5242 offset,
5243 POSIX_LOCK);
5244 } else {
5245 uint32 block_smbpid;
5247 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5248 fsp,
5249 lock_pid,
5250 count,
5251 offset,
5252 lock_type,
5253 POSIX_LOCK,
5254 blocking_lock,
5255 &status,
5256 &block_smbpid);
5258 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5260 * A blocking lock was requested. Package up
5261 * this smb into a queued request and push it
5262 * onto the blocking lock queue.
5264 if(push_blocking_lock_request(br_lck,
5265 req,
5266 fsp,
5267 -1, /* infinite timeout. */
5269 lock_pid,
5270 lock_type,
5271 POSIX_LOCK,
5272 offset,
5273 count,
5274 block_smbpid)) {
5275 TALLOC_FREE(br_lck);
5276 return status;
5279 TALLOC_FREE(br_lck);
5282 return status;
5285 /****************************************************************************
5286 Deal with SMB_INFO_STANDARD.
5287 ****************************************************************************/
5289 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5290 const char *pdata,
5291 int total_data,
5292 files_struct *fsp,
5293 const char *fname,
5294 const SMB_STRUCT_STAT *psbuf)
5296 struct timespec ts[2];
5298 if (total_data < 12) {
5299 return NT_STATUS_INVALID_PARAMETER;
5302 /* access time */
5303 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5304 /* write time */
5305 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5307 DEBUG(10,("smb_set_info_standard: file %s\n",
5308 fname ? fname : fsp->fsp_name ));
5310 return smb_set_file_time(conn,
5311 fsp,
5312 fname,
5313 psbuf,
5315 true);
5318 /****************************************************************************
5319 Deal with SMB_SET_FILE_BASIC_INFO.
5320 ****************************************************************************/
5322 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5323 const char *pdata,
5324 int total_data,
5325 files_struct *fsp,
5326 const char *fname,
5327 SMB_STRUCT_STAT *psbuf)
5329 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5330 struct timespec write_time;
5331 struct timespec changed_time;
5332 uint32 dosmode = 0;
5333 struct timespec ts[2];
5334 NTSTATUS status = NT_STATUS_OK;
5335 bool setting_write_time = true;
5337 if (total_data < 36) {
5338 return NT_STATUS_INVALID_PARAMETER;
5341 /* Set the attributes */
5342 dosmode = IVAL(pdata,32);
5343 status = smb_set_file_dosmode(conn,
5344 fname,
5345 psbuf,
5346 dosmode);
5347 if (!NT_STATUS_IS_OK(status)) {
5348 return status;
5351 /* Ignore create time at offset pdata. */
5353 /* access time */
5354 ts[0] = interpret_long_date(pdata+8);
5356 write_time = interpret_long_date(pdata+16);
5357 changed_time = interpret_long_date(pdata+24);
5359 /* mtime */
5360 ts[1] = timespec_min(&write_time, &changed_time);
5362 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5363 ts[1] = write_time;
5366 /* Prefer a defined time to an undefined one. */
5367 if (null_timespec(ts[1])) {
5368 if (null_timespec(write_time)) {
5369 ts[1] = changed_time;
5370 setting_write_time = false;
5371 } else {
5372 ts[1] = write_time;
5376 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5377 fname ? fname : fsp->fsp_name ));
5379 return smb_set_file_time(conn,
5380 fsp,
5381 fname,
5382 psbuf,
5384 setting_write_time);
5387 /****************************************************************************
5388 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5389 ****************************************************************************/
5391 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5392 struct smb_request *req,
5393 const char *pdata,
5394 int total_data,
5395 files_struct *fsp,
5396 const char *fname,
5397 SMB_STRUCT_STAT *psbuf)
5399 SMB_BIG_UINT allocation_size = 0;
5400 NTSTATUS status = NT_STATUS_OK;
5401 files_struct *new_fsp = NULL;
5403 if (!VALID_STAT(*psbuf)) {
5404 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5407 if (total_data < 8) {
5408 return NT_STATUS_INVALID_PARAMETER;
5411 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5412 #ifdef LARGE_SMB_OFF_T
5413 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5414 #else /* LARGE_SMB_OFF_T */
5415 if (IVAL(pdata,4) != 0) {
5416 /* more than 32 bits? */
5417 return NT_STATUS_INVALID_PARAMETER;
5419 #endif /* LARGE_SMB_OFF_T */
5421 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5422 fname, (double)allocation_size ));
5424 if (allocation_size) {
5425 allocation_size = smb_roundup(conn, allocation_size);
5428 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5429 fname, (double)allocation_size ));
5431 if (fsp && fsp->fh->fd != -1) {
5432 /* Open file handle. */
5433 /* Only change if needed. */
5434 if (allocation_size != get_file_size(*psbuf)) {
5435 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5436 return map_nt_error_from_unix(errno);
5439 /* But always update the time. */
5440 if (null_timespec(fsp->pending_modtime)) {
5442 * This is equivalent to a write. Ensure it's seen immediately
5443 * if there are no pending writes.
5445 set_filetime(fsp->conn, fsp->fsp_name,
5446 timespec_current());
5448 return NT_STATUS_OK;
5451 /* Pathname or stat or directory file. */
5453 status = open_file_ntcreate(conn, req, fname, psbuf,
5454 FILE_WRITE_DATA,
5455 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5456 FILE_OPEN,
5458 FILE_ATTRIBUTE_NORMAL,
5459 FORCE_OPLOCK_BREAK_TO_NONE,
5460 NULL, &new_fsp);
5462 if (!NT_STATUS_IS_OK(status)) {
5463 /* NB. We check for open_was_deferred in the caller. */
5464 return status;
5467 /* Only change if needed. */
5468 if (allocation_size != get_file_size(*psbuf)) {
5469 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5470 status = map_nt_error_from_unix(errno);
5471 close_file(new_fsp,NORMAL_CLOSE);
5472 return status;
5476 /* Changing the allocation size should set the last mod time. */
5477 /* Don't need to call set_filetime as this will be flushed on
5478 * close. */
5480 fsp_set_pending_modtime(new_fsp, timespec_current());
5482 close_file(new_fsp,NORMAL_CLOSE);
5483 return NT_STATUS_OK;
5486 /****************************************************************************
5487 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5488 ****************************************************************************/
5490 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5491 struct smb_request *req,
5492 const char *pdata,
5493 int total_data,
5494 files_struct *fsp,
5495 const char *fname,
5496 SMB_STRUCT_STAT *psbuf)
5498 SMB_OFF_T size;
5500 if (total_data < 8) {
5501 return NT_STATUS_INVALID_PARAMETER;
5504 size = IVAL(pdata,0);
5505 #ifdef LARGE_SMB_OFF_T
5506 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5507 #else /* LARGE_SMB_OFF_T */
5508 if (IVAL(pdata,4) != 0) {
5509 /* more than 32 bits? */
5510 return NT_STATUS_INVALID_PARAMETER;
5512 #endif /* LARGE_SMB_OFF_T */
5513 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5514 "file %s to %.0f\n", fname, (double)size ));
5516 return smb_set_file_size(conn, req,
5517 fsp,
5518 fname,
5519 psbuf,
5520 size);
5523 /****************************************************************************
5524 Allow a UNIX info mknod.
5525 ****************************************************************************/
5527 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5528 const char *pdata,
5529 int total_data,
5530 const char *fname,
5531 SMB_STRUCT_STAT *psbuf)
5533 uint32 file_type = IVAL(pdata,56);
5534 #if defined(HAVE_MAKEDEV)
5535 uint32 dev_major = IVAL(pdata,60);
5536 uint32 dev_minor = IVAL(pdata,68);
5537 #endif
5538 SMB_DEV_T dev = (SMB_DEV_T)0;
5539 uint32 raw_unixmode = IVAL(pdata,84);
5540 NTSTATUS status;
5541 mode_t unixmode;
5543 if (total_data < 100) {
5544 return NT_STATUS_INVALID_PARAMETER;
5547 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5548 if (!NT_STATUS_IS_OK(status)) {
5549 return status;
5552 #if defined(HAVE_MAKEDEV)
5553 dev = makedev(dev_major, dev_minor);
5554 #endif
5556 switch (file_type) {
5557 #if defined(S_IFIFO)
5558 case UNIX_TYPE_FIFO:
5559 unixmode |= S_IFIFO;
5560 break;
5561 #endif
5562 #if defined(S_IFSOCK)
5563 case UNIX_TYPE_SOCKET:
5564 unixmode |= S_IFSOCK;
5565 break;
5566 #endif
5567 #if defined(S_IFCHR)
5568 case UNIX_TYPE_CHARDEV:
5569 unixmode |= S_IFCHR;
5570 break;
5571 #endif
5572 #if defined(S_IFBLK)
5573 case UNIX_TYPE_BLKDEV:
5574 unixmode |= S_IFBLK;
5575 break;
5576 #endif
5577 default:
5578 return NT_STATUS_INVALID_PARAMETER;
5581 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5582 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5584 /* Ok - do the mknod. */
5585 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5586 return map_nt_error_from_unix(errno);
5589 /* If any of the other "set" calls fail we
5590 * don't want to end up with a half-constructed mknod.
5593 if (lp_inherit_perms(SNUM(conn))) {
5594 inherit_access_acl(
5595 conn, parent_dirname(fname),
5596 fname, unixmode);
5599 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5600 status = map_nt_error_from_unix(errno);
5601 SMB_VFS_UNLINK(conn,fname);
5602 return status;
5604 return NT_STATUS_OK;
5607 /****************************************************************************
5608 Deal with SMB_SET_FILE_UNIX_BASIC.
5609 ****************************************************************************/
5611 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5612 struct smb_request *req,
5613 const char *pdata,
5614 int total_data,
5615 files_struct *fsp,
5616 const char *fname,
5617 SMB_STRUCT_STAT *psbuf)
5619 struct timespec ts[2];
5620 uint32 raw_unixmode;
5621 mode_t unixmode;
5622 SMB_OFF_T size = 0;
5623 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5624 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5625 NTSTATUS status = NT_STATUS_OK;
5626 bool delete_on_fail = False;
5627 enum perm_type ptype;
5629 if (total_data < 100) {
5630 return NT_STATUS_INVALID_PARAMETER;
5633 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5634 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5635 size=IVAL(pdata,0); /* first 8 Bytes are size */
5636 #ifdef LARGE_SMB_OFF_T
5637 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5638 #else /* LARGE_SMB_OFF_T */
5639 if (IVAL(pdata,4) != 0) {
5640 /* more than 32 bits? */
5641 return NT_STATUS_INVALID_PARAMETER;
5643 #endif /* LARGE_SMB_OFF_T */
5646 ts[0] = interpret_long_date(pdata+24); /* access_time */
5647 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5648 set_owner = (uid_t)IVAL(pdata,40);
5649 set_grp = (gid_t)IVAL(pdata,48);
5650 raw_unixmode = IVAL(pdata,84);
5652 if (VALID_STAT(*psbuf)) {
5653 if (S_ISDIR(psbuf->st_mode)) {
5654 ptype = PERM_EXISTING_DIR;
5655 } else {
5656 ptype = PERM_EXISTING_FILE;
5658 } else {
5659 ptype = PERM_NEW_FILE;
5662 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5663 if (!NT_STATUS_IS_OK(status)) {
5664 return status;
5667 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5668 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5669 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5671 if (!VALID_STAT(*psbuf)) {
5673 * The only valid use of this is to create character and block
5674 * devices, and named pipes. This is deprecated (IMHO) and
5675 * a new info level should be used for mknod. JRA.
5678 status = smb_unix_mknod(conn,
5679 pdata,
5680 total_data,
5681 fname,
5682 psbuf);
5683 if (!NT_STATUS_IS_OK(status)) {
5684 return status;
5687 /* Ensure we don't try and change anything else. */
5688 raw_unixmode = SMB_MODE_NO_CHANGE;
5689 size = get_file_size(*psbuf);
5690 ts[0] = get_atimespec(psbuf);
5691 ts[1] = get_mtimespec(psbuf);
5693 * We continue here as we might want to change the
5694 * owner uid/gid.
5696 delete_on_fail = True;
5699 #if 1
5700 /* Horrible backwards compatibility hack as an old server bug
5701 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5702 * */
5704 if (!size) {
5705 size = get_file_size(*psbuf);
5707 #endif
5710 * Deal with the UNIX specific mode set.
5713 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5714 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5715 (unsigned int)unixmode, fname ));
5716 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5717 return map_nt_error_from_unix(errno);
5722 * Deal with the UNIX specific uid set.
5725 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5726 int ret;
5728 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5729 (unsigned int)set_owner, fname ));
5731 if (S_ISLNK(psbuf->st_mode)) {
5732 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5733 } else {
5734 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5737 if (ret != 0) {
5738 status = map_nt_error_from_unix(errno);
5739 if (delete_on_fail) {
5740 SMB_VFS_UNLINK(conn,fname);
5742 return status;
5747 * Deal with the UNIX specific gid set.
5750 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5751 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5752 (unsigned int)set_owner, fname ));
5753 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5754 status = map_nt_error_from_unix(errno);
5755 if (delete_on_fail) {
5756 SMB_VFS_UNLINK(conn,fname);
5758 return status;
5762 /* Deal with any size changes. */
5764 status = smb_set_file_size(conn, req,
5765 fsp,
5766 fname,
5767 psbuf,
5768 size);
5769 if (!NT_STATUS_IS_OK(status)) {
5770 return status;
5773 /* Deal with any time changes. */
5775 return smb_set_file_time(conn,
5776 fsp,
5777 fname,
5778 psbuf,
5780 true);
5783 /****************************************************************************
5784 Deal with SMB_SET_FILE_UNIX_INFO2.
5785 ****************************************************************************/
5787 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5788 struct smb_request *req,
5789 const char *pdata,
5790 int total_data,
5791 files_struct *fsp,
5792 const char *fname,
5793 SMB_STRUCT_STAT *psbuf)
5795 NTSTATUS status;
5796 uint32 smb_fflags;
5797 uint32 smb_fmask;
5799 if (total_data < 116) {
5800 return NT_STATUS_INVALID_PARAMETER;
5803 /* Start by setting all the fields that are common between UNIX_BASIC
5804 * and UNIX_INFO2.
5806 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5807 fsp, fname, psbuf);
5808 if (!NT_STATUS_IS_OK(status)) {
5809 return status;
5812 smb_fflags = IVAL(pdata, 108);
5813 smb_fmask = IVAL(pdata, 112);
5815 /* NB: We should only attempt to alter the file flags if the client
5816 * sends a non-zero mask.
5818 if (smb_fmask != 0) {
5819 int stat_fflags = 0;
5821 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5822 &stat_fflags)) {
5823 /* Client asked to alter a flag we don't understand. */
5824 return NT_STATUS_INVALID_PARAMETER;
5827 if (fsp && fsp->fh->fd != -1) {
5828 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5829 return NT_STATUS_NOT_SUPPORTED;
5830 } else {
5831 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5832 return map_nt_error_from_unix(errno);
5837 /* XXX: need to add support for changing the create_time here. You
5838 * can do this for paths on Darwin with setattrlist(2). The right way
5839 * to hook this up is probably by extending the VFS utimes interface.
5842 return NT_STATUS_OK;
5845 /****************************************************************************
5846 Create a directory with POSIX semantics.
5847 ****************************************************************************/
5849 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5850 struct smb_request *req,
5851 char **ppdata,
5852 int total_data,
5853 const char *fname,
5854 SMB_STRUCT_STAT *psbuf,
5855 int *pdata_return_size)
5857 NTSTATUS status = NT_STATUS_OK;
5858 uint32 raw_unixmode = 0;
5859 uint32 mod_unixmode = 0;
5860 mode_t unixmode = (mode_t)0;
5861 files_struct *fsp = NULL;
5862 uint16 info_level_return = 0;
5863 int info;
5864 char *pdata = *ppdata;
5866 if (total_data < 18) {
5867 return NT_STATUS_INVALID_PARAMETER;
5870 raw_unixmode = IVAL(pdata,8);
5871 /* Next 4 bytes are not yet defined. */
5873 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5874 if (!NT_STATUS_IS_OK(status)) {
5875 return status;
5878 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5880 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5881 fname, (unsigned int)unixmode ));
5883 status = open_directory(conn, req,
5884 fname,
5885 psbuf,
5886 FILE_READ_ATTRIBUTES, /* Just a stat open */
5887 FILE_SHARE_NONE, /* Ignored for stat opens */
5888 FILE_CREATE,
5890 mod_unixmode,
5891 &info,
5892 &fsp);
5894 if (NT_STATUS_IS_OK(status)) {
5895 close_file(fsp, NORMAL_CLOSE);
5898 info_level_return = SVAL(pdata,16);
5900 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5901 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5902 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5903 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5904 } else {
5905 *pdata_return_size = 12;
5908 /* Realloc the data size */
5909 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5910 if (*ppdata == NULL) {
5911 *pdata_return_size = 0;
5912 return NT_STATUS_NO_MEMORY;
5914 pdata = *ppdata;
5916 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5917 SSVAL(pdata,2,0); /* No fnum. */
5918 SIVAL(pdata,4,info); /* Was directory created. */
5920 switch (info_level_return) {
5921 case SMB_QUERY_FILE_UNIX_BASIC:
5922 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5923 SSVAL(pdata,10,0); /* Padding. */
5924 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5925 break;
5926 case SMB_QUERY_FILE_UNIX_INFO2:
5927 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5928 SSVAL(pdata,10,0); /* Padding. */
5929 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5930 break;
5931 default:
5932 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5933 SSVAL(pdata,10,0); /* Padding. */
5934 break;
5937 return status;
5940 /****************************************************************************
5941 Open/Create a file with POSIX semantics.
5942 ****************************************************************************/
5944 static NTSTATUS smb_posix_open(connection_struct *conn,
5945 struct smb_request *req,
5946 char **ppdata,
5947 int total_data,
5948 const char *fname,
5949 SMB_STRUCT_STAT *psbuf,
5950 int *pdata_return_size)
5952 bool extended_oplock_granted = False;
5953 char *pdata = *ppdata;
5954 uint32 flags = 0;
5955 uint32 wire_open_mode = 0;
5956 uint32 raw_unixmode = 0;
5957 uint32 mod_unixmode = 0;
5958 uint32 create_disp = 0;
5959 uint32 access_mask = 0;
5960 uint32 create_options = 0;
5961 NTSTATUS status = NT_STATUS_OK;
5962 mode_t unixmode = (mode_t)0;
5963 files_struct *fsp = NULL;
5964 int oplock_request = 0;
5965 int info = 0;
5966 uint16 info_level_return = 0;
5968 if (total_data < 18) {
5969 return NT_STATUS_INVALID_PARAMETER;
5972 flags = IVAL(pdata,0);
5973 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5974 if (oplock_request) {
5975 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5978 wire_open_mode = IVAL(pdata,4);
5980 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5981 return smb_posix_mkdir(conn, req,
5982 ppdata,
5983 total_data,
5984 fname,
5985 psbuf,
5986 pdata_return_size);
5989 switch (wire_open_mode & SMB_ACCMODE) {
5990 case SMB_O_RDONLY:
5991 access_mask = FILE_READ_DATA;
5992 break;
5993 case SMB_O_WRONLY:
5994 access_mask = FILE_WRITE_DATA;
5995 break;
5996 case SMB_O_RDWR:
5997 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5998 break;
5999 default:
6000 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6001 (unsigned int)wire_open_mode ));
6002 return NT_STATUS_INVALID_PARAMETER;
6005 wire_open_mode &= ~SMB_ACCMODE;
6007 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6008 create_disp = FILE_CREATE;
6009 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6010 create_disp = FILE_OVERWRITE_IF;
6011 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6012 create_disp = FILE_OPEN_IF;
6013 } else {
6014 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6015 (unsigned int)wire_open_mode ));
6016 return NT_STATUS_INVALID_PARAMETER;
6019 raw_unixmode = IVAL(pdata,8);
6020 /* Next 4 bytes are not yet defined. */
6022 status = unix_perms_from_wire(conn,
6023 psbuf,
6024 raw_unixmode,
6025 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6026 &unixmode);
6028 if (!NT_STATUS_IS_OK(status)) {
6029 return status;
6032 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6034 if (wire_open_mode & SMB_O_SYNC) {
6035 create_options |= FILE_WRITE_THROUGH;
6037 if (wire_open_mode & SMB_O_APPEND) {
6038 access_mask |= FILE_APPEND_DATA;
6040 if (wire_open_mode & SMB_O_DIRECT) {
6041 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6044 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6045 fname,
6046 (unsigned int)wire_open_mode,
6047 (unsigned int)unixmode ));
6049 status = open_file_ntcreate(conn, req,
6050 fname,
6051 psbuf,
6052 access_mask,
6053 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6054 create_disp,
6055 0, /* no create options yet. */
6056 mod_unixmode,
6057 oplock_request,
6058 &info,
6059 &fsp);
6061 if (!NT_STATUS_IS_OK(status)) {
6062 return status;
6065 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6066 extended_oplock_granted = True;
6069 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6070 extended_oplock_granted = True;
6073 info_level_return = SVAL(pdata,16);
6075 /* Allocate the correct return size. */
6077 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6078 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6079 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6080 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6081 } else {
6082 *pdata_return_size = 12;
6085 /* Realloc the data size */
6086 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6087 if (*ppdata == NULL) {
6088 close_file(fsp,ERROR_CLOSE);
6089 *pdata_return_size = 0;
6090 return NT_STATUS_NO_MEMORY;
6092 pdata = *ppdata;
6094 if (extended_oplock_granted) {
6095 if (flags & REQUEST_BATCH_OPLOCK) {
6096 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6097 } else {
6098 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6100 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6101 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6102 } else {
6103 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6106 SSVAL(pdata,2,fsp->fnum);
6107 SIVAL(pdata,4,info); /* Was file created etc. */
6109 switch (info_level_return) {
6110 case SMB_QUERY_FILE_UNIX_BASIC:
6111 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6112 SSVAL(pdata,10,0); /* padding. */
6113 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6114 break;
6115 case SMB_QUERY_FILE_UNIX_INFO2:
6116 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6117 SSVAL(pdata,10,0); /* padding. */
6118 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6119 break;
6120 default:
6121 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6122 SSVAL(pdata,10,0); /* padding. */
6123 break;
6125 return NT_STATUS_OK;
6128 /****************************************************************************
6129 Delete a file with POSIX semantics.
6130 ****************************************************************************/
6132 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6133 struct smb_request *req,
6134 const char *pdata,
6135 int total_data,
6136 const char *fname,
6137 SMB_STRUCT_STAT *psbuf)
6139 NTSTATUS status = NT_STATUS_OK;
6140 files_struct *fsp = NULL;
6141 uint16 flags = 0;
6142 char del = 1;
6143 int info = 0;
6144 int i;
6145 struct share_mode_lock *lck = NULL;
6147 if (total_data < 2) {
6148 return NT_STATUS_INVALID_PARAMETER;
6151 flags = SVAL(pdata,0);
6153 if (!VALID_STAT(*psbuf)) {
6154 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6157 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6158 !VALID_STAT_OF_DIR(*psbuf)) {
6159 return NT_STATUS_NOT_A_DIRECTORY;
6162 DEBUG(10,("smb_posix_unlink: %s %s\n",
6163 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6164 fname));
6166 if (VALID_STAT_OF_DIR(*psbuf)) {
6167 status = open_directory(conn, req,
6168 fname,
6169 psbuf,
6170 DELETE_ACCESS,
6171 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6172 FILE_OPEN,
6174 FILE_FLAG_POSIX_SEMANTICS|0777,
6175 &info,
6176 &fsp);
6177 } else {
6179 status = open_file_ntcreate(conn, req,
6180 fname,
6181 psbuf,
6182 DELETE_ACCESS,
6183 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6184 FILE_OPEN,
6186 FILE_FLAG_POSIX_SEMANTICS|0777,
6187 0, /* No oplock, but break existing ones. */
6188 &info,
6189 &fsp);
6192 if (!NT_STATUS_IS_OK(status)) {
6193 return status;
6197 * Don't lie to client. If we can't really delete due to
6198 * non-POSIX opens return SHARING_VIOLATION.
6201 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
6202 if (lck == NULL) {
6203 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6204 "lock for file %s\n", fsp->fsp_name));
6205 close_file(fsp, NORMAL_CLOSE);
6206 return NT_STATUS_INVALID_PARAMETER;
6210 * See if others still have the file open. If this is the case, then
6211 * don't delete. If all opens are POSIX delete we can set the delete
6212 * on close disposition.
6214 for (i=0; i<lck->num_share_modes; i++) {
6215 struct share_mode_entry *e = &lck->share_modes[i];
6216 if (is_valid_share_mode_entry(e)) {
6217 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6218 continue;
6220 /* Fail with sharing violation. */
6221 close_file(fsp, NORMAL_CLOSE);
6222 TALLOC_FREE(lck);
6223 return NT_STATUS_SHARING_VIOLATION;
6228 * Set the delete on close.
6230 status = smb_set_file_disposition_info(conn,
6231 &del,
6233 fsp,
6234 fname,
6235 psbuf);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 close_file(fsp, NORMAL_CLOSE);
6239 TALLOC_FREE(lck);
6240 return status;
6242 TALLOC_FREE(lck);
6243 return close_file(fsp, NORMAL_CLOSE);
6246 /****************************************************************************
6247 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6248 ****************************************************************************/
6250 static void call_trans2setfilepathinfo(connection_struct *conn,
6251 struct smb_request *req,
6252 unsigned int tran_call,
6253 char **pparams, int total_params,
6254 char **ppdata, int total_data,
6255 unsigned int max_data_bytes)
6257 char *params = *pparams;
6258 char *pdata = *ppdata;
6259 uint16 info_level;
6260 SMB_STRUCT_STAT sbuf;
6261 char *fname = NULL;
6262 files_struct *fsp = NULL;
6263 NTSTATUS status = NT_STATUS_OK;
6264 int data_return_size = 0;
6265 TALLOC_CTX *ctx = talloc_tos();
6267 if (!params) {
6268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6269 return;
6272 ZERO_STRUCT(sbuf);
6274 if (tran_call == TRANSACT2_SETFILEINFO) {
6275 if (total_params < 4) {
6276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6277 return;
6280 fsp = file_fsp(SVAL(params,0));
6281 /* Basic check for non-null fsp. */
6282 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6283 return;
6285 info_level = SVAL(params,2);
6287 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6288 if (!fname) {
6289 reply_nterror(req, NT_STATUS_NO_MEMORY);
6290 return;
6293 if(fsp->is_directory || fsp->fh->fd == -1) {
6295 * This is actually a SETFILEINFO on a directory
6296 * handle (returned from an NT SMB). NT5.0 seems
6297 * to do this call. JRA.
6299 if (INFO_LEVEL_IS_UNIX(info_level)) {
6300 /* Always do lstat for UNIX calls. */
6301 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6302 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6303 reply_unixerror(req,ERRDOS,ERRbadpath);
6304 return;
6306 } else {
6307 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6308 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6309 reply_unixerror(req,ERRDOS,ERRbadpath);
6310 return;
6313 } else if (fsp->print_file) {
6315 * Doing a DELETE_ON_CLOSE should cancel a print job.
6317 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6318 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6320 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6322 SSVAL(params,0,0);
6323 send_trans2_replies(conn, req, params, 2,
6324 *ppdata, 0,
6325 max_data_bytes);
6326 return;
6327 } else {
6328 reply_unixerror(req, ERRDOS, ERRbadpath);
6329 return;
6331 } else {
6333 * Original code - this is an open file.
6335 if (!check_fsp(conn, req, fsp, &current_user)) {
6336 return;
6339 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6340 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6341 reply_unixerror(req, ERRDOS, ERRbadfid);
6342 return;
6345 } else {
6346 /* set path info */
6347 if (total_params < 7) {
6348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6349 return;
6352 info_level = SVAL(params,0);
6353 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6354 total_params - 6, STR_TERMINATE,
6355 &status);
6356 if (!NT_STATUS_IS_OK(status)) {
6357 reply_nterror(req, status);
6358 return;
6361 status = resolve_dfspath(ctx, conn,
6362 req->flags2 & FLAGS2_DFS_PATHNAMES,
6363 fname,
6364 &fname);
6365 if (!NT_STATUS_IS_OK(status)) {
6366 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6367 reply_botherror(req,
6368 NT_STATUS_PATH_NOT_COVERED,
6369 ERRSRV, ERRbadpath);
6370 return;
6372 reply_nterror(req, status);
6373 return;
6376 status = unix_convert(ctx, conn, fname, False,
6377 &fname, NULL, &sbuf);
6378 if (!NT_STATUS_IS_OK(status)) {
6379 reply_nterror(req, status);
6380 return;
6383 status = check_name(conn, fname);
6384 if (!NT_STATUS_IS_OK(status)) {
6385 reply_nterror(req, status);
6386 return;
6389 if (INFO_LEVEL_IS_UNIX(info_level)) {
6391 * For CIFS UNIX extensions the target name may not exist.
6394 /* Always do lstat for UNIX calls. */
6395 SMB_VFS_LSTAT(conn,fname,&sbuf);
6397 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6398 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6399 reply_unixerror(req, ERRDOS, ERRbadpath);
6400 return;
6404 if (!CAN_WRITE(conn)) {
6405 reply_doserror(req, ERRSRV, ERRaccess);
6406 return;
6409 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6410 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6411 return;
6414 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6415 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6417 /* Realloc the parameter size */
6418 *pparams = (char *)SMB_REALLOC(*pparams,2);
6419 if (*pparams == NULL) {
6420 reply_nterror(req, NT_STATUS_NO_MEMORY);
6421 return;
6423 params = *pparams;
6425 SSVAL(params,0,0);
6427 if (fsp && !null_timespec(fsp->pending_modtime)) {
6428 /* the pending modtime overrides the current modtime */
6429 set_mtimespec(&sbuf, fsp->pending_modtime);
6432 switch (info_level) {
6434 case SMB_INFO_STANDARD:
6436 status = smb_set_info_standard(conn,
6437 pdata,
6438 total_data,
6439 fsp,
6440 fname,
6441 &sbuf);
6442 break;
6445 case SMB_INFO_SET_EA:
6447 status = smb_info_set_ea(conn,
6448 pdata,
6449 total_data,
6450 fsp,
6451 fname);
6452 break;
6455 case SMB_SET_FILE_BASIC_INFO:
6456 case SMB_FILE_BASIC_INFORMATION:
6458 status = smb_set_file_basic_info(conn,
6459 pdata,
6460 total_data,
6461 fsp,
6462 fname,
6463 &sbuf);
6464 break;
6467 case SMB_FILE_ALLOCATION_INFORMATION:
6468 case SMB_SET_FILE_ALLOCATION_INFO:
6470 status = smb_set_file_allocation_info(conn, req,
6471 pdata,
6472 total_data,
6473 fsp,
6474 fname,
6475 &sbuf);
6476 break;
6479 case SMB_FILE_END_OF_FILE_INFORMATION:
6480 case SMB_SET_FILE_END_OF_FILE_INFO:
6482 status = smb_set_file_end_of_file_info(conn, req,
6483 pdata,
6484 total_data,
6485 fsp,
6486 fname,
6487 &sbuf);
6488 break;
6491 case SMB_FILE_DISPOSITION_INFORMATION:
6492 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6494 #if 0
6495 /* JRA - We used to just ignore this on a path ?
6496 * Shouldn't this be invalid level on a pathname
6497 * based call ?
6499 if (tran_call != TRANSACT2_SETFILEINFO) {
6500 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6502 #endif
6503 status = smb_set_file_disposition_info(conn,
6504 pdata,
6505 total_data,
6506 fsp,
6507 fname,
6508 &sbuf);
6509 break;
6512 case SMB_FILE_POSITION_INFORMATION:
6514 status = smb_file_position_information(conn,
6515 pdata,
6516 total_data,
6517 fsp);
6518 break;
6521 /* From tridge Samba4 :
6522 * MODE_INFORMATION in setfileinfo (I have no
6523 * idea what "mode information" on a file is - it takes a value of 0,
6524 * 2, 4 or 6. What could it be?).
6527 case SMB_FILE_MODE_INFORMATION:
6529 status = smb_file_mode_information(conn,
6530 pdata,
6531 total_data);
6532 break;
6536 * CIFS UNIX extensions.
6539 case SMB_SET_FILE_UNIX_BASIC:
6541 status = smb_set_file_unix_basic(conn, req,
6542 pdata,
6543 total_data,
6544 fsp,
6545 fname,
6546 &sbuf);
6547 break;
6550 case SMB_SET_FILE_UNIX_INFO2:
6552 status = smb_set_file_unix_info2(conn, req,
6553 pdata,
6554 total_data,
6555 fsp,
6556 fname,
6557 &sbuf);
6558 break;
6561 case SMB_SET_FILE_UNIX_LINK:
6563 if (tran_call != TRANSACT2_SETPATHINFO) {
6564 /* We must have a pathname for this. */
6565 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6566 return;
6568 status = smb_set_file_unix_link(conn, req, pdata,
6569 total_data, fname);
6570 break;
6573 case SMB_SET_FILE_UNIX_HLINK:
6575 if (tran_call != TRANSACT2_SETPATHINFO) {
6576 /* We must have a pathname for this. */
6577 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6578 return;
6580 status = smb_set_file_unix_hlink(conn, req,
6581 pdata, total_data,
6582 fname);
6583 break;
6586 case SMB_FILE_RENAME_INFORMATION:
6588 status = smb_file_rename_information(conn, req,
6589 pdata, total_data,
6590 fsp, fname);
6591 break;
6594 #if defined(HAVE_POSIX_ACLS)
6595 case SMB_SET_POSIX_ACL:
6597 status = smb_set_posix_acl(conn,
6598 pdata,
6599 total_data,
6600 fsp,
6601 fname,
6602 &sbuf);
6603 break;
6605 #endif
6607 case SMB_SET_POSIX_LOCK:
6609 if (tran_call != TRANSACT2_SETFILEINFO) {
6610 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6611 return;
6613 status = smb_set_posix_lock(conn, req,
6614 pdata, total_data, fsp);
6615 break;
6618 case SMB_POSIX_PATH_OPEN:
6620 if (tran_call != TRANSACT2_SETPATHINFO) {
6621 /* We must have a pathname for this. */
6622 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6623 return;
6626 status = smb_posix_open(conn, req,
6627 ppdata,
6628 total_data,
6629 fname,
6630 &sbuf,
6631 &data_return_size);
6632 break;
6635 case SMB_POSIX_PATH_UNLINK:
6637 if (tran_call != TRANSACT2_SETPATHINFO) {
6638 /* We must have a pathname for this. */
6639 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6640 return;
6643 status = smb_posix_unlink(conn, req,
6644 pdata,
6645 total_data,
6646 fname,
6647 &sbuf);
6648 break;
6651 default:
6652 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6653 return;
6657 if (!NT_STATUS_IS_OK(status)) {
6658 if (open_was_deferred(req->mid)) {
6659 /* We have re-scheduled this call. */
6660 return;
6662 if (blocking_lock_was_deferred(req->mid)) {
6663 /* We have re-scheduled this call. */
6664 return;
6666 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6667 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6668 ERRSRV, ERRbadpath);
6669 return;
6671 if (info_level == SMB_POSIX_PATH_OPEN) {
6672 reply_openerror(req, status);
6673 return;
6676 reply_nterror(req, status);
6677 return;
6680 SSVAL(params,0,0);
6681 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6682 max_data_bytes);
6684 return;
6687 /****************************************************************************
6688 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6689 ****************************************************************************/
6691 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6692 char **pparams, int total_params,
6693 char **ppdata, int total_data,
6694 unsigned int max_data_bytes)
6696 char *params = *pparams;
6697 char *pdata = *ppdata;
6698 char *directory = NULL;
6699 SMB_STRUCT_STAT sbuf;
6700 NTSTATUS status = NT_STATUS_OK;
6701 struct ea_list *ea_list = NULL;
6702 TALLOC_CTX *ctx = talloc_tos();
6704 if (!CAN_WRITE(conn)) {
6705 reply_doserror(req, ERRSRV, ERRaccess);
6706 return;
6709 if (total_params < 5) {
6710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6711 return;
6714 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
6715 total_params - 4, STR_TERMINATE,
6716 &status);
6717 if (!NT_STATUS_IS_OK(status)) {
6718 reply_nterror(req, status);
6719 return;
6722 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6724 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6725 if (!NT_STATUS_IS_OK(status)) {
6726 reply_nterror(req, status);
6727 return;
6730 status = check_name(conn, directory);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6733 reply_nterror(req, status);
6734 return;
6737 /* Any data in this call is an EA list. */
6738 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6739 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6740 return;
6744 * OS/2 workplace shell seems to send SET_EA requests of "null"
6745 * length (4 bytes containing IVAL 4).
6746 * They seem to have no effect. Bug #3212. JRA.
6749 if (total_data != 4) {
6750 if (total_data < 10) {
6751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6752 return;
6755 if (IVAL(pdata,0) > total_data) {
6756 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6757 IVAL(pdata,0), (unsigned int)total_data));
6758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6759 return;
6762 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6763 total_data - 4);
6764 if (!ea_list) {
6765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6766 return;
6768 } else if (IVAL(pdata,0) != 4) {
6769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6770 return;
6773 status = create_directory(conn, req, directory);
6775 if (!NT_STATUS_IS_OK(status)) {
6776 reply_nterror(req, status);
6777 return;
6780 /* Try and set any given EA. */
6781 if (ea_list) {
6782 status = set_ea(conn, NULL, directory, ea_list);
6783 if (!NT_STATUS_IS_OK(status)) {
6784 reply_nterror(req, status);
6785 return;
6789 /* Realloc the parameter and data sizes */
6790 *pparams = (char *)SMB_REALLOC(*pparams,2);
6791 if(*pparams == NULL) {
6792 reply_nterror(req, NT_STATUS_NO_MEMORY);
6793 return;
6795 params = *pparams;
6797 SSVAL(params,0,0);
6799 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
6801 return;
6804 /****************************************************************************
6805 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6806 We don't actually do this - we just send a null response.
6807 ****************************************************************************/
6809 static void call_trans2findnotifyfirst(connection_struct *conn,
6810 struct smb_request *req,
6811 char **pparams, int total_params,
6812 char **ppdata, int total_data,
6813 unsigned int max_data_bytes)
6815 static uint16 fnf_handle = 257;
6816 char *params = *pparams;
6817 uint16 info_level;
6819 if (total_params < 6) {
6820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6821 return;
6824 info_level = SVAL(params,4);
6825 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6827 switch (info_level) {
6828 case 1:
6829 case 2:
6830 break;
6831 default:
6832 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6833 return;
6836 /* Realloc the parameter and data sizes */
6837 *pparams = (char *)SMB_REALLOC(*pparams,6);
6838 if (*pparams == NULL) {
6839 reply_nterror(req, NT_STATUS_NO_MEMORY);
6840 return;
6842 params = *pparams;
6844 SSVAL(params,0,fnf_handle);
6845 SSVAL(params,2,0); /* No changes */
6846 SSVAL(params,4,0); /* No EA errors */
6848 fnf_handle++;
6850 if(fnf_handle == 0)
6851 fnf_handle = 257;
6853 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
6855 return;
6858 /****************************************************************************
6859 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6860 changes). Currently this does nothing.
6861 ****************************************************************************/
6863 static void call_trans2findnotifynext(connection_struct *conn,
6864 struct smb_request *req,
6865 char **pparams, int total_params,
6866 char **ppdata, int total_data,
6867 unsigned int max_data_bytes)
6869 char *params = *pparams;
6871 DEBUG(3,("call_trans2findnotifynext\n"));
6873 /* Realloc the parameter and data sizes */
6874 *pparams = (char *)SMB_REALLOC(*pparams,4);
6875 if (*pparams == NULL) {
6876 reply_nterror(req, NT_STATUS_NO_MEMORY);
6877 return;
6879 params = *pparams;
6881 SSVAL(params,0,0); /* No changes */
6882 SSVAL(params,2,0); /* No EA errors */
6884 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
6886 return;
6889 /****************************************************************************
6890 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6891 ****************************************************************************/
6893 static void call_trans2getdfsreferral(connection_struct *conn,
6894 struct smb_request *req,
6895 char **pparams, int total_params,
6896 char **ppdata, int total_data,
6897 unsigned int max_data_bytes)
6899 char *params = *pparams;
6900 char *pathname = NULL;
6901 int reply_size = 0;
6902 int max_referral_level;
6903 NTSTATUS status = NT_STATUS_OK;
6904 TALLOC_CTX *ctx = talloc_tos();
6906 DEBUG(10,("call_trans2getdfsreferral\n"));
6908 if (total_params < 3) {
6909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6910 return;
6913 max_referral_level = SVAL(params,0);
6915 if(!lp_host_msdfs()) {
6916 reply_doserror(req, ERRDOS, ERRbadfunc);
6917 return;
6920 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
6921 total_params - 2, STR_TERMINATE);
6922 if (!pathname) {
6923 reply_nterror(req, NT_STATUS_NOT_FOUND);
6924 return;
6926 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6927 ppdata,&status)) < 0) {
6928 reply_nterror(req, status);
6929 return;
6932 SSVAL(req->inbuf, smb_flg2,
6933 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6934 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
6936 return;
6939 #define LMCAT_SPL 0x53
6940 #define LMFUNC_GETJOBID 0x60
6942 /****************************************************************************
6943 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6944 ****************************************************************************/
6946 static void call_trans2ioctl(connection_struct *conn,
6947 struct smb_request *req,
6948 char **pparams, int total_params,
6949 char **ppdata, int total_data,
6950 unsigned int max_data_bytes)
6952 char *pdata = *ppdata;
6953 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6955 /* check for an invalid fid before proceeding */
6957 if (!fsp) {
6958 reply_doserror(req, ERRDOS, ERRbadfid);
6959 return;
6962 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6963 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6964 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6965 if (*ppdata == NULL) {
6966 reply_nterror(req, NT_STATUS_NO_MEMORY);
6967 return;
6969 pdata = *ppdata;
6971 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6972 CAN ACCEPT THIS IN UNICODE. JRA. */
6974 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6975 srvstr_push(pdata, req->flags2, pdata + 2,
6976 global_myname(), 15,
6977 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6978 srvstr_push(pdata, req->flags2, pdata+18,
6979 lp_servicename(SNUM(conn)), 13,
6980 STR_ASCII|STR_TERMINATE); /* Service name */
6981 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
6982 max_data_bytes);
6983 return;
6986 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6987 reply_doserror(req, ERRSRV, ERRerror);
6990 /****************************************************************************
6991 Reply to a SMBfindclose (stop trans2 directory search).
6992 ****************************************************************************/
6994 void reply_findclose(struct smb_request *req)
6996 int dptr_num;
6998 START_PROFILE(SMBfindclose);
7000 if (req->wct < 1) {
7001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7002 END_PROFILE(SMBfindclose);
7003 return;
7006 dptr_num = SVALS(req->inbuf,smb_vwv0);
7008 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7010 dptr_close(&dptr_num);
7012 reply_outbuf(req, 0, 0);
7014 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7016 END_PROFILE(SMBfindclose);
7017 return;
7020 /****************************************************************************
7021 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7022 ****************************************************************************/
7024 void reply_findnclose(struct smb_request *req)
7026 int dptr_num;
7028 START_PROFILE(SMBfindnclose);
7030 if (req->wct < 1) {
7031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7032 END_PROFILE(SMBfindnclose);
7033 return;
7036 dptr_num = SVAL(req->inbuf,smb_vwv0);
7038 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7040 /* We never give out valid handles for a
7041 findnotifyfirst - so any dptr_num is ok here.
7042 Just ignore it. */
7044 reply_outbuf(req, 0, 0);
7046 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7048 END_PROFILE(SMBfindnclose);
7049 return;
7052 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7053 struct trans_state *state)
7055 if (Protocol >= PROTOCOL_NT1) {
7056 req->flags2 |= 0x40; /* IS_LONG_NAME */
7057 SSVAL(req->inbuf,smb_flg2,req->flags2);
7060 if (conn->encrypt_level == Required && !req->encrypted) {
7061 if (state->call != TRANSACT2_QFSINFO &&
7062 state->call != TRANSACT2_SETFSINFO) {
7063 DEBUG(0,("handle_trans2: encryption required "
7064 "with call 0x%x\n",
7065 (unsigned int)state->call));
7066 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7067 return;
7071 /* Now we must call the relevant TRANS2 function */
7072 switch(state->call) {
7073 case TRANSACT2_OPEN:
7075 START_PROFILE(Trans2_open);
7076 call_trans2open(conn, req,
7077 &state->param, state->total_param,
7078 &state->data, state->total_data,
7079 state->max_data_return);
7080 END_PROFILE(Trans2_open);
7081 break;
7084 case TRANSACT2_FINDFIRST:
7086 START_PROFILE(Trans2_findfirst);
7087 call_trans2findfirst(conn, req,
7088 &state->param, state->total_param,
7089 &state->data, state->total_data,
7090 state->max_data_return);
7091 END_PROFILE(Trans2_findfirst);
7092 break;
7095 case TRANSACT2_FINDNEXT:
7097 START_PROFILE(Trans2_findnext);
7098 call_trans2findnext(conn, req,
7099 &state->param, state->total_param,
7100 &state->data, state->total_data,
7101 state->max_data_return);
7102 END_PROFILE(Trans2_findnext);
7103 break;
7106 case TRANSACT2_QFSINFO:
7108 START_PROFILE(Trans2_qfsinfo);
7109 call_trans2qfsinfo(conn, req,
7110 &state->param, state->total_param,
7111 &state->data, state->total_data,
7112 state->max_data_return);
7113 END_PROFILE(Trans2_qfsinfo);
7114 break;
7117 case TRANSACT2_SETFSINFO:
7119 START_PROFILE(Trans2_setfsinfo);
7120 call_trans2setfsinfo(conn, req,
7121 &state->param, state->total_param,
7122 &state->data, state->total_data,
7123 state->max_data_return);
7124 END_PROFILE(Trans2_setfsinfo);
7125 break;
7128 case TRANSACT2_QPATHINFO:
7129 case TRANSACT2_QFILEINFO:
7131 START_PROFILE(Trans2_qpathinfo);
7132 call_trans2qfilepathinfo(conn, req, state->call,
7133 &state->param, state->total_param,
7134 &state->data, state->total_data,
7135 state->max_data_return);
7136 END_PROFILE(Trans2_qpathinfo);
7137 break;
7140 case TRANSACT2_SETPATHINFO:
7141 case TRANSACT2_SETFILEINFO:
7143 START_PROFILE(Trans2_setpathinfo);
7144 call_trans2setfilepathinfo(conn, req, state->call,
7145 &state->param, state->total_param,
7146 &state->data, state->total_data,
7147 state->max_data_return);
7148 END_PROFILE(Trans2_setpathinfo);
7149 break;
7152 case TRANSACT2_FINDNOTIFYFIRST:
7154 START_PROFILE(Trans2_findnotifyfirst);
7155 call_trans2findnotifyfirst(conn, req,
7156 &state->param, state->total_param,
7157 &state->data, state->total_data,
7158 state->max_data_return);
7159 END_PROFILE(Trans2_findnotifyfirst);
7160 break;
7163 case TRANSACT2_FINDNOTIFYNEXT:
7165 START_PROFILE(Trans2_findnotifynext);
7166 call_trans2findnotifynext(conn, req,
7167 &state->param, state->total_param,
7168 &state->data, state->total_data,
7169 state->max_data_return);
7170 END_PROFILE(Trans2_findnotifynext);
7171 break;
7174 case TRANSACT2_MKDIR:
7176 START_PROFILE(Trans2_mkdir);
7177 call_trans2mkdir(conn, req,
7178 &state->param, state->total_param,
7179 &state->data, state->total_data,
7180 state->max_data_return);
7181 END_PROFILE(Trans2_mkdir);
7182 break;
7185 case TRANSACT2_GET_DFS_REFERRAL:
7187 START_PROFILE(Trans2_get_dfs_referral);
7188 call_trans2getdfsreferral(conn, req,
7189 &state->param, state->total_param,
7190 &state->data, state->total_data,
7191 state->max_data_return);
7192 END_PROFILE(Trans2_get_dfs_referral);
7193 break;
7196 case TRANSACT2_IOCTL:
7198 START_PROFILE(Trans2_ioctl);
7199 call_trans2ioctl(conn, req,
7200 &state->param, state->total_param,
7201 &state->data, state->total_data,
7202 state->max_data_return);
7203 END_PROFILE(Trans2_ioctl);
7204 break;
7207 default:
7208 /* Error in request */
7209 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7210 reply_doserror(req, ERRSRV,ERRerror);
7214 /****************************************************************************
7215 Reply to a SMBtrans2.
7216 ****************************************************************************/
7218 void reply_trans2(struct smb_request *req)
7220 connection_struct *conn = req->conn;
7221 unsigned int dsoff;
7222 unsigned int dscnt;
7223 unsigned int psoff;
7224 unsigned int pscnt;
7225 unsigned int tran_call;
7226 int size;
7227 struct trans_state *state;
7228 NTSTATUS result;
7230 START_PROFILE(SMBtrans2);
7232 if (req->wct < 14) {
7233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7234 END_PROFILE(SMBtrans2);
7235 return;
7238 dsoff = SVAL(req->inbuf, smb_dsoff);
7239 dscnt = SVAL(req->inbuf, smb_dscnt);
7240 psoff = SVAL(req->inbuf, smb_psoff);
7241 pscnt = SVAL(req->inbuf, smb_pscnt);
7242 tran_call = SVAL(req->inbuf, smb_setup0);
7243 size = smb_len(req->inbuf) + 4;
7245 result = allow_new_trans(conn->pending_trans, req->mid);
7246 if (!NT_STATUS_IS_OK(result)) {
7247 DEBUG(2, ("Got invalid trans2 request: %s\n",
7248 nt_errstr(result)));
7249 reply_nterror(req, result);
7250 END_PROFILE(SMBtrans2);
7251 return;
7254 if (IS_IPC(conn)) {
7255 switch (tran_call) {
7256 /* List the allowed trans2 calls on IPC$ */
7257 case TRANSACT2_OPEN:
7258 case TRANSACT2_GET_DFS_REFERRAL:
7259 case TRANSACT2_QFILEINFO:
7260 case TRANSACT2_QFSINFO:
7261 case TRANSACT2_SETFSINFO:
7262 break;
7263 default:
7264 reply_doserror(req, ERRSRV, ERRaccess);
7265 END_PROFILE(SMBtrans2);
7266 return;
7270 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7271 DEBUG(0, ("talloc failed\n"));
7272 reply_nterror(req, NT_STATUS_NO_MEMORY);
7273 END_PROFILE(SMBtrans2);
7274 return;
7277 state->cmd = SMBtrans2;
7279 state->mid = req->mid;
7280 state->vuid = req->vuid;
7281 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7282 state->setup = NULL;
7283 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7284 state->param = NULL;
7285 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7286 state->data = NULL;
7287 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7288 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7289 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7290 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7291 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7293 state->call = tran_call;
7295 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7296 is so as a sanity check */
7297 if (state->setup_count != 1) {
7299 * Need to have rc=0 for ioctl to get job id for OS/2.
7300 * Network printing will fail if function is not successful.
7301 * Similar function in reply.c will be used if protocol
7302 * is LANMAN1.0 instead of LM1.2X002.
7303 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7304 * outbuf doesn't have to be set(only job id is used).
7306 if ( (state->setup_count == 4)
7307 && (tran_call == TRANSACT2_IOCTL)
7308 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7309 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7310 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7311 } else {
7312 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7313 DEBUG(2,("Transaction is %d\n",tran_call));
7314 TALLOC_FREE(state);
7315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7316 END_PROFILE(SMBtrans2);
7317 return;
7321 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7322 goto bad_param;
7324 if (state->total_data) {
7325 /* Can't use talloc here, the core routines do realloc on the
7326 * params and data. */
7327 state->data = (char *)SMB_MALLOC(state->total_data);
7328 if (state->data == NULL) {
7329 DEBUG(0,("reply_trans2: data malloc fail for %u "
7330 "bytes !\n", (unsigned int)state->total_data));
7331 TALLOC_FREE(state);
7332 reply_nterror(req, NT_STATUS_NO_MEMORY);
7333 END_PROFILE(SMBtrans2);
7334 return;
7336 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7337 goto bad_param;
7338 if ((smb_base(req->inbuf)+dsoff+dscnt
7339 > (char *)req->inbuf + size) ||
7340 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7341 goto bad_param;
7343 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7346 if (state->total_param) {
7347 /* Can't use talloc here, the core routines do realloc on the
7348 * params and data. */
7349 state->param = (char *)SMB_MALLOC(state->total_param);
7350 if (state->param == NULL) {
7351 DEBUG(0,("reply_trans: param malloc fail for %u "
7352 "bytes !\n", (unsigned int)state->total_param));
7353 SAFE_FREE(state->data);
7354 TALLOC_FREE(state);
7355 reply_nterror(req, NT_STATUS_NO_MEMORY);
7356 END_PROFILE(SMBtrans2);
7357 return;
7359 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7360 goto bad_param;
7361 if ((smb_base(req->inbuf)+psoff+pscnt
7362 > (char *)req->inbuf + size) ||
7363 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7364 goto bad_param;
7366 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7369 state->received_data = dscnt;
7370 state->received_param = pscnt;
7372 if ((state->received_param == state->total_param) &&
7373 (state->received_data == state->total_data)) {
7375 handle_trans2(conn, req, state);
7377 SAFE_FREE(state->data);
7378 SAFE_FREE(state->param);
7379 TALLOC_FREE(state);
7380 END_PROFILE(SMBtrans2);
7381 return;
7384 DLIST_ADD(conn->pending_trans, state);
7386 /* We need to send an interim response then receive the rest
7387 of the parameter/data bytes */
7388 reply_outbuf(req, 0, 0);
7389 show_msg((char *)req->outbuf);
7390 END_PROFILE(SMBtrans2);
7391 return;
7393 bad_param:
7395 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7396 SAFE_FREE(state->data);
7397 SAFE_FREE(state->param);
7398 TALLOC_FREE(state);
7399 END_PROFILE(SMBtrans2);
7400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7404 /****************************************************************************
7405 Reply to a SMBtranss2
7406 ****************************************************************************/
7408 void reply_transs2(struct smb_request *req)
7410 connection_struct *conn = req->conn;
7411 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7412 struct trans_state *state;
7413 int size;
7415 START_PROFILE(SMBtranss2);
7417 show_msg((char *)req->inbuf);
7419 if (req->wct < 8) {
7420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7421 END_PROFILE(SMBtranss2);
7422 return;
7425 size = smb_len(req->inbuf)+4;
7427 for (state = conn->pending_trans; state != NULL;
7428 state = state->next) {
7429 if (state->mid == req->mid) {
7430 break;
7434 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7435 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7436 END_PROFILE(SMBtranss2);
7437 return;
7440 /* Revise state->total_param and state->total_data in case they have
7441 changed downwards */
7443 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7444 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7445 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7446 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7448 pcnt = SVAL(req->inbuf, smb_spscnt);
7449 poff = SVAL(req->inbuf, smb_spsoff);
7450 pdisp = SVAL(req->inbuf, smb_spsdisp);
7452 dcnt = SVAL(req->inbuf, smb_sdscnt);
7453 doff = SVAL(req->inbuf, smb_sdsoff);
7454 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7456 state->received_param += pcnt;
7457 state->received_data += dcnt;
7459 if ((state->received_data > state->total_data) ||
7460 (state->received_param > state->total_param))
7461 goto bad_param;
7463 if (pcnt) {
7464 if (pdisp+pcnt > state->total_param)
7465 goto bad_param;
7466 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7467 goto bad_param;
7468 if (pdisp > state->total_param)
7469 goto bad_param;
7470 if ((smb_base(req->inbuf) + poff + pcnt
7471 > (char *)req->inbuf + size) ||
7472 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7473 goto bad_param;
7474 if (state->param + pdisp < state->param)
7475 goto bad_param;
7477 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7478 pcnt);
7481 if (dcnt) {
7482 if (ddisp+dcnt > state->total_data)
7483 goto bad_param;
7484 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7485 goto bad_param;
7486 if (ddisp > state->total_data)
7487 goto bad_param;
7488 if ((smb_base(req->inbuf) + doff + dcnt
7489 > (char *)req->inbuf + size) ||
7490 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7491 goto bad_param;
7492 if (state->data + ddisp < state->data)
7493 goto bad_param;
7495 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7496 dcnt);
7499 if ((state->received_param < state->total_param) ||
7500 (state->received_data < state->total_data)) {
7501 END_PROFILE(SMBtranss2);
7502 return;
7506 * construct_reply_common will copy smb_com from inbuf to
7507 * outbuf. SMBtranss2 is wrong here.
7509 SCVAL(req->inbuf,smb_com,SMBtrans2);
7511 handle_trans2(conn, req, state);
7513 DLIST_REMOVE(conn->pending_trans, state);
7514 SAFE_FREE(state->data);
7515 SAFE_FREE(state->param);
7516 TALLOC_FREE(state);
7518 END_PROFILE(SMBtranss2);
7519 return;
7521 bad_param:
7523 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7524 DLIST_REMOVE(conn->pending_trans, state);
7525 SAFE_FREE(state->data);
7526 SAFE_FREE(state->param);
7527 TALLOC_FREE(state);
7528 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7529 END_PROFILE(SMBtranss2);
7530 return;