Convert call_trans2open to create_file()
[Samba.git] / source / smbd / trans2.c
blobeba8cb50f0443db5c277ee9ea371ec26e9fb1bc1
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, fsp->fh->fd, 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, fsp->fh->fd, 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_init("estimate_ea_size");
301 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
302 talloc_destroy(mem_ctx);
303 return total_ea_len;
306 /****************************************************************************
307 Ensure the EA name is case insensitive by matching any existing EA name.
308 ****************************************************************************/
310 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
312 size_t total_ea_len;
313 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
314 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
316 for (; ea_list; ea_list = ea_list->next) {
317 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
318 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
319 &unix_ea_name[5], ea_list->ea.name));
320 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
321 break;
324 talloc_destroy(mem_ctx);
327 /****************************************************************************
328 Set or delete an extended attribute.
329 ****************************************************************************/
331 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
333 if (!lp_ea_support(SNUM(conn))) {
334 return NT_STATUS_EAS_NOT_SUPPORTED;
337 for (;ea_list; ea_list = ea_list->next) {
338 int ret;
339 fstring unix_ea_name;
341 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
342 fstrcat(unix_ea_name, ea_list->ea.name);
344 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
346 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
348 if (samba_private_attr_name(unix_ea_name)) {
349 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
350 return NT_STATUS_ACCESS_DENIED;
353 if (ea_list->ea.value.length == 0) {
354 /* Remove the attribute. */
355 if (fsp && (fsp->fh->fd != -1)) {
356 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
357 unix_ea_name, fsp->fsp_name));
358 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
359 } else {
360 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
361 unix_ea_name, fname));
362 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
364 #ifdef ENOATTR
365 /* Removing a non existent attribute always succeeds. */
366 if (ret == -1 && errno == ENOATTR) {
367 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
368 unix_ea_name));
369 ret = 0;
371 #endif
372 } else {
373 if (fsp && (fsp->fh->fd != -1)) {
374 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
375 unix_ea_name, fsp->fsp_name));
376 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
377 ea_list->ea.value.data, ea_list->ea.value.length, 0);
378 } else {
379 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
380 unix_ea_name, fname));
381 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
382 ea_list->ea.value.data, ea_list->ea.value.length, 0);
386 if (ret == -1) {
387 #ifdef ENOTSUP
388 if (errno == ENOTSUP) {
389 return NT_STATUS_EAS_NOT_SUPPORTED;
391 #endif
392 return map_nt_error_from_unix(errno);
396 return NT_STATUS_OK;
398 /****************************************************************************
399 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
400 ****************************************************************************/
402 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
404 struct ea_list *ea_list_head = NULL;
405 size_t offset = 0;
407 while (offset + 2 < data_size) {
408 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
409 unsigned int namelen = CVAL(pdata,offset);
411 offset++; /* Go past the namelen byte. */
413 /* integer wrap paranioa. */
414 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
415 (offset > data_size) || (namelen > data_size) ||
416 (offset + namelen >= data_size)) {
417 break;
419 /* Ensure the name is null terminated. */
420 if (pdata[offset + namelen] != '\0') {
421 return NULL;
423 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
424 if (!eal->ea.name) {
425 return NULL;
428 offset += (namelen + 1); /* Go past the name + terminating zero. */
429 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
430 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
433 return ea_list_head;
436 /****************************************************************************
437 Read one EA list entry from the buffer.
438 ****************************************************************************/
440 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
442 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
443 uint16 val_len;
444 unsigned int namelen;
446 if (!eal) {
447 return NULL;
450 if (data_size < 6) {
451 return NULL;
454 eal->ea.flags = CVAL(pdata,0);
455 namelen = CVAL(pdata,1);
456 val_len = SVAL(pdata,2);
458 if (4 + namelen + 1 + val_len > data_size) {
459 return NULL;
462 /* Ensure the name is null terminated. */
463 if (pdata[namelen + 4] != '\0') {
464 return NULL;
466 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
467 if (!eal->ea.name) {
468 return NULL;
471 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
472 if (!eal->ea.value.data) {
473 return NULL;
476 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
478 /* Ensure we're null terminated just in case we print the value. */
479 eal->ea.value.data[val_len] = '\0';
480 /* But don't count the null. */
481 eal->ea.value.length--;
483 if (pbytes_used) {
484 *pbytes_used = 4 + namelen + 1 + val_len;
487 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
488 dump_data(10, eal->ea.value.data, eal->ea.value.length);
490 return eal;
493 /****************************************************************************
494 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
495 ****************************************************************************/
497 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
499 struct ea_list *ea_list_head = NULL;
500 size_t offset = 0;
501 size_t bytes_used = 0;
503 while (offset < data_size) {
504 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
506 if (!eal) {
507 return NULL;
510 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
511 offset += bytes_used;
514 return ea_list_head;
517 /****************************************************************************
518 Count the total EA size needed.
519 ****************************************************************************/
521 static size_t ea_list_size(struct ea_list *ealist)
523 fstring dos_ea_name;
524 struct ea_list *listp;
525 size_t ret = 0;
527 for (listp = ealist; listp; listp = listp->next) {
528 push_ascii_fstring(dos_ea_name, listp->ea.name);
529 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
531 /* Add on 4 for total length. */
532 if (ret) {
533 ret += 4;
536 return ret;
539 /****************************************************************************
540 Return a union of EA's from a file list and a list of names.
541 The TALLOC context for the two lists *MUST* be identical as we steal
542 memory from one list to add to another. JRA.
543 ****************************************************************************/
545 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
547 struct ea_list *nlistp, *flistp;
549 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
550 for (flistp = file_list; flistp; flistp = flistp->next) {
551 if (strequal(nlistp->ea.name, flistp->ea.name)) {
552 break;
556 if (flistp) {
557 /* Copy the data from this entry. */
558 nlistp->ea.flags = flistp->ea.flags;
559 nlistp->ea.value = flistp->ea.value;
560 } else {
561 /* Null entry. */
562 nlistp->ea.flags = 0;
563 ZERO_STRUCT(nlistp->ea.value);
567 *total_ea_len = ea_list_size(name_list);
568 return name_list;
571 /****************************************************************************
572 Send the required number of replies back.
573 We assume all fields other than the data fields are
574 set correctly for the type of call.
575 HACK ! Always assumes smb_setup field is zero.
576 ****************************************************************************/
578 void send_trans2_replies(struct smb_request *req,
579 const char *params,
580 int paramsize,
581 const char *pdata,
582 int datasize,
583 int max_data_bytes)
585 /* As we are using a protocol > LANMAN1 then the max_send
586 variable must have been set in the sessetupX call.
587 This takes precedence over the max_xmit field in the
588 global struct. These different max_xmit variables should
589 be merged as this is now too confusing */
591 int data_to_send = datasize;
592 int params_to_send = paramsize;
593 int useable_space;
594 const char *pp = params;
595 const char *pd = pdata;
596 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
597 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
598 int data_alignment_offset = 0;
599 bool overflow = False;
601 /* Modify the data_to_send and datasize and set the error if
602 we're trying to send more than max_data_bytes. We still send
603 the part of the packet(s) that fit. Strange, but needed
604 for OS/2. */
606 if (max_data_bytes > 0 && datasize > max_data_bytes) {
607 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
608 max_data_bytes, datasize ));
609 datasize = data_to_send = max_data_bytes;
610 overflow = True;
613 /* If there genuinely are no parameters or data to send just send the empty packet */
615 if(params_to_send == 0 && data_to_send == 0) {
616 reply_outbuf(req, 10, 0);
617 show_msg((char *)req->outbuf);
618 return;
621 /* When sending params and data ensure that both are nicely aligned */
622 /* Only do this alignment when there is also data to send - else
623 can cause NT redirector problems. */
625 if (((params_to_send % 4) != 0) && (data_to_send != 0))
626 data_alignment_offset = 4 - (params_to_send % 4);
628 /* Space is bufsize minus Netbios over TCP header minus SMB header */
629 /* The alignment_offset is to align the param bytes on an even byte
630 boundary. NT 4.0 Beta needs this to work correctly. */
632 useable_space = max_send - (smb_size
633 + 2 * 10 /* wct */
634 + alignment_offset
635 + data_alignment_offset);
637 /* useable_space can never be more than max_send minus the alignment offset. */
639 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
641 while (params_to_send || data_to_send) {
642 /* Calculate whether we will totally or partially fill this packet */
644 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
646 /* We can never send more than useable_space */
648 * Note that 'useable_space' does not include the alignment offsets,
649 * but we must include the alignment offsets in the calculation of
650 * the length of the data we send over the wire, as the alignment offsets
651 * are sent here. Fix from Marc_Jacobsen@hp.com.
654 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
656 reply_outbuf(req, 10, total_sent_thistime);
658 /* Set total params and data to be sent */
659 SSVAL(req->outbuf,smb_tprcnt,paramsize);
660 SSVAL(req->outbuf,smb_tdrcnt,datasize);
662 /* Calculate how many parameters and data we can fit into
663 * this packet. Parameters get precedence
666 params_sent_thistime = MIN(params_to_send,useable_space);
667 data_sent_thistime = useable_space - params_sent_thistime;
668 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
670 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
672 /* smb_proff is the offset from the start of the SMB header to the
673 parameter bytes, however the first 4 bytes of outbuf are
674 the Netbios over TCP header. Thus use smb_base() to subtract
675 them from the calculation */
677 SSVAL(req->outbuf,smb_proff,
678 ((smb_buf(req->outbuf)+alignment_offset)
679 - smb_base(req->outbuf)));
681 if(params_sent_thistime == 0)
682 SSVAL(req->outbuf,smb_prdisp,0);
683 else
684 /* Absolute displacement of param bytes sent in this packet */
685 SSVAL(req->outbuf,smb_prdisp,pp - params);
687 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
688 if(data_sent_thistime == 0) {
689 SSVAL(req->outbuf,smb_droff,0);
690 SSVAL(req->outbuf,smb_drdisp, 0);
691 } else {
692 /* The offset of the data bytes is the offset of the
693 parameter bytes plus the number of parameters being sent this time */
694 SSVAL(req->outbuf, smb_droff,
695 ((smb_buf(req->outbuf)+alignment_offset)
696 - smb_base(req->outbuf))
697 + params_sent_thistime + data_alignment_offset);
698 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
701 /* Initialize the padding for alignment */
703 if (alignment_offset != 0) {
704 memset(smb_buf(req->outbuf), 0, alignment_offset);
707 /* Copy the param bytes into the packet */
709 if(params_sent_thistime) {
710 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
711 params_sent_thistime);
714 /* Copy in the data bytes */
715 if(data_sent_thistime) {
716 if (data_alignment_offset != 0) {
717 memset((smb_buf(req->outbuf)+alignment_offset+
718 params_sent_thistime), 0,
719 data_alignment_offset);
721 memcpy(smb_buf(req->outbuf)+alignment_offset
722 +params_sent_thistime+data_alignment_offset,
723 pd,data_sent_thistime);
726 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
727 params_sent_thistime, data_sent_thistime, useable_space));
728 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
729 params_to_send, data_to_send, paramsize, datasize));
731 if (overflow) {
732 error_packet_set((char *)req->outbuf,
733 ERRDOS,ERRbufferoverflow,
734 STATUS_BUFFER_OVERFLOW,
735 __LINE__,__FILE__);
738 /* Send the packet */
739 show_msg((char *)req->outbuf);
740 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
741 exit_server_cleanly("send_trans2_replies: send_smb failed.");
743 TALLOC_FREE(req->outbuf);
745 pp += params_sent_thistime;
746 pd += data_sent_thistime;
748 params_to_send -= params_sent_thistime;
749 data_to_send -= data_sent_thistime;
751 /* Sanity check */
752 if(params_to_send < 0 || data_to_send < 0) {
753 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
754 params_to_send, data_to_send));
755 return;
759 return;
762 /****************************************************************************
763 Reply to a TRANSACT2_OPEN.
764 ****************************************************************************/
766 static void call_trans2open(connection_struct *conn,
767 struct smb_request *req,
768 char **pparams, int total_params,
769 char **ppdata, int total_data,
770 unsigned int max_data_bytes)
772 char *params = *pparams;
773 char *pdata = *ppdata;
774 int deny_mode;
775 int32 open_attr;
776 bool oplock_request;
777 #if 0
778 bool return_additional_info;
779 int16 open_sattr;
780 time_t open_time;
781 #endif
782 int open_ofun;
783 uint32 open_size;
784 char *pname;
785 char *fname = NULL;
786 SMB_OFF_T size=0;
787 int fattr=0,mtime=0;
788 SMB_INO_T inode = 0;
789 SMB_STRUCT_STAT sbuf;
790 int smb_action = 0;
791 files_struct *fsp;
792 struct ea_list *ea_list = NULL;
793 uint16 flags = 0;
794 NTSTATUS status;
795 uint32 access_mask;
796 uint32 share_mode;
797 uint32 create_disposition;
798 uint32 create_options = 0;
799 TALLOC_CTX *ctx = talloc_tos();
802 * Ensure we have enough parameters to perform the operation.
805 if (total_params < 29) {
806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
807 return;
810 flags = SVAL(params, 0);
811 deny_mode = SVAL(params, 2);
812 open_attr = SVAL(params,6);
813 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
814 if (oplock_request) {
815 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
818 #if 0
819 return_additional_info = BITSETW(params,0);
820 open_sattr = SVAL(params, 4);
821 open_time = make_unix_date3(params+8);
822 #endif
823 open_ofun = SVAL(params,12);
824 open_size = IVAL(params,14);
825 pname = &params[28];
827 if (IS_IPC(conn)) {
828 reply_doserror(req, ERRSRV, ERRaccess);
829 return;
832 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
833 total_params - 28, STR_TERMINATE,
834 &status);
835 if (!NT_STATUS_IS_OK(status)) {
836 reply_nterror(req, status);
837 return;
840 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
841 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
842 (unsigned int)open_ofun, open_size));
844 if (open_ofun == 0) {
845 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
846 return;
849 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
850 &access_mask,
851 &share_mode,
852 &create_disposition,
853 &create_options)) {
854 reply_doserror(req, ERRDOS, ERRbadaccess);
855 return;
858 /* Any data in this call is an EA list. */
859 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
860 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
861 return;
864 if (total_data != 4) {
865 if (total_data < 10) {
866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
867 return;
870 if (IVAL(pdata,0) > total_data) {
871 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
872 IVAL(pdata,0), (unsigned int)total_data));
873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
874 return;
877 ea_list = read_ea_list(talloc_tos(), pdata + 4,
878 total_data - 4);
879 if (!ea_list) {
880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
881 return;
883 } else if (IVAL(pdata,0) != 4) {
884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
885 return;
888 status = create_file(conn, /* conn */
889 req, /* req */
890 0, /* root_dir_fid */
891 fname, /* fname */
892 access_mask, /* access_mask */
893 share_mode, /* share_access */
894 create_disposition, /* create_disposition*/
895 create_options, /* create_options */
896 open_attr, /* file_attributes */
897 oplock_request, /* oplock_request */
898 open_size, /* allocation_size */
899 NULL, /* sd */
900 ea_list, /* ea_list */
901 &fsp, /* result */
902 &smb_action, /* pinfo */
903 &sbuf); /* psbuf */
905 if (!NT_STATUS_IS_OK(status)) {
906 if (open_was_deferred(req->mid)) {
907 /* We have re-scheduled this call. */
908 return;
910 reply_openerror(req, status);
911 return;
914 size = get_file_size(sbuf);
915 fattr = dos_mode(conn,fname,&sbuf);
916 mtime = sbuf.st_mtime;
917 inode = sbuf.st_ino;
918 if (fattr & aDIR) {
919 close_file(fsp,ERROR_CLOSE);
920 reply_doserror(req, ERRDOS,ERRnoaccess);
921 return;
924 /* Realloc the size of parameters and data we will return */
925 *pparams = (char *)SMB_REALLOC(*pparams, 30);
926 if(*pparams == NULL ) {
927 reply_nterror(req, NT_STATUS_NO_MEMORY);
928 return;
930 params = *pparams;
932 SSVAL(params,0,fsp->fnum);
933 SSVAL(params,2,fattr);
934 srv_put_dos_date2(params,4, mtime);
935 SIVAL(params,8, (uint32)size);
936 SSVAL(params,12,deny_mode);
937 SSVAL(params,14,0); /* open_type - file or directory. */
938 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
940 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
941 smb_action |= EXTENDED_OPLOCK_GRANTED;
944 SSVAL(params,18,smb_action);
947 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
949 SIVAL(params,20,inode);
950 SSVAL(params,24,0); /* Padding. */
951 if (flags & 8) {
952 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
953 SIVAL(params, 26, ea_size);
954 } else {
955 SIVAL(params, 26, 0);
958 /* Send the required number of replies */
959 send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
962 /*********************************************************
963 Routine to check if a given string matches exactly.
964 as a special case a mask of "." does NOT match. That
965 is required for correct wildcard semantics
966 Case can be significant or not.
967 **********************************************************/
969 static bool exact_match(connection_struct *conn,
970 const char *str,
971 const char *mask)
973 if (mask[0] == '.' && mask[1] == 0)
974 return False;
975 if (conn->case_sensitive)
976 return strcmp(str,mask)==0;
977 if (StrCaseCmp(str,mask) != 0) {
978 return False;
980 if (dptr_has_wild(conn->dirptr)) {
981 return False;
983 return True;
986 /****************************************************************************
987 Return the filetype for UNIX extensions.
988 ****************************************************************************/
990 static uint32 unix_filetype(mode_t mode)
992 if(S_ISREG(mode))
993 return UNIX_TYPE_FILE;
994 else if(S_ISDIR(mode))
995 return UNIX_TYPE_DIR;
996 #ifdef S_ISLNK
997 else if(S_ISLNK(mode))
998 return UNIX_TYPE_SYMLINK;
999 #endif
1000 #ifdef S_ISCHR
1001 else if(S_ISCHR(mode))
1002 return UNIX_TYPE_CHARDEV;
1003 #endif
1004 #ifdef S_ISBLK
1005 else if(S_ISBLK(mode))
1006 return UNIX_TYPE_BLKDEV;
1007 #endif
1008 #ifdef S_ISFIFO
1009 else if(S_ISFIFO(mode))
1010 return UNIX_TYPE_FIFO;
1011 #endif
1012 #ifdef S_ISSOCK
1013 else if(S_ISSOCK(mode))
1014 return UNIX_TYPE_SOCKET;
1015 #endif
1017 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1018 return UNIX_TYPE_UNKNOWN;
1021 /****************************************************************************
1022 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1023 ****************************************************************************/
1025 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1027 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1028 SMB_STRUCT_STAT *psbuf,
1029 uint32 perms,
1030 enum perm_type ptype,
1031 mode_t *ret_perms)
1033 mode_t ret = 0;
1035 if (perms == SMB_MODE_NO_CHANGE) {
1036 if (!VALID_STAT(*psbuf)) {
1037 return NT_STATUS_INVALID_PARAMETER;
1038 } else {
1039 *ret_perms = psbuf->st_mode;
1040 return NT_STATUS_OK;
1044 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1045 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1046 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1047 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1048 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1049 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1050 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1051 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1052 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1053 #ifdef S_ISVTX
1054 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1055 #endif
1056 #ifdef S_ISGID
1057 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1058 #endif
1059 #ifdef S_ISUID
1060 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1061 #endif
1063 switch (ptype) {
1064 case PERM_NEW_FILE:
1065 /* Apply mode mask */
1066 ret &= lp_create_mask(SNUM(conn));
1067 /* Add in force bits */
1068 ret |= lp_force_create_mode(SNUM(conn));
1069 break;
1070 case PERM_NEW_DIR:
1071 ret &= lp_dir_mask(SNUM(conn));
1072 /* Add in force bits */
1073 ret |= lp_force_dir_mode(SNUM(conn));
1074 break;
1075 case PERM_EXISTING_FILE:
1076 /* Apply mode mask */
1077 ret &= lp_security_mask(SNUM(conn));
1078 /* Add in force bits */
1079 ret |= lp_force_security_mode(SNUM(conn));
1080 break;
1081 case PERM_EXISTING_DIR:
1082 /* Apply mode mask */
1083 ret &= lp_dir_security_mask(SNUM(conn));
1084 /* Add in force bits */
1085 ret |= lp_force_dir_security_mode(SNUM(conn));
1086 break;
1089 *ret_perms = ret;
1090 return NT_STATUS_OK;
1093 /****************************************************************************
1094 Get a level dependent lanman2 dir entry.
1095 ****************************************************************************/
1097 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1098 connection_struct *conn,
1099 uint16 flags2,
1100 const char *path_mask,
1101 uint32 dirtype,
1102 int info_level,
1103 int requires_resume_key,
1104 bool dont_descend,
1105 char **ppdata,
1106 char *base_data,
1107 char *end_data,
1108 int space_remaining,
1109 bool *out_of_space,
1110 bool *got_exact_match,
1111 int *last_entry_off,
1112 struct ea_list *name_list)
1114 const char *dname;
1115 bool found = False;
1116 SMB_STRUCT_STAT sbuf;
1117 const char *mask = NULL;
1118 char *pathreal = NULL;
1119 const char *fname = NULL;
1120 char *p, *q, *pdata = *ppdata;
1121 uint32 reskey=0;
1122 long prev_dirpos=0;
1123 uint32 mode=0;
1124 SMB_OFF_T file_size = 0;
1125 SMB_BIG_UINT allocation_size = 0;
1126 uint32 len;
1127 struct timespec mdate_ts, adate_ts, create_date_ts;
1128 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1129 char *nameptr;
1130 char *last_entry_ptr;
1131 bool was_8_3;
1132 uint32 nt_extmode; /* Used for NT connections instead of mode */
1133 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1134 bool check_mangled_names = lp_manglednames(conn->params);
1135 char mangled_name[13]; /* mangled 8.3 name. */
1137 *out_of_space = False;
1138 *got_exact_match = False;
1140 ZERO_STRUCT(mdate_ts);
1141 ZERO_STRUCT(adate_ts);
1142 ZERO_STRUCT(create_date_ts);
1144 if (!conn->dirptr) {
1145 return(False);
1148 p = strrchr_m(path_mask,'/');
1149 if(p != NULL) {
1150 if(p[1] == '\0') {
1151 mask = talloc_strdup(ctx,"*.*");
1152 } else {
1153 mask = p+1;
1155 } else {
1156 mask = path_mask;
1159 while (!found) {
1160 bool got_match;
1161 bool ms_dfs_link = False;
1163 /* Needed if we run out of space */
1164 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1165 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1168 * Due to bugs in NT client redirectors we are not using
1169 * resume keys any more - set them to zero.
1170 * Check out the related comments in findfirst/findnext.
1171 * JRA.
1174 reskey = 0;
1176 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1177 (long)conn->dirptr,curr_dirpos));
1179 if (!dname) {
1180 return(False);
1184 * fname may get mangled, dname is never mangled.
1185 * Whenever we're accessing the filesystem we use
1186 * pathreal which is composed from dname.
1189 pathreal = NULL;
1190 fname = dname;
1192 /* Mangle fname if it's an illegal name. */
1193 if (mangle_must_mangle(dname,conn->params)) {
1194 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1195 continue; /* Error - couldn't mangle. */
1197 fname = mangled_name;
1200 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1201 got_match = mask_match(fname, mask, conn->case_sensitive);
1204 if(!got_match && check_mangled_names &&
1205 !mangle_is_8_3(fname, False, conn->params)) {
1207 * It turns out that NT matches wildcards against
1208 * both long *and* short names. This may explain some
1209 * of the wildcard wierdness from old DOS clients
1210 * that some people have been seeing.... JRA.
1212 /* Force the mangling into 8.3. */
1213 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1214 continue; /* Error - couldn't mangle. */
1217 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1218 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1222 if (got_match) {
1223 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1225 if (dont_descend && !isdots) {
1226 continue;
1229 if (needslash) {
1230 pathreal = NULL;
1231 pathreal = talloc_asprintf(ctx,
1232 "%s/%s",
1233 conn->dirpath,
1234 dname);
1235 } else {
1236 pathreal = talloc_asprintf(ctx,
1237 "%s%s",
1238 conn->dirpath,
1239 dname);
1242 if (!pathreal) {
1243 return False;
1246 if (INFO_LEVEL_IS_UNIX(info_level)) {
1247 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1248 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1249 pathreal,strerror(errno)));
1250 TALLOC_FREE(pathreal);
1251 continue;
1253 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1254 /* Needed to show the msdfs symlinks as
1255 * directories */
1257 if(lp_host_msdfs() &&
1258 lp_msdfs_root(SNUM(conn)) &&
1259 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1260 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1261 "as a directory\n",
1262 pathreal));
1263 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1265 } else {
1267 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1268 pathreal,strerror(errno)));
1269 TALLOC_FREE(pathreal);
1270 continue;
1274 if (ms_dfs_link) {
1275 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1276 } else {
1277 mode = dos_mode(conn,pathreal,&sbuf);
1280 if (!dir_check_ftype(conn,mode,dirtype)) {
1281 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1282 TALLOC_FREE(pathreal);
1283 continue;
1286 if (!(mode & aDIR)) {
1287 file_size = get_file_size(sbuf);
1289 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1291 mdate_ts = get_mtimespec(&sbuf);
1292 adate_ts = get_atimespec(&sbuf);
1293 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1295 if (lp_dos_filetime_resolution(SNUM(conn))) {
1296 dos_filetime_timespec(&create_date_ts);
1297 dos_filetime_timespec(&mdate_ts);
1298 dos_filetime_timespec(&adate_ts);
1301 create_date = convert_timespec_to_time_t(create_date_ts);
1302 mdate = convert_timespec_to_time_t(mdate_ts);
1303 adate = convert_timespec_to_time_t(adate_ts);
1305 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1307 found = True;
1309 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1313 p = pdata;
1314 last_entry_ptr = p;
1316 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1318 switch (info_level) {
1319 case SMB_FIND_INFO_STANDARD:
1320 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1321 if(requires_resume_key) {
1322 SIVAL(p,0,reskey);
1323 p += 4;
1325 srv_put_dos_date2(p,0,create_date);
1326 srv_put_dos_date2(p,4,adate);
1327 srv_put_dos_date2(p,8,mdate);
1328 SIVAL(p,12,(uint32)file_size);
1329 SIVAL(p,16,(uint32)allocation_size);
1330 SSVAL(p,20,mode);
1331 p += 23;
1332 nameptr = p;
1333 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1334 p += ucs2_align(base_data, p, 0);
1336 len = srvstr_push(base_data, flags2, p,
1337 fname, PTR_DIFF(end_data, p),
1338 STR_TERMINATE);
1339 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1340 if (len > 2) {
1341 SCVAL(nameptr, -1, len - 2);
1342 } else {
1343 SCVAL(nameptr, -1, 0);
1345 } else {
1346 if (len > 1) {
1347 SCVAL(nameptr, -1, len - 1);
1348 } else {
1349 SCVAL(nameptr, -1, 0);
1352 p += len;
1353 break;
1355 case SMB_FIND_EA_SIZE:
1356 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1357 if(requires_resume_key) {
1358 SIVAL(p,0,reskey);
1359 p += 4;
1361 srv_put_dos_date2(p,0,create_date);
1362 srv_put_dos_date2(p,4,adate);
1363 srv_put_dos_date2(p,8,mdate);
1364 SIVAL(p,12,(uint32)file_size);
1365 SIVAL(p,16,(uint32)allocation_size);
1366 SSVAL(p,20,mode);
1368 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1369 SIVAL(p,22,ea_size); /* Extended attributes */
1371 p += 27;
1372 nameptr = p - 1;
1373 len = srvstr_push(base_data, flags2,
1374 p, fname, PTR_DIFF(end_data, p),
1375 STR_TERMINATE | STR_NOALIGN);
1376 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1377 if (len > 2) {
1378 len -= 2;
1379 } else {
1380 len = 0;
1382 } else {
1383 if (len > 1) {
1384 len -= 1;
1385 } else {
1386 len = 0;
1389 SCVAL(nameptr,0,len);
1390 p += len;
1391 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1392 break;
1394 case SMB_FIND_EA_LIST:
1396 struct ea_list *file_list = NULL;
1397 size_t ea_len = 0;
1399 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1400 if (!name_list) {
1401 return False;
1403 if(requires_resume_key) {
1404 SIVAL(p,0,reskey);
1405 p += 4;
1407 srv_put_dos_date2(p,0,create_date);
1408 srv_put_dos_date2(p,4,adate);
1409 srv_put_dos_date2(p,8,mdate);
1410 SIVAL(p,12,(uint32)file_size);
1411 SIVAL(p,16,(uint32)allocation_size);
1412 SSVAL(p,20,mode);
1413 p += 22; /* p now points to the EA area. */
1415 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1416 name_list = ea_list_union(name_list, file_list, &ea_len);
1418 /* We need to determine if this entry will fit in the space available. */
1419 /* Max string size is 255 bytes. */
1420 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1421 /* Move the dirptr back to prev_dirpos */
1422 dptr_SeekDir(conn->dirptr, prev_dirpos);
1423 *out_of_space = True;
1424 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1425 return False; /* Not finished - just out of space */
1428 /* Push the ea_data followed by the name. */
1429 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1430 nameptr = p;
1431 len = srvstr_push(base_data, flags2,
1432 p + 1, fname, PTR_DIFF(end_data, p+1),
1433 STR_TERMINATE | STR_NOALIGN);
1434 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1435 if (len > 2) {
1436 len -= 2;
1437 } else {
1438 len = 0;
1440 } else {
1441 if (len > 1) {
1442 len -= 1;
1443 } else {
1444 len = 0;
1447 SCVAL(nameptr,0,len);
1448 p += len + 1;
1449 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1450 break;
1453 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1454 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1455 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1456 p += 4;
1457 SIVAL(p,0,reskey); p += 4;
1458 put_long_date_timespec(p,create_date_ts); p += 8;
1459 put_long_date_timespec(p,adate_ts); p += 8;
1460 put_long_date_timespec(p,mdate_ts); p += 8;
1461 put_long_date_timespec(p,mdate_ts); p += 8;
1462 SOFF_T(p,0,file_size); p += 8;
1463 SOFF_T(p,0,allocation_size); p += 8;
1464 SIVAL(p,0,nt_extmode); p += 4;
1465 q = p; p += 4; /* q is placeholder for name length. */
1467 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1468 SIVAL(p,0,ea_size); /* Extended attributes */
1469 p += 4;
1471 /* Clear the short name buffer. This is
1472 * IMPORTANT as not doing so will trigger
1473 * a Win2k client bug. JRA.
1475 if (!was_8_3 && check_mangled_names) {
1476 if (!name_to_8_3(fname,mangled_name,True,
1477 conn->params)) {
1478 /* Error - mangle failed ! */
1479 memset(mangled_name,'\0',12);
1481 mangled_name[12] = 0;
1482 len = srvstr_push(base_data, flags2,
1483 p+2, mangled_name, 24,
1484 STR_UPPER|STR_UNICODE);
1485 if (len < 24) {
1486 memset(p + 2 + len,'\0',24 - len);
1488 SSVAL(p, 0, len);
1489 } else {
1490 memset(p,'\0',26);
1492 p += 2 + 24;
1493 len = srvstr_push(base_data, flags2, p,
1494 fname, PTR_DIFF(end_data, p),
1495 STR_TERMINATE_ASCII);
1496 SIVAL(q,0,len);
1497 p += len;
1498 SIVAL(p,0,0); /* Ensure any padding is null. */
1499 len = PTR_DIFF(p, pdata);
1500 len = (len + 3) & ~3;
1501 SIVAL(pdata,0,len);
1502 p = pdata + len;
1503 break;
1505 case SMB_FIND_FILE_DIRECTORY_INFO:
1506 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1507 p += 4;
1508 SIVAL(p,0,reskey); p += 4;
1509 put_long_date_timespec(p,create_date_ts); p += 8;
1510 put_long_date_timespec(p,adate_ts); p += 8;
1511 put_long_date_timespec(p,mdate_ts); p += 8;
1512 put_long_date_timespec(p,mdate_ts); p += 8;
1513 SOFF_T(p,0,file_size); p += 8;
1514 SOFF_T(p,0,allocation_size); p += 8;
1515 SIVAL(p,0,nt_extmode); p += 4;
1516 len = srvstr_push(base_data, flags2,
1517 p + 4, fname, PTR_DIFF(end_data, p+4),
1518 STR_TERMINATE_ASCII);
1519 SIVAL(p,0,len);
1520 p += 4 + len;
1521 SIVAL(p,0,0); /* Ensure any padding is null. */
1522 len = PTR_DIFF(p, pdata);
1523 len = (len + 3) & ~3;
1524 SIVAL(pdata,0,len);
1525 p = pdata + len;
1526 break;
1528 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1529 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1530 p += 4;
1531 SIVAL(p,0,reskey); p += 4;
1532 put_long_date_timespec(p,create_date_ts); p += 8;
1533 put_long_date_timespec(p,adate_ts); p += 8;
1534 put_long_date_timespec(p,mdate_ts); p += 8;
1535 put_long_date_timespec(p,mdate_ts); p += 8;
1536 SOFF_T(p,0,file_size); p += 8;
1537 SOFF_T(p,0,allocation_size); p += 8;
1538 SIVAL(p,0,nt_extmode); p += 4;
1539 q = p; p += 4; /* q is placeholder for name length. */
1541 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1542 SIVAL(p,0,ea_size); /* Extended attributes */
1543 p +=4;
1545 len = srvstr_push(base_data, flags2, p,
1546 fname, PTR_DIFF(end_data, p),
1547 STR_TERMINATE_ASCII);
1548 SIVAL(q, 0, len);
1549 p += len;
1551 SIVAL(p,0,0); /* Ensure any padding is null. */
1552 len = PTR_DIFF(p, pdata);
1553 len = (len + 3) & ~3;
1554 SIVAL(pdata,0,len);
1555 p = pdata + len;
1556 break;
1558 case SMB_FIND_FILE_NAMES_INFO:
1559 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1560 p += 4;
1561 SIVAL(p,0,reskey); p += 4;
1562 p += 4;
1563 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1564 acl on a dir (tridge) */
1565 len = srvstr_push(base_data, flags2, p,
1566 fname, PTR_DIFF(end_data, p),
1567 STR_TERMINATE_ASCII);
1568 SIVAL(p, -4, len);
1569 p += len;
1570 SIVAL(p,0,0); /* Ensure any padding is null. */
1571 len = PTR_DIFF(p, pdata);
1572 len = (len + 3) & ~3;
1573 SIVAL(pdata,0,len);
1574 p = pdata + len;
1575 break;
1577 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1578 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1579 p += 4;
1580 SIVAL(p,0,reskey); p += 4;
1581 put_long_date_timespec(p,create_date_ts); p += 8;
1582 put_long_date_timespec(p,adate_ts); p += 8;
1583 put_long_date_timespec(p,mdate_ts); p += 8;
1584 put_long_date_timespec(p,mdate_ts); p += 8;
1585 SOFF_T(p,0,file_size); p += 8;
1586 SOFF_T(p,0,allocation_size); p += 8;
1587 SIVAL(p,0,nt_extmode); p += 4;
1588 q = p; p += 4; /* q is placeholder for name length. */
1590 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1591 SIVAL(p,0,ea_size); /* Extended attributes */
1592 p +=4;
1594 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1595 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1596 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1597 len = srvstr_push(base_data, flags2, p,
1598 fname, PTR_DIFF(end_data, p),
1599 STR_TERMINATE_ASCII);
1600 SIVAL(q, 0, len);
1601 p += len;
1602 SIVAL(p,0,0); /* Ensure any padding is null. */
1603 len = PTR_DIFF(p, pdata);
1604 len = (len + 3) & ~3;
1605 SIVAL(pdata,0,len);
1606 p = pdata + len;
1607 break;
1609 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1610 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1611 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1612 p += 4;
1613 SIVAL(p,0,reskey); p += 4;
1614 put_long_date_timespec(p,create_date_ts); p += 8;
1615 put_long_date_timespec(p,adate_ts); p += 8;
1616 put_long_date_timespec(p,mdate_ts); p += 8;
1617 put_long_date_timespec(p,mdate_ts); p += 8;
1618 SOFF_T(p,0,file_size); p += 8;
1619 SOFF_T(p,0,allocation_size); p += 8;
1620 SIVAL(p,0,nt_extmode); p += 4;
1621 q = p; p += 4; /* q is placeholder for name length */
1623 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1624 SIVAL(p,0,ea_size); /* Extended attributes */
1625 p +=4;
1627 /* Clear the short name buffer. This is
1628 * IMPORTANT as not doing so will trigger
1629 * a Win2k client bug. JRA.
1631 if (!was_8_3 && check_mangled_names) {
1632 if (!name_to_8_3(fname,mangled_name,True,
1633 conn->params)) {
1634 /* Error - mangle failed ! */
1635 memset(mangled_name,'\0',12);
1637 mangled_name[12] = 0;
1638 len = srvstr_push(base_data, flags2,
1639 p+2, mangled_name, 24,
1640 STR_UPPER|STR_UNICODE);
1641 SSVAL(p, 0, len);
1642 if (len < 24) {
1643 memset(p + 2 + len,'\0',24 - len);
1645 SSVAL(p, 0, len);
1646 } else {
1647 memset(p,'\0',26);
1649 p += 26;
1650 SSVAL(p,0,0); p += 2; /* Reserved ? */
1651 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1652 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1653 len = srvstr_push(base_data, flags2, p,
1654 fname, PTR_DIFF(end_data, p),
1655 STR_TERMINATE_ASCII);
1656 SIVAL(q,0,len);
1657 p += len;
1658 SIVAL(p,0,0); /* Ensure any padding is null. */
1659 len = PTR_DIFF(p, pdata);
1660 len = (len + 3) & ~3;
1661 SIVAL(pdata,0,len);
1662 p = pdata + len;
1663 break;
1665 /* CIFS UNIX Extension. */
1667 case SMB_FIND_FILE_UNIX:
1668 case SMB_FIND_FILE_UNIX_INFO2:
1669 p+= 4;
1670 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1672 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1674 if (info_level == SMB_FIND_FILE_UNIX) {
1675 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1676 p = store_file_unix_basic(conn, p,
1677 NULL, &sbuf);
1678 len = srvstr_push(base_data, flags2, p,
1679 fname, PTR_DIFF(end_data, p),
1680 STR_TERMINATE);
1681 } else {
1682 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1683 p = store_file_unix_basic_info2(conn, p,
1684 NULL, &sbuf);
1685 nameptr = p;
1686 p += 4;
1687 len = srvstr_push(base_data, flags2, p, fname,
1688 PTR_DIFF(end_data, p), 0);
1689 SIVAL(nameptr, 0, len);
1692 p += len;
1693 SIVAL(p,0,0); /* Ensure any padding is null. */
1695 len = PTR_DIFF(p, pdata);
1696 len = (len + 3) & ~3;
1697 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1698 p = pdata + len;
1699 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1701 break;
1703 default:
1704 return(False);
1708 if (PTR_DIFF(p,pdata) > space_remaining) {
1709 /* Move the dirptr back to prev_dirpos */
1710 dptr_SeekDir(conn->dirptr, prev_dirpos);
1711 *out_of_space = True;
1712 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1713 return False; /* Not finished - just out of space */
1716 /* Setup the last entry pointer, as an offset from base_data */
1717 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1718 /* Advance the data pointer to the next slot */
1719 *ppdata = p;
1721 return(found);
1724 /****************************************************************************
1725 Reply to a TRANS2_FINDFIRST.
1726 ****************************************************************************/
1728 static void call_trans2findfirst(connection_struct *conn,
1729 struct smb_request *req,
1730 char **pparams, int total_params,
1731 char **ppdata, int total_data,
1732 unsigned int max_data_bytes)
1734 /* We must be careful here that we don't return more than the
1735 allowed number of data bytes. If this means returning fewer than
1736 maxentries then so be it. We assume that the redirector has
1737 enough room for the fixed number of parameter bytes it has
1738 requested. */
1739 char *params = *pparams;
1740 char *pdata = *ppdata;
1741 char *data_end;
1742 uint32 dirtype;
1743 int maxentries;
1744 uint16 findfirst_flags;
1745 bool close_after_first;
1746 bool close_if_end;
1747 bool requires_resume_key;
1748 int info_level;
1749 char *directory = NULL;
1750 const char *mask = NULL;
1751 char *p;
1752 int last_entry_off=0;
1753 int dptr_num = -1;
1754 int numentries = 0;
1755 int i;
1756 bool finished = False;
1757 bool dont_descend = False;
1758 bool out_of_space = False;
1759 int space_remaining;
1760 bool mask_contains_wcard = False;
1761 SMB_STRUCT_STAT sbuf;
1762 struct ea_list *ea_list = NULL;
1763 NTSTATUS ntstatus = NT_STATUS_OK;
1764 TALLOC_CTX *ctx = talloc_tos();
1766 if (total_params < 13) {
1767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1768 return;
1771 dirtype = SVAL(params,0);
1772 maxentries = SVAL(params,2);
1773 findfirst_flags = SVAL(params,4);
1774 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1775 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1776 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1777 info_level = SVAL(params,6);
1779 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1780 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1781 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1782 info_level, max_data_bytes));
1784 if (!maxentries) {
1785 /* W2K3 seems to treat zero as 1. */
1786 maxentries = 1;
1789 switch (info_level) {
1790 case SMB_FIND_INFO_STANDARD:
1791 case SMB_FIND_EA_SIZE:
1792 case SMB_FIND_EA_LIST:
1793 case SMB_FIND_FILE_DIRECTORY_INFO:
1794 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1795 case SMB_FIND_FILE_NAMES_INFO:
1796 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1797 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1798 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1799 break;
1800 case SMB_FIND_FILE_UNIX:
1801 case SMB_FIND_FILE_UNIX_INFO2:
1802 if (!lp_unix_extensions()) {
1803 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1804 return;
1806 break;
1807 default:
1808 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1809 return;
1812 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1813 params+12, total_params - 12,
1814 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1815 if (!NT_STATUS_IS_OK(ntstatus)) {
1816 reply_nterror(req, ntstatus);
1817 return;
1820 ntstatus = resolve_dfspath_wcard(ctx, conn,
1821 req->flags2 & FLAGS2_DFS_PATHNAMES,
1822 directory,
1823 &directory,
1824 &mask_contains_wcard);
1825 if (!NT_STATUS_IS_OK(ntstatus)) {
1826 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1827 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1828 ERRSRV, ERRbadpath);
1829 return;
1831 reply_nterror(req, ntstatus);
1832 return;
1835 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1836 if (!NT_STATUS_IS_OK(ntstatus)) {
1837 reply_nterror(req, ntstatus);
1838 return;
1841 ntstatus = check_name(conn, directory);
1842 if (!NT_STATUS_IS_OK(ntstatus)) {
1843 reply_nterror(req, ntstatus);
1844 return;
1847 p = strrchr_m(directory,'/');
1848 if(p == NULL) {
1849 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1850 if((directory[0] == '.') && (directory[1] == '\0')) {
1851 mask = "*";
1852 mask_contains_wcard = True;
1853 } else {
1854 mask = directory;
1856 directory = talloc_strdup(talloc_tos(), "./");
1857 if (!directory) {
1858 reply_nterror(req, NT_STATUS_NO_MEMORY);
1859 return;
1861 } else {
1862 mask = p+1;
1863 *p = 0;
1866 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1868 if (info_level == SMB_FIND_EA_LIST) {
1869 uint32 ea_size;
1871 if (total_data < 4) {
1872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1873 return;
1876 ea_size = IVAL(pdata,0);
1877 if (ea_size != total_data) {
1878 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1879 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1881 return;
1884 if (!lp_ea_support(SNUM(conn))) {
1885 reply_doserror(req, ERRDOS, ERReasnotsupported);
1886 return;
1889 /* Pull out the list of names. */
1890 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1891 if (!ea_list) {
1892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1893 return;
1897 *ppdata = (char *)SMB_REALLOC(
1898 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1899 if(*ppdata == NULL ) {
1900 reply_nterror(req, NT_STATUS_NO_MEMORY);
1901 return;
1903 pdata = *ppdata;
1904 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1906 /* Realloc the params space */
1907 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1908 if (*pparams == NULL) {
1909 reply_nterror(req, NT_STATUS_NO_MEMORY);
1910 return;
1912 params = *pparams;
1914 /* Save the wildcard match and attribs we are using on this directory -
1915 needed as lanman2 assumes these are being saved between calls */
1917 ntstatus = dptr_create(conn,
1918 directory,
1919 False,
1920 True,
1921 req->smbpid,
1922 mask,
1923 mask_contains_wcard,
1924 dirtype,
1925 &conn->dirptr);
1927 if (!NT_STATUS_IS_OK(ntstatus)) {
1928 reply_nterror(req, ntstatus);
1929 return;
1932 dptr_num = dptr_dnum(conn->dirptr);
1933 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1935 /* We don't need to check for VOL here as this is returned by
1936 a different TRANS2 call. */
1938 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1939 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1940 dont_descend = True;
1942 p = pdata;
1943 space_remaining = max_data_bytes;
1944 out_of_space = False;
1946 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1947 bool got_exact_match = False;
1949 /* this is a heuristic to avoid seeking the dirptr except when
1950 absolutely necessary. It allows for a filename of about 40 chars */
1951 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1952 out_of_space = True;
1953 finished = False;
1954 } else {
1955 TALLOC_CTX *sub_ctx = talloc_stackframe();
1957 finished = !get_lanman2_dir_entry(sub_ctx,
1958 conn,
1959 req->flags2,
1960 mask,dirtype,info_level,
1961 requires_resume_key,dont_descend,
1962 &p,pdata,data_end,
1963 space_remaining, &out_of_space,
1964 &got_exact_match,
1965 &last_entry_off, ea_list);
1967 TALLOC_FREE(sub_ctx);
1970 if (finished && out_of_space)
1971 finished = False;
1973 if (!finished && !out_of_space)
1974 numentries++;
1977 * As an optimisation if we know we aren't looking
1978 * for a wildcard name (ie. the name matches the wildcard exactly)
1979 * then we can finish on any (first) match.
1980 * This speeds up large directory searches. JRA.
1983 if(got_exact_match)
1984 finished = True;
1986 /* Ensure space_remaining never goes -ve. */
1987 if (PTR_DIFF(p,pdata) > max_data_bytes) {
1988 space_remaining = 0;
1989 out_of_space = true;
1990 } else {
1991 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1995 /* Check if we can close the dirptr */
1996 if(close_after_first || (finished && close_if_end)) {
1997 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1998 dptr_close(&dptr_num);
2002 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2003 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2004 * the protocol level is less than NT1. Tested with smbclient. JRA.
2005 * This should fix the OS/2 client bug #2335.
2008 if(numentries == 0) {
2009 dptr_close(&dptr_num);
2010 if (Protocol < PROTOCOL_NT1) {
2011 reply_doserror(req, ERRDOS, ERRnofiles);
2012 return;
2013 } else {
2014 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2015 ERRDOS, ERRbadfile);
2016 return;
2020 /* At this point pdata points to numentries directory entries. */
2022 /* Set up the return parameter block */
2023 SSVAL(params,0,dptr_num);
2024 SSVAL(params,2,numentries);
2025 SSVAL(params,4,finished);
2026 SSVAL(params,6,0); /* Never an EA error */
2027 SSVAL(params,8,last_entry_off);
2029 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2030 max_data_bytes);
2032 if ((! *directory) && dptr_path(dptr_num)) {
2033 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2034 if (!directory) {
2035 reply_nterror(req, NT_STATUS_NO_MEMORY);
2039 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2040 smb_fn_name(CVAL(req->inbuf,smb_com)),
2041 mask, directory, dirtype, numentries ) );
2044 * Force a name mangle here to ensure that the
2045 * mask as an 8.3 name is top of the mangled cache.
2046 * The reasons for this are subtle. Don't remove
2047 * this code unless you know what you are doing
2048 * (see PR#13758). JRA.
2051 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2052 char mangled_name[13];
2053 name_to_8_3(mask, mangled_name, True, conn->params);
2056 return;
2059 /****************************************************************************
2060 Reply to a TRANS2_FINDNEXT.
2061 ****************************************************************************/
2063 static void call_trans2findnext(connection_struct *conn,
2064 struct smb_request *req,
2065 char **pparams, int total_params,
2066 char **ppdata, int total_data,
2067 unsigned int max_data_bytes)
2069 /* We must be careful here that we don't return more than the
2070 allowed number of data bytes. If this means returning fewer than
2071 maxentries then so be it. We assume that the redirector has
2072 enough room for the fixed number of parameter bytes it has
2073 requested. */
2074 char *params = *pparams;
2075 char *pdata = *ppdata;
2076 char *data_end;
2077 int dptr_num;
2078 int maxentries;
2079 uint16 info_level;
2080 uint32 resume_key;
2081 uint16 findnext_flags;
2082 bool close_after_request;
2083 bool close_if_end;
2084 bool requires_resume_key;
2085 bool continue_bit;
2086 bool mask_contains_wcard = False;
2087 char *resume_name = NULL;
2088 const char *mask = NULL;
2089 const char *directory = NULL;
2090 char *p = NULL;
2091 uint16 dirtype;
2092 int numentries = 0;
2093 int i, last_entry_off=0;
2094 bool finished = False;
2095 bool dont_descend = False;
2096 bool out_of_space = False;
2097 int space_remaining;
2098 struct ea_list *ea_list = NULL;
2099 NTSTATUS ntstatus = NT_STATUS_OK;
2100 TALLOC_CTX *ctx = talloc_tos();
2102 if (total_params < 13) {
2103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2104 return;
2107 dptr_num = SVAL(params,0);
2108 maxentries = SVAL(params,2);
2109 info_level = SVAL(params,4);
2110 resume_key = IVAL(params,6);
2111 findnext_flags = SVAL(params,10);
2112 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2113 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2114 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2115 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2117 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2118 params+12,
2119 total_params - 12, STR_TERMINATE, &ntstatus,
2120 &mask_contains_wcard);
2121 if (!NT_STATUS_IS_OK(ntstatus)) {
2122 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2123 complain (it thinks we're asking for the directory above the shared
2124 path or an invalid name). Catch this as the resume name is only compared, never used in
2125 a file access. JRA. */
2126 srvstr_pull_talloc(ctx, params, req->flags2,
2127 &resume_name, params+12,
2128 total_params - 12,
2129 STR_TERMINATE);
2131 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2132 reply_nterror(req, ntstatus);
2133 return;
2137 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2138 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2139 resume_key = %d resume name = %s continue=%d level = %d\n",
2140 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2141 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2143 if (!maxentries) {
2144 /* W2K3 seems to treat zero as 1. */
2145 maxentries = 1;
2148 switch (info_level) {
2149 case SMB_FIND_INFO_STANDARD:
2150 case SMB_FIND_EA_SIZE:
2151 case SMB_FIND_EA_LIST:
2152 case SMB_FIND_FILE_DIRECTORY_INFO:
2153 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2154 case SMB_FIND_FILE_NAMES_INFO:
2155 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2156 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2157 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2158 break;
2159 case SMB_FIND_FILE_UNIX:
2160 case SMB_FIND_FILE_UNIX_INFO2:
2161 if (!lp_unix_extensions()) {
2162 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2163 return;
2165 break;
2166 default:
2167 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2168 return;
2171 if (info_level == SMB_FIND_EA_LIST) {
2172 uint32 ea_size;
2174 if (total_data < 4) {
2175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2176 return;
2179 ea_size = IVAL(pdata,0);
2180 if (ea_size != total_data) {
2181 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2182 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2184 return;
2187 if (!lp_ea_support(SNUM(conn))) {
2188 reply_doserror(req, ERRDOS, ERReasnotsupported);
2189 return;
2192 /* Pull out the list of names. */
2193 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2194 if (!ea_list) {
2195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2196 return;
2200 *ppdata = (char *)SMB_REALLOC(
2201 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2202 if(*ppdata == NULL) {
2203 reply_nterror(req, NT_STATUS_NO_MEMORY);
2204 return;
2207 pdata = *ppdata;
2208 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2210 /* Realloc the params space */
2211 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2212 if(*pparams == NULL ) {
2213 reply_nterror(req, NT_STATUS_NO_MEMORY);
2214 return;
2217 params = *pparams;
2219 /* Check that the dptr is valid */
2220 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2221 reply_doserror(req, ERRDOS, ERRnofiles);
2222 return;
2225 string_set(&conn->dirpath,dptr_path(dptr_num));
2227 /* Get the wildcard mask from the dptr */
2228 if((p = dptr_wcard(dptr_num))== NULL) {
2229 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2230 reply_doserror(req, ERRDOS, ERRnofiles);
2231 return;
2234 mask = p;
2235 directory = conn->dirpath;
2237 /* Get the attr mask from the dptr */
2238 dirtype = dptr_attr(dptr_num);
2240 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2241 dptr_num, mask, dirtype,
2242 (long)conn->dirptr,
2243 dptr_TellDir(conn->dirptr)));
2245 /* We don't need to check for VOL here as this is returned by
2246 a different TRANS2 call. */
2248 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2249 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2250 dont_descend = True;
2252 p = pdata;
2253 space_remaining = max_data_bytes;
2254 out_of_space = False;
2257 * Seek to the correct position. We no longer use the resume key but
2258 * depend on the last file name instead.
2261 if(*resume_name && !continue_bit) {
2262 SMB_STRUCT_STAT st;
2264 long current_pos = 0;
2266 * Remember, name_to_8_3 is called by
2267 * get_lanman2_dir_entry(), so the resume name
2268 * could be mangled. Ensure we check the unmangled name.
2271 if (mangle_is_mangled(resume_name, conn->params)) {
2272 char *new_resume_name = NULL;
2273 mangle_lookup_name_from_8_3(ctx,
2274 resume_name,
2275 &new_resume_name,
2276 conn->params);
2277 if (new_resume_name) {
2278 resume_name = new_resume_name;
2283 * Fix for NT redirector problem triggered by resume key indexes
2284 * changing between directory scans. We now return a resume key of 0
2285 * and instead look for the filename to continue from (also given
2286 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2287 * findfirst/findnext (as is usual) then the directory pointer
2288 * should already be at the correct place.
2291 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2292 } /* end if resume_name && !continue_bit */
2294 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2295 bool got_exact_match = False;
2297 /* this is a heuristic to avoid seeking the dirptr except when
2298 absolutely necessary. It allows for a filename of about 40 chars */
2299 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2300 out_of_space = True;
2301 finished = False;
2302 } else {
2303 TALLOC_CTX *sub_ctx = talloc_stackframe();
2305 finished = !get_lanman2_dir_entry(sub_ctx,
2306 conn,
2307 req->flags2,
2308 mask,dirtype,info_level,
2309 requires_resume_key,dont_descend,
2310 &p,pdata,data_end,
2311 space_remaining, &out_of_space,
2312 &got_exact_match,
2313 &last_entry_off, ea_list);
2315 TALLOC_FREE(sub_ctx);
2318 if (finished && out_of_space)
2319 finished = False;
2321 if (!finished && !out_of_space)
2322 numentries++;
2325 * As an optimisation if we know we aren't looking
2326 * for a wildcard name (ie. the name matches the wildcard exactly)
2327 * then we can finish on any (first) match.
2328 * This speeds up large directory searches. JRA.
2331 if(got_exact_match)
2332 finished = True;
2334 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2337 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2338 smb_fn_name(CVAL(req->inbuf,smb_com)),
2339 mask, directory, dirtype, numentries ) );
2341 /* Check if we can close the dirptr */
2342 if(close_after_request || (finished && close_if_end)) {
2343 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2344 dptr_close(&dptr_num); /* This frees up the saved mask */
2347 /* Set up the return parameter block */
2348 SSVAL(params,0,numentries);
2349 SSVAL(params,2,finished);
2350 SSVAL(params,4,0); /* Never an EA error */
2351 SSVAL(params,6,last_entry_off);
2353 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2354 max_data_bytes);
2356 return;
2359 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2361 E_md4hash(lp_servicename(SNUM(conn)),objid);
2362 return objid;
2365 /****************************************************************************
2366 Reply to a TRANS2_QFSINFO (query filesystem info).
2367 ****************************************************************************/
2369 static void call_trans2qfsinfo(connection_struct *conn,
2370 struct smb_request *req,
2371 char **pparams, int total_params,
2372 char **ppdata, int total_data,
2373 unsigned int max_data_bytes)
2375 char *pdata, *end_data;
2376 char *params = *pparams;
2377 uint16 info_level;
2378 int data_len, len;
2379 SMB_STRUCT_STAT st;
2380 const char *vname = volume_label(SNUM(conn));
2381 int snum = SNUM(conn);
2382 char *fstype = lp_fstype(SNUM(conn));
2383 int quota_flag = 0;
2385 if (total_params < 2) {
2386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2387 return;
2390 info_level = SVAL(params,0);
2392 if (IS_IPC(conn) ||
2393 (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF )) {
2394 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2395 DEBUG(0,("call_trans2qfsinfo: encryption required "
2396 "and info level 0x%x sent.\n",
2397 (unsigned int)info_level));
2398 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2399 return;
2403 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2405 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2406 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2407 reply_doserror(req, ERRSRV, ERRinvdevice);
2408 return;
2411 *ppdata = (char *)SMB_REALLOC(
2412 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2413 if (*ppdata == NULL ) {
2414 reply_nterror(req, NT_STATUS_NO_MEMORY);
2415 return;
2418 pdata = *ppdata;
2419 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2420 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2422 switch (info_level) {
2423 case SMB_INFO_ALLOCATION:
2425 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2426 data_len = 18;
2427 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2428 reply_unixerror(req, ERRHRD, ERRgeneral);
2429 return;
2432 block_size = lp_block_size(snum);
2433 if (bsize < block_size) {
2434 SMB_BIG_UINT factor = block_size/bsize;
2435 bsize = block_size;
2436 dsize /= factor;
2437 dfree /= factor;
2439 if (bsize > block_size) {
2440 SMB_BIG_UINT factor = bsize/block_size;
2441 bsize = block_size;
2442 dsize *= factor;
2443 dfree *= factor;
2445 bytes_per_sector = 512;
2446 sectors_per_unit = bsize/bytes_per_sector;
2448 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2449 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2450 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2452 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2453 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2454 SIVAL(pdata,l1_cUnit,dsize);
2455 SIVAL(pdata,l1_cUnitAvail,dfree);
2456 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2457 break;
2460 case SMB_INFO_VOLUME:
2461 /* Return volume name */
2463 * Add volume serial number - hash of a combination of
2464 * the called hostname and the service name.
2466 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2468 * Win2k3 and previous mess this up by sending a name length
2469 * one byte short. I believe only older clients (OS/2 Win9x) use
2470 * this call so try fixing this by adding a terminating null to
2471 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2473 len = srvstr_push(
2474 pdata, req->flags2,
2475 pdata+l2_vol_szVolLabel, vname,
2476 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2477 STR_NOALIGN|STR_TERMINATE);
2478 SCVAL(pdata,l2_vol_cch,len);
2479 data_len = l2_vol_szVolLabel + len;
2480 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2481 (unsigned)st.st_ctime, len, vname));
2482 break;
2484 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2485 case SMB_FS_ATTRIBUTE_INFORMATION:
2488 #if defined(HAVE_SYS_QUOTAS)
2489 quota_flag = FILE_VOLUME_QUOTAS;
2490 #endif
2492 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2493 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2494 FILE_SUPPORTS_OBJECT_IDS|
2495 FILE_UNICODE_ON_DISK|
2496 quota_flag); /* FS ATTRIBUTES */
2498 SIVAL(pdata,4,255); /* Max filename component length */
2499 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2500 and will think we can't do long filenames */
2501 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2502 PTR_DIFF(end_data, pdata+12),
2503 STR_UNICODE);
2504 SIVAL(pdata,8,len);
2505 data_len = 12 + len;
2506 break;
2508 case SMB_QUERY_FS_LABEL_INFO:
2509 case SMB_FS_LABEL_INFORMATION:
2510 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2511 PTR_DIFF(end_data, pdata+4), 0);
2512 data_len = 4 + len;
2513 SIVAL(pdata,0,len);
2514 break;
2516 case SMB_QUERY_FS_VOLUME_INFO:
2517 case SMB_FS_VOLUME_INFORMATION:
2520 * Add volume serial number - hash of a combination of
2521 * the called hostname and the service name.
2523 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2524 (str_checksum(get_local_machine_name())<<16));
2526 /* Max label len is 32 characters. */
2527 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2528 PTR_DIFF(end_data, pdata+18),
2529 STR_UNICODE);
2530 SIVAL(pdata,12,len);
2531 data_len = 18+len;
2533 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2534 (int)strlen(vname),vname, lp_servicename(snum)));
2535 break;
2537 case SMB_QUERY_FS_SIZE_INFO:
2538 case SMB_FS_SIZE_INFORMATION:
2540 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2541 data_len = 24;
2542 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2543 reply_unixerror(req, ERRHRD, ERRgeneral);
2544 return;
2546 block_size = lp_block_size(snum);
2547 if (bsize < block_size) {
2548 SMB_BIG_UINT factor = block_size/bsize;
2549 bsize = block_size;
2550 dsize /= factor;
2551 dfree /= factor;
2553 if (bsize > block_size) {
2554 SMB_BIG_UINT factor = bsize/block_size;
2555 bsize = block_size;
2556 dsize *= factor;
2557 dfree *= factor;
2559 bytes_per_sector = 512;
2560 sectors_per_unit = bsize/bytes_per_sector;
2561 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2562 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2563 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2564 SBIG_UINT(pdata,0,dsize);
2565 SBIG_UINT(pdata,8,dfree);
2566 SIVAL(pdata,16,sectors_per_unit);
2567 SIVAL(pdata,20,bytes_per_sector);
2568 break;
2571 case SMB_FS_FULL_SIZE_INFORMATION:
2573 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2574 data_len = 32;
2575 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2576 reply_unixerror(req, ERRHRD, ERRgeneral);
2577 return;
2579 block_size = lp_block_size(snum);
2580 if (bsize < block_size) {
2581 SMB_BIG_UINT factor = block_size/bsize;
2582 bsize = block_size;
2583 dsize /= factor;
2584 dfree /= factor;
2586 if (bsize > block_size) {
2587 SMB_BIG_UINT factor = bsize/block_size;
2588 bsize = block_size;
2589 dsize *= factor;
2590 dfree *= factor;
2592 bytes_per_sector = 512;
2593 sectors_per_unit = bsize/bytes_per_sector;
2594 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2595 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2596 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2597 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2598 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2599 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2600 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2601 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2602 break;
2605 case SMB_QUERY_FS_DEVICE_INFO:
2606 case SMB_FS_DEVICE_INFORMATION:
2607 data_len = 8;
2608 SIVAL(pdata,0,0); /* dev type */
2609 SIVAL(pdata,4,0); /* characteristics */
2610 break;
2612 #ifdef HAVE_SYS_QUOTAS
2613 case SMB_FS_QUOTA_INFORMATION:
2615 * what we have to send --metze:
2617 * Unknown1: 24 NULL bytes
2618 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2619 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2620 * Quota Flags: 2 byte :
2621 * Unknown3: 6 NULL bytes
2623 * 48 bytes total
2625 * details for Quota Flags:
2627 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2628 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2629 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2630 * 0x0001 Enable Quotas: enable quota for this fs
2634 /* we need to fake up a fsp here,
2635 * because its not send in this call
2637 files_struct fsp;
2638 SMB_NTQUOTA_STRUCT quotas;
2640 ZERO_STRUCT(fsp);
2641 ZERO_STRUCT(quotas);
2643 fsp.conn = conn;
2644 fsp.fnum = -1;
2646 /* access check */
2647 if (current_user.ut.uid != 0) {
2648 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2649 lp_servicename(SNUM(conn)),conn->user));
2650 reply_doserror(req, ERRDOS, ERRnoaccess);
2651 return;
2654 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2655 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2656 reply_doserror(req, ERRSRV, ERRerror);
2657 return;
2660 data_len = 48;
2662 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2664 /* Unknown1 24 NULL bytes*/
2665 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2666 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2667 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2669 /* Default Soft Quota 8 bytes */
2670 SBIG_UINT(pdata,24,quotas.softlim);
2672 /* Default Hard Quota 8 bytes */
2673 SBIG_UINT(pdata,32,quotas.hardlim);
2675 /* Quota flag 2 bytes */
2676 SSVAL(pdata,40,quotas.qflags);
2678 /* Unknown3 6 NULL bytes */
2679 SSVAL(pdata,42,0);
2680 SIVAL(pdata,44,0);
2682 break;
2684 #endif /* HAVE_SYS_QUOTAS */
2685 case SMB_FS_OBJECTID_INFORMATION:
2687 unsigned char objid[16];
2688 memcpy(pdata,create_volume_objectid(conn, objid),16);
2689 data_len = 64;
2690 break;
2694 * Query the version and capabilities of the CIFS UNIX extensions
2695 * in use.
2698 case SMB_QUERY_CIFS_UNIX_INFO:
2700 bool large_write = lp_min_receive_file_size() &&
2701 !srv_is_signing_active();
2702 bool large_read = !srv_is_signing_active();
2703 int encrypt_caps = 0;
2705 if (!lp_unix_extensions()) {
2706 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2707 return;
2710 switch (conn->encrypt_level) {
2711 case 0:
2712 encrypt_caps = 0;
2713 break;
2714 case 1:
2715 case Auto:
2716 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2717 break;
2718 case Required:
2719 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2720 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2721 large_write = false;
2722 large_read = false;
2723 break;
2726 data_len = 12;
2727 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2728 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2730 /* We have POSIX ACLs, pathname, encryption,
2731 * large read/write, and locking capability. */
2733 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2734 CIFS_UNIX_POSIX_ACLS_CAP|
2735 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2736 CIFS_UNIX_FCNTL_LOCKS_CAP|
2737 CIFS_UNIX_EXTATTR_CAP|
2738 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2739 encrypt_caps|
2740 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2741 (large_write ?
2742 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2743 break;
2746 case SMB_QUERY_POSIX_FS_INFO:
2748 int rc;
2749 vfs_statvfs_struct svfs;
2751 if (!lp_unix_extensions()) {
2752 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2753 return;
2756 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2758 if (!rc) {
2759 data_len = 56;
2760 SIVAL(pdata,0,svfs.OptimalTransferSize);
2761 SIVAL(pdata,4,svfs.BlockSize);
2762 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2763 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2764 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2765 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2766 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2767 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2768 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2769 #ifdef EOPNOTSUPP
2770 } else if (rc == EOPNOTSUPP) {
2771 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2772 return;
2773 #endif /* EOPNOTSUPP */
2774 } else {
2775 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2776 reply_doserror(req, ERRSRV, ERRerror);
2777 return;
2779 break;
2782 case SMB_QUERY_POSIX_WHOAMI:
2784 uint32_t flags = 0;
2785 uint32_t sid_bytes;
2786 int i;
2788 if (!lp_unix_extensions()) {
2789 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2790 return;
2793 if (max_data_bytes < 40) {
2794 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2795 return;
2798 /* We ARE guest if global_sid_Builtin_Guests is
2799 * in our list of SIDs.
2801 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2802 current_user.nt_user_token)) {
2803 flags |= SMB_WHOAMI_GUEST;
2806 /* We are NOT guest if global_sid_Authenticated_Users
2807 * is in our list of SIDs.
2809 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2810 current_user.nt_user_token)) {
2811 flags &= ~SMB_WHOAMI_GUEST;
2814 /* NOTE: 8 bytes for UID/GID, irrespective of native
2815 * platform size. This matches
2816 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2818 data_len = 4 /* flags */
2819 + 4 /* flag mask */
2820 + 8 /* uid */
2821 + 8 /* gid */
2822 + 4 /* ngroups */
2823 + 4 /* num_sids */
2824 + 4 /* SID bytes */
2825 + 4 /* pad/reserved */
2826 + (current_user.ut.ngroups * 8)
2827 /* groups list */
2828 + (current_user.nt_user_token->num_sids *
2829 SID_MAX_SIZE)
2830 /* SID list */;
2832 SIVAL(pdata, 0, flags);
2833 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2834 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2835 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2838 if (data_len >= max_data_bytes) {
2839 /* Potential overflow, skip the GIDs and SIDs. */
2841 SIVAL(pdata, 24, 0); /* num_groups */
2842 SIVAL(pdata, 28, 0); /* num_sids */
2843 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2844 SIVAL(pdata, 36, 0); /* reserved */
2846 data_len = 40;
2847 break;
2850 SIVAL(pdata, 24, current_user.ut.ngroups);
2851 SIVAL(pdata, 28,
2852 current_user.nt_user_token->num_sids);
2854 /* We walk the SID list twice, but this call is fairly
2855 * infrequent, and I don't expect that it's performance
2856 * sensitive -- jpeach
2858 for (i = 0, sid_bytes = 0;
2859 i < current_user.nt_user_token->num_sids; ++i) {
2860 sid_bytes += ndr_size_dom_sid(
2861 &current_user.nt_user_token->user_sids[i], 0);
2864 /* SID list byte count */
2865 SIVAL(pdata, 32, sid_bytes);
2867 /* 4 bytes pad/reserved - must be zero */
2868 SIVAL(pdata, 36, 0);
2869 data_len = 40;
2871 /* GID list */
2872 for (i = 0; i < current_user.ut.ngroups; ++i) {
2873 SBIG_UINT(pdata, data_len,
2874 (SMB_BIG_UINT)current_user.ut.groups[i]);
2875 data_len += 8;
2878 /* SID list */
2879 for (i = 0;
2880 i < current_user.nt_user_token->num_sids; ++i) {
2881 int sid_len = ndr_size_dom_sid(
2882 &current_user.nt_user_token->user_sids[i], 0);
2884 sid_linearize(pdata + data_len, sid_len,
2885 &current_user.nt_user_token->user_sids[i]);
2886 data_len += sid_len;
2889 break;
2892 case SMB_MAC_QUERY_FS_INFO:
2894 * Thursby MAC extension... ONLY on NTFS filesystems
2895 * once we do streams then we don't need this
2897 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2898 data_len = 88;
2899 SIVAL(pdata,84,0x100); /* Don't support mac... */
2900 break;
2902 /* drop through */
2903 default:
2904 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2905 return;
2909 send_trans2_replies(req, params, 0, pdata, data_len,
2910 max_data_bytes);
2912 DEBUG( 4, ( "%s info_level = %d\n",
2913 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2915 return;
2918 /****************************************************************************
2919 Reply to a TRANS2_SETFSINFO (set filesystem info).
2920 ****************************************************************************/
2922 static void call_trans2setfsinfo(connection_struct *conn,
2923 struct smb_request *req,
2924 char **pparams, int total_params,
2925 char **ppdata, int total_data,
2926 unsigned int max_data_bytes)
2928 char *pdata = *ppdata;
2929 char *params = *pparams;
2930 uint16 info_level;
2932 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2934 /* */
2935 if (total_params < 4) {
2936 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2937 total_params));
2938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2939 return;
2942 info_level = SVAL(params,2);
2944 if (IS_IPC(conn)) {
2945 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
2946 info_level != SMB_SET_CIFS_UNIX_INFO) {
2947 DEBUG(0,("call_trans2setfsinfo: not an allowed "
2948 "info level (0x%x) on IPC$.\n",
2949 (unsigned int)info_level));
2950 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2951 return;
2955 if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
2956 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
2957 DEBUG(0,("call_trans2setfsinfo: encryption required "
2958 "and info level 0x%x sent.\n",
2959 (unsigned int)info_level));
2960 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2961 return;
2965 switch(info_level) {
2966 case SMB_SET_CIFS_UNIX_INFO:
2968 uint16 client_unix_major;
2969 uint16 client_unix_minor;
2970 uint32 client_unix_cap_low;
2971 uint32 client_unix_cap_high;
2973 if (!lp_unix_extensions()) {
2974 reply_nterror(req,
2975 NT_STATUS_INVALID_LEVEL);
2976 return;
2979 /* There should be 12 bytes of capabilities set. */
2980 if (total_data < 8) {
2981 reply_nterror(
2982 req,
2983 NT_STATUS_INVALID_PARAMETER);
2984 return;
2986 client_unix_major = SVAL(pdata,0);
2987 client_unix_minor = SVAL(pdata,2);
2988 client_unix_cap_low = IVAL(pdata,4);
2989 client_unix_cap_high = IVAL(pdata,8);
2990 /* Just print these values for now. */
2991 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2992 cap_low = 0x%x, cap_high = 0x%x\n",
2993 (unsigned int)client_unix_major,
2994 (unsigned int)client_unix_minor,
2995 (unsigned int)client_unix_cap_low,
2996 (unsigned int)client_unix_cap_high ));
2998 /* Here is where we must switch to posix pathname processing... */
2999 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3000 lp_set_posix_pathnames();
3001 mangle_change_to_posix();
3004 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3005 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3006 /* Client that knows how to do posix locks,
3007 * but not posix open/mkdir operations. Set a
3008 * default type for read/write checks. */
3010 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3013 break;
3016 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3018 NTSTATUS status;
3019 size_t param_len = 0;
3020 size_t data_len = total_data;
3022 if (!lp_unix_extensions()) {
3023 reply_nterror(
3024 req,
3025 NT_STATUS_INVALID_LEVEL);
3026 return;
3029 if (lp_smb_encrypt(SNUM(conn)) == false) {
3030 reply_nterror(
3031 req,
3032 NT_STATUS_NOT_SUPPORTED);
3033 return;
3036 DEBUG( 4,("call_trans2setfsinfo: "
3037 "request transport encrption.\n"));
3039 status = srv_request_encryption_setup(conn,
3040 (unsigned char **)ppdata,
3041 &data_len,
3042 (unsigned char **)pparams,
3043 &param_len);
3045 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3046 !NT_STATUS_IS_OK(status)) {
3047 reply_nterror(req, status);
3048 return;
3051 send_trans2_replies(req,
3052 *pparams,
3053 param_len,
3054 *ppdata,
3055 data_len,
3056 max_data_bytes);
3058 if (NT_STATUS_IS_OK(status)) {
3059 /* Server-side transport
3060 * encryption is now *on*. */
3061 status = srv_encryption_start(conn);
3062 if (!NT_STATUS_IS_OK(status)) {
3063 exit_server_cleanly(
3064 "Failure in setting "
3065 "up encrypted transport");
3068 return;
3071 case SMB_FS_QUOTA_INFORMATION:
3073 files_struct *fsp = NULL;
3074 SMB_NTQUOTA_STRUCT quotas;
3076 ZERO_STRUCT(quotas);
3078 /* access check */
3079 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3080 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3081 lp_servicename(SNUM(conn)),conn->user));
3082 reply_doserror(req, ERRSRV, ERRaccess);
3083 return;
3086 /* note: normaly there're 48 bytes,
3087 * but we didn't use the last 6 bytes for now
3088 * --metze
3090 fsp = file_fsp(SVAL(params,0));
3091 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3092 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3093 reply_nterror(
3094 req, NT_STATUS_INVALID_HANDLE);
3095 return;
3098 if (total_data < 42) {
3099 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3100 total_data));
3101 reply_nterror(
3102 req,
3103 NT_STATUS_INVALID_PARAMETER);
3104 return;
3107 /* unknown_1 24 NULL bytes in pdata*/
3109 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3110 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3111 #ifdef LARGE_SMB_OFF_T
3112 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3113 #else /* LARGE_SMB_OFF_T */
3114 if ((IVAL(pdata,28) != 0)&&
3115 ((quotas.softlim != 0xFFFFFFFF)||
3116 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3117 /* more than 32 bits? */
3118 reply_nterror(
3119 req,
3120 NT_STATUS_INVALID_PARAMETER);
3121 return;
3123 #endif /* LARGE_SMB_OFF_T */
3125 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3126 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3127 #ifdef LARGE_SMB_OFF_T
3128 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3129 #else /* LARGE_SMB_OFF_T */
3130 if ((IVAL(pdata,36) != 0)&&
3131 ((quotas.hardlim != 0xFFFFFFFF)||
3132 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3133 /* more than 32 bits? */
3134 reply_nterror(
3135 req,
3136 NT_STATUS_INVALID_PARAMETER);
3137 return;
3139 #endif /* LARGE_SMB_OFF_T */
3141 /* quota_flags 2 bytes **/
3142 quotas.qflags = SVAL(pdata,40);
3144 /* unknown_2 6 NULL bytes follow*/
3146 /* now set the quotas */
3147 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3148 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3149 reply_doserror(req, ERRSRV, ERRerror);
3150 return;
3153 break;
3155 default:
3156 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3157 info_level));
3158 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3159 return;
3160 break;
3164 * sending this reply works fine,
3165 * but I'm not sure it's the same
3166 * like windows do...
3167 * --metze
3169 reply_outbuf(req, 10, 0);
3172 #if defined(HAVE_POSIX_ACLS)
3173 /****************************************************************************
3174 Utility function to count the number of entries in a POSIX acl.
3175 ****************************************************************************/
3177 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3179 unsigned int ace_count = 0;
3180 int entry_id = SMB_ACL_FIRST_ENTRY;
3181 SMB_ACL_ENTRY_T entry;
3183 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3184 /* get_next... */
3185 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3186 entry_id = SMB_ACL_NEXT_ENTRY;
3188 ace_count++;
3190 return ace_count;
3193 /****************************************************************************
3194 Utility function to marshall a POSIX acl into wire format.
3195 ****************************************************************************/
3197 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3199 int entry_id = SMB_ACL_FIRST_ENTRY;
3200 SMB_ACL_ENTRY_T entry;
3202 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3203 SMB_ACL_TAG_T tagtype;
3204 SMB_ACL_PERMSET_T permset;
3205 unsigned char perms = 0;
3206 unsigned int own_grp;
3208 /* get_next... */
3209 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3210 entry_id = SMB_ACL_NEXT_ENTRY;
3213 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3214 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3215 return False;
3218 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3219 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3220 return False;
3223 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3224 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3225 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3227 SCVAL(pdata,1,perms);
3229 switch (tagtype) {
3230 case SMB_ACL_USER_OBJ:
3231 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3232 own_grp = (unsigned int)pst->st_uid;
3233 SIVAL(pdata,2,own_grp);
3234 SIVAL(pdata,6,0);
3235 break;
3236 case SMB_ACL_USER:
3238 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3239 if (!puid) {
3240 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3241 return False;
3243 own_grp = (unsigned int)*puid;
3244 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3245 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3246 SIVAL(pdata,2,own_grp);
3247 SIVAL(pdata,6,0);
3248 break;
3250 case SMB_ACL_GROUP_OBJ:
3251 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3252 own_grp = (unsigned int)pst->st_gid;
3253 SIVAL(pdata,2,own_grp);
3254 SIVAL(pdata,6,0);
3255 break;
3256 case SMB_ACL_GROUP:
3258 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3259 if (!pgid) {
3260 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3261 return False;
3263 own_grp = (unsigned int)*pgid;
3264 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3265 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3266 SIVAL(pdata,2,own_grp);
3267 SIVAL(pdata,6,0);
3268 break;
3270 case SMB_ACL_MASK:
3271 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3272 SIVAL(pdata,2,0xFFFFFFFF);
3273 SIVAL(pdata,6,0xFFFFFFFF);
3274 break;
3275 case SMB_ACL_OTHER:
3276 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3277 SIVAL(pdata,2,0xFFFFFFFF);
3278 SIVAL(pdata,6,0xFFFFFFFF);
3279 break;
3280 default:
3281 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3282 return False;
3284 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3287 return True;
3289 #endif
3291 /****************************************************************************
3292 Store the FILE_UNIX_BASIC info.
3293 ****************************************************************************/
3295 static char *store_file_unix_basic(connection_struct *conn,
3296 char *pdata,
3297 files_struct *fsp,
3298 const SMB_STRUCT_STAT *psbuf)
3300 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3301 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3303 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3304 pdata += 8;
3306 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3307 pdata += 8;
3309 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3310 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3311 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3312 pdata += 24;
3314 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3315 SIVAL(pdata,4,0);
3316 pdata += 8;
3318 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3319 SIVAL(pdata,4,0);
3320 pdata += 8;
3322 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3323 pdata += 4;
3325 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3326 SIVAL(pdata,4,0);
3327 pdata += 8;
3329 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3330 SIVAL(pdata,4,0);
3331 pdata += 8;
3333 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3334 pdata += 8;
3336 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3337 SIVAL(pdata,4,0);
3338 pdata += 8;
3340 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3341 SIVAL(pdata,4,0);
3342 pdata += 8;
3344 return pdata;
3347 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3348 * the chflags(2) (or equivalent) flags.
3350 * XXX: this really should be behind the VFS interface. To do this, we would
3351 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3352 * Each VFS module could then implement its own mapping as appropriate for the
3353 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3355 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3356 info2_flags_map[] =
3358 #ifdef UF_NODUMP
3359 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3360 #endif
3362 #ifdef UF_IMMUTABLE
3363 { UF_IMMUTABLE, EXT_IMMUTABLE },
3364 #endif
3366 #ifdef UF_APPEND
3367 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3368 #endif
3370 #ifdef UF_HIDDEN
3371 { UF_HIDDEN, EXT_HIDDEN },
3372 #endif
3374 /* Do not remove. We need to guarantee that this array has at least one
3375 * entry to build on HP-UX.
3377 { 0, 0 }
3381 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3382 uint32 *smb_fflags, uint32 *smb_fmask)
3384 #ifdef HAVE_STAT_ST_FLAGS
3385 int i;
3387 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3388 *smb_fmask |= info2_flags_map[i].smb_fflag;
3389 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3390 *smb_fflags |= info2_flags_map[i].smb_fflag;
3393 #endif /* HAVE_STAT_ST_FLAGS */
3396 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3397 const uint32 smb_fflags,
3398 const uint32 smb_fmask,
3399 int *stat_fflags)
3401 #ifdef HAVE_STAT_ST_FLAGS
3402 uint32 max_fmask = 0;
3403 int i;
3405 *stat_fflags = psbuf->st_flags;
3407 /* For each flags requested in smb_fmask, check the state of the
3408 * corresponding flag in smb_fflags and set or clear the matching
3409 * stat flag.
3412 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3413 max_fmask |= info2_flags_map[i].smb_fflag;
3414 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3415 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3416 *stat_fflags |= info2_flags_map[i].stat_fflag;
3417 } else {
3418 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3423 /* If smb_fmask is asking to set any bits that are not supported by
3424 * our flag mappings, we should fail.
3426 if ((smb_fmask & max_fmask) != smb_fmask) {
3427 return False;
3430 return True;
3431 #else
3432 return False;
3433 #endif /* HAVE_STAT_ST_FLAGS */
3437 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3438 * of file flags and birth (create) time.
3440 static char *store_file_unix_basic_info2(connection_struct *conn,
3441 char *pdata,
3442 files_struct *fsp,
3443 const SMB_STRUCT_STAT *psbuf)
3445 uint32 file_flags = 0;
3446 uint32 flags_mask = 0;
3448 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3450 /* Create (birth) time 64 bit */
3451 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3452 pdata += 8;
3454 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3455 SIVAL(pdata, 0, file_flags); /* flags */
3456 SIVAL(pdata, 4, flags_mask); /* mask */
3457 pdata += 8;
3459 return pdata;
3462 /****************************************************************************
3463 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3464 ****************************************************************************/
3466 static void call_trans2qpipeinfo(connection_struct *conn,
3467 struct smb_request *req,
3468 unsigned int tran_call,
3469 char **pparams, int total_params,
3470 char **ppdata, int total_data,
3471 unsigned int max_data_bytes)
3473 char *params = *pparams;
3474 char *pdata = *ppdata;
3475 unsigned int data_size = 0;
3476 unsigned int param_size = 2;
3477 uint16 info_level;
3478 smb_np_struct *p_pipe = NULL;
3480 if (!params) {
3481 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3482 return;
3485 if (total_params < 4) {
3486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3487 return;
3490 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3491 if (p_pipe == NULL) {
3492 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3493 return;
3496 info_level = SVAL(params,2);
3498 *pparams = (char *)SMB_REALLOC(*pparams,2);
3499 if (*pparams == NULL) {
3500 reply_nterror(req, NT_STATUS_NO_MEMORY);
3501 return;
3503 params = *pparams;
3504 SSVAL(params,0,0);
3505 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3506 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3507 if (*ppdata == NULL ) {
3508 reply_nterror(req, NT_STATUS_NO_MEMORY);
3509 return;
3511 pdata = *ppdata;
3513 switch (info_level) {
3514 case SMB_FILE_STANDARD_INFORMATION:
3515 memset(pdata,0,24);
3516 SOFF_T(pdata,0,4096LL);
3517 SIVAL(pdata,16,1);
3518 SIVAL(pdata,20,1);
3519 data_size = 24;
3520 break;
3522 default:
3523 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3524 return;
3527 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3528 max_data_bytes);
3530 return;
3533 /****************************************************************************
3534 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3535 file name or file id).
3536 ****************************************************************************/
3538 static void call_trans2qfilepathinfo(connection_struct *conn,
3539 struct smb_request *req,
3540 unsigned int tran_call,
3541 char **pparams, int total_params,
3542 char **ppdata, int total_data,
3543 unsigned int max_data_bytes)
3545 char *params = *pparams;
3546 char *pdata = *ppdata;
3547 char *dstart, *dend;
3548 uint16 info_level;
3549 int mode=0;
3550 int nlink;
3551 SMB_OFF_T file_size=0;
3552 SMB_BIG_UINT allocation_size=0;
3553 unsigned int data_size = 0;
3554 unsigned int param_size = 2;
3555 SMB_STRUCT_STAT sbuf;
3556 char *dos_fname = NULL;
3557 char *fname = NULL;
3558 char *fullpathname;
3559 char *base_name;
3560 char *p;
3561 SMB_OFF_T pos = 0;
3562 bool delete_pending = False;
3563 int len;
3564 time_t create_time, mtime, atime;
3565 struct timespec create_time_ts, mtime_ts, atime_ts;
3566 files_struct *fsp = NULL;
3567 struct file_id fileid;
3568 struct ea_list *ea_list = NULL;
3569 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3570 char *lock_data = NULL;
3571 TALLOC_CTX *ctx = talloc_tos();
3573 if (!params) {
3574 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3575 return;
3578 ZERO_STRUCT(sbuf);
3580 if (tran_call == TRANSACT2_QFILEINFO) {
3581 if (total_params < 4) {
3582 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3583 return;
3586 if (IS_IPC(conn)) {
3587 call_trans2qpipeinfo(conn, req, tran_call,
3588 pparams, total_params,
3589 ppdata, total_data,
3590 max_data_bytes);
3591 return;
3594 fsp = file_fsp(SVAL(params,0));
3595 info_level = SVAL(params,2);
3597 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3599 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3600 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3601 return;
3604 /* Initial check for valid fsp ptr. */
3605 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3606 return;
3609 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3610 if (!fname) {
3611 reply_nterror(req, NT_STATUS_NO_MEMORY);
3612 return;
3615 if(fsp->fake_file_handle) {
3617 * This is actually for the QUOTA_FAKE_FILE --metze
3620 /* We know this name is ok, it's already passed the checks. */
3622 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3624 * This is actually a QFILEINFO on a directory
3625 * handle (returned from an NT SMB). NT5.0 seems
3626 * to do this call. JRA.
3629 if (INFO_LEVEL_IS_UNIX(info_level)) {
3630 /* Always do lstat for UNIX calls. */
3631 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3632 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3633 reply_unixerror(req,ERRDOS,ERRbadpath);
3634 return;
3636 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3637 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3638 reply_unixerror(req, ERRDOS, ERRbadpath);
3639 return;
3642 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3643 delete_pending = get_delete_on_close_flag(fileid);
3644 } else {
3646 * Original code - this is an open file.
3648 if (!check_fsp(conn, req, fsp, &current_user)) {
3649 return;
3652 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3653 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3654 reply_unixerror(req, ERRDOS, ERRbadfid);
3655 return;
3657 pos = fsp->fh->position_information;
3658 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3659 delete_pending = get_delete_on_close_flag(fileid);
3660 access_mask = fsp->access_mask;
3663 } else {
3664 NTSTATUS status = NT_STATUS_OK;
3666 /* qpathinfo */
3667 if (total_params < 7) {
3668 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3669 return;
3672 info_level = SVAL(params,0);
3674 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3676 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3677 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3678 return;
3681 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3682 total_params - 6,
3683 STR_TERMINATE, &status);
3684 if (!NT_STATUS_IS_OK(status)) {
3685 reply_nterror(req, status);
3686 return;
3689 status = resolve_dfspath(ctx,
3690 conn,
3691 req->flags2 & FLAGS2_DFS_PATHNAMES,
3692 fname,
3693 &fname);
3694 if (!NT_STATUS_IS_OK(status)) {
3695 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3696 reply_botherror(req,
3697 NT_STATUS_PATH_NOT_COVERED,
3698 ERRSRV, ERRbadpath);
3700 reply_nterror(req, status);
3701 return;
3704 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3705 if (!NT_STATUS_IS_OK(status)) {
3706 reply_nterror(req, status);
3707 return;
3709 status = check_name(conn, fname);
3710 if (!NT_STATUS_IS_OK(status)) {
3711 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3712 reply_nterror(req, status);
3713 return;
3716 if (INFO_LEVEL_IS_UNIX(info_level)) {
3717 /* Always do lstat for UNIX calls. */
3718 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3719 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3720 reply_unixerror(req, ERRDOS, ERRbadpath);
3721 return;
3723 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3724 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3725 reply_unixerror(req, ERRDOS, ERRbadpath);
3726 return;
3729 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3730 delete_pending = get_delete_on_close_flag(fileid);
3731 if (delete_pending) {
3732 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3733 return;
3737 nlink = sbuf.st_nlink;
3739 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3740 /* NTFS does not seem to count ".." */
3741 nlink -= 1;
3744 if ((nlink > 0) && delete_pending) {
3745 nlink -= 1;
3748 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3749 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3750 return;
3753 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3754 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3756 p = strrchr_m(fname,'/');
3757 if (!p)
3758 base_name = fname;
3759 else
3760 base_name = p+1;
3762 mode = dos_mode(conn,fname,&sbuf);
3763 if (!mode)
3764 mode = FILE_ATTRIBUTE_NORMAL;
3766 fullpathname = fname;
3767 if (!(mode & aDIR))
3768 file_size = get_file_size(sbuf);
3770 /* Pull out any data sent here before we realloc. */
3771 switch (info_level) {
3772 case SMB_INFO_QUERY_EAS_FROM_LIST:
3774 /* Pull any EA list from the data portion. */
3775 uint32 ea_size;
3777 if (total_data < 4) {
3778 reply_nterror(
3779 req, NT_STATUS_INVALID_PARAMETER);
3780 return;
3782 ea_size = IVAL(pdata,0);
3784 if (total_data > 0 && ea_size != total_data) {
3785 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3786 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3787 reply_nterror(
3788 req, NT_STATUS_INVALID_PARAMETER);
3789 return;
3792 if (!lp_ea_support(SNUM(conn))) {
3793 reply_doserror(req, ERRDOS,
3794 ERReasnotsupported);
3795 return;
3798 /* Pull out the list of names. */
3799 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3800 if (!ea_list) {
3801 reply_nterror(
3802 req, NT_STATUS_INVALID_PARAMETER);
3803 return;
3805 break;
3808 case SMB_QUERY_POSIX_LOCK:
3810 if (fsp == NULL || fsp->fh->fd == -1) {
3811 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3812 return;
3815 if (total_data != POSIX_LOCK_DATA_SIZE) {
3816 reply_nterror(
3817 req, NT_STATUS_INVALID_PARAMETER);
3818 return;
3821 /* Copy the lock range data. */
3822 lock_data = (char *)TALLOC_MEMDUP(
3823 ctx, pdata, total_data);
3824 if (!lock_data) {
3825 reply_nterror(req, NT_STATUS_NO_MEMORY);
3826 return;
3829 default:
3830 break;
3833 *pparams = (char *)SMB_REALLOC(*pparams,2);
3834 if (*pparams == NULL) {
3835 reply_nterror(req, NT_STATUS_NO_MEMORY);
3836 return;
3838 params = *pparams;
3839 SSVAL(params,0,0);
3840 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3841 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3842 if (*ppdata == NULL ) {
3843 reply_nterror(req, NT_STATUS_NO_MEMORY);
3844 return;
3846 pdata = *ppdata;
3847 dstart = pdata;
3848 dend = dstart + data_size - 1;
3850 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3851 mtime_ts = get_mtimespec(&sbuf);
3852 atime_ts = get_atimespec(&sbuf);
3854 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3856 if (fsp) {
3857 if (!null_timespec(fsp->pending_modtime)) {
3858 /* the pending modtime overrides the current modtime */
3859 mtime_ts = fsp->pending_modtime;
3861 } else {
3862 files_struct *fsp1;
3863 /* Do we have this path open ? */
3864 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3865 fsp1 = file_find_di_first(fileid);
3866 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3867 /* the pending modtime overrides the current modtime */
3868 mtime_ts = fsp1->pending_modtime;
3870 if (fsp1 && fsp1->initial_allocation_size) {
3871 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3875 if (lp_dos_filetime_resolution(SNUM(conn))) {
3876 dos_filetime_timespec(&create_time_ts);
3877 dos_filetime_timespec(&mtime_ts);
3878 dos_filetime_timespec(&atime_ts);
3881 create_time = convert_timespec_to_time_t(create_time_ts);
3882 mtime = convert_timespec_to_time_t(mtime_ts);
3883 atime = convert_timespec_to_time_t(atime_ts);
3885 /* NT expects the name to be in an exact form of the *full*
3886 filename. See the trans2 torture test */
3887 if (ISDOT(base_name)) {
3888 dos_fname = talloc_strdup(ctx, "\\");
3889 if (!dos_fname) {
3890 reply_nterror(req, NT_STATUS_NO_MEMORY);
3891 return;
3893 } else {
3894 dos_fname = talloc_asprintf(ctx,
3895 "\\%s",
3896 fname);
3897 if (!dos_fname) {
3898 reply_nterror(req, NT_STATUS_NO_MEMORY);
3899 return;
3901 string_replace(dos_fname, '/', '\\');
3904 switch (info_level) {
3905 case SMB_INFO_STANDARD:
3906 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3907 data_size = 22;
3908 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3909 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3910 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3911 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3912 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3913 SSVAL(pdata,l1_attrFile,mode);
3914 break;
3916 case SMB_INFO_QUERY_EA_SIZE:
3918 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3919 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3920 data_size = 26;
3921 srv_put_dos_date2(pdata,0,create_time);
3922 srv_put_dos_date2(pdata,4,atime);
3923 srv_put_dos_date2(pdata,8,mtime); /* write time */
3924 SIVAL(pdata,12,(uint32)file_size);
3925 SIVAL(pdata,16,(uint32)allocation_size);
3926 SSVAL(pdata,20,mode);
3927 SIVAL(pdata,22,ea_size);
3928 break;
3931 case SMB_INFO_IS_NAME_VALID:
3932 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3933 if (tran_call == TRANSACT2_QFILEINFO) {
3934 /* os/2 needs this ? really ?*/
3935 reply_doserror(req, ERRDOS, ERRbadfunc);
3936 return;
3938 data_size = 0;
3939 param_size = 0;
3940 break;
3942 case SMB_INFO_QUERY_EAS_FROM_LIST:
3944 size_t total_ea_len = 0;
3945 struct ea_list *ea_file_list = NULL;
3947 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3949 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3950 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3952 if (!ea_list || (total_ea_len > data_size)) {
3953 data_size = 4;
3954 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3955 break;
3958 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3959 break;
3962 case SMB_INFO_QUERY_ALL_EAS:
3964 /* We have data_size bytes to put EA's into. */
3965 size_t total_ea_len = 0;
3967 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3969 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3970 if (!ea_list || (total_ea_len > data_size)) {
3971 data_size = 4;
3972 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3973 break;
3976 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3977 break;
3980 case SMB_FILE_BASIC_INFORMATION:
3981 case SMB_QUERY_FILE_BASIC_INFO:
3983 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3984 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3985 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3986 } else {
3987 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3988 data_size = 40;
3989 SIVAL(pdata,36,0);
3991 put_long_date_timespec(pdata,create_time_ts);
3992 put_long_date_timespec(pdata+8,atime_ts);
3993 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3994 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3995 SIVAL(pdata,32,mode);
3997 DEBUG(5,("SMB_QFBI - "));
3998 DEBUG(5,("create: %s ", ctime(&create_time)));
3999 DEBUG(5,("access: %s ", ctime(&atime)));
4000 DEBUG(5,("write: %s ", ctime(&mtime)));
4001 DEBUG(5,("change: %s ", ctime(&mtime)));
4002 DEBUG(5,("mode: %x\n", mode));
4003 break;
4005 case SMB_FILE_STANDARD_INFORMATION:
4006 case SMB_QUERY_FILE_STANDARD_INFO:
4008 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4009 data_size = 24;
4010 SOFF_T(pdata,0,allocation_size);
4011 SOFF_T(pdata,8,file_size);
4012 SIVAL(pdata,16,nlink);
4013 SCVAL(pdata,20,delete_pending?1:0);
4014 SCVAL(pdata,21,(mode&aDIR)?1:0);
4015 SSVAL(pdata,22,0); /* Padding. */
4016 break;
4018 case SMB_FILE_EA_INFORMATION:
4019 case SMB_QUERY_FILE_EA_INFO:
4021 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4022 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4023 data_size = 4;
4024 SIVAL(pdata,0,ea_size);
4025 break;
4028 /* Get the 8.3 name - used if NT SMB was negotiated. */
4029 case SMB_QUERY_FILE_ALT_NAME_INFO:
4030 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4032 char mangled_name[13];
4033 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4034 if (!name_to_8_3(base_name,mangled_name,
4035 True,conn->params)) {
4036 reply_nterror(
4037 req,
4038 NT_STATUS_NO_MEMORY);
4040 len = srvstr_push(dstart, req->flags2,
4041 pdata+4, mangled_name,
4042 PTR_DIFF(dend, pdata+4),
4043 STR_UNICODE);
4044 data_size = 4 + len;
4045 SIVAL(pdata,0,len);
4046 break;
4049 case SMB_QUERY_FILE_NAME_INFO:
4051 this must be *exactly* right for ACLs on mapped drives to work
4053 len = srvstr_push(dstart, req->flags2,
4054 pdata+4, dos_fname,
4055 PTR_DIFF(dend, pdata+4),
4056 STR_UNICODE);
4057 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4058 data_size = 4 + len;
4059 SIVAL(pdata,0,len);
4060 break;
4062 case SMB_FILE_ALLOCATION_INFORMATION:
4063 case SMB_QUERY_FILE_ALLOCATION_INFO:
4064 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4065 data_size = 8;
4066 SOFF_T(pdata,0,allocation_size);
4067 break;
4069 case SMB_FILE_END_OF_FILE_INFORMATION:
4070 case SMB_QUERY_FILE_END_OF_FILEINFO:
4071 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4072 data_size = 8;
4073 SOFF_T(pdata,0,file_size);
4074 break;
4076 case SMB_QUERY_FILE_ALL_INFO:
4077 case SMB_FILE_ALL_INFORMATION:
4079 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4080 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4081 put_long_date_timespec(pdata,create_time_ts);
4082 put_long_date_timespec(pdata+8,atime_ts);
4083 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4084 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4085 SIVAL(pdata,32,mode);
4086 SIVAL(pdata,36,0); /* padding. */
4087 pdata += 40;
4088 SOFF_T(pdata,0,allocation_size);
4089 SOFF_T(pdata,8,file_size);
4090 SIVAL(pdata,16,nlink);
4091 SCVAL(pdata,20,delete_pending);
4092 SCVAL(pdata,21,(mode&aDIR)?1:0);
4093 SSVAL(pdata,22,0);
4094 pdata += 24;
4095 SIVAL(pdata,0,ea_size);
4096 pdata += 4; /* EA info */
4097 len = srvstr_push(dstart, req->flags2,
4098 pdata+4, dos_fname,
4099 PTR_DIFF(dend, pdata+4),
4100 STR_UNICODE);
4101 SIVAL(pdata,0,len);
4102 pdata += 4 + len;
4103 data_size = PTR_DIFF(pdata,(*ppdata));
4104 break;
4106 case SMB_FILE_INTERNAL_INFORMATION:
4107 /* This should be an index number - looks like
4108 dev/ino to me :-)
4110 I think this causes us to fail the IFSKIT
4111 BasicFileInformationTest. -tpot */
4113 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4114 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4115 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4116 data_size = 8;
4117 break;
4119 case SMB_FILE_ACCESS_INFORMATION:
4120 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4121 SIVAL(pdata,0,access_mask);
4122 data_size = 4;
4123 break;
4125 case SMB_FILE_NAME_INFORMATION:
4126 /* Pathname with leading '\'. */
4128 size_t byte_len;
4129 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4130 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4131 SIVAL(pdata,0,byte_len);
4132 data_size = 4 + byte_len;
4133 break;
4136 case SMB_FILE_DISPOSITION_INFORMATION:
4137 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4138 data_size = 1;
4139 SCVAL(pdata,0,delete_pending);
4140 break;
4142 case SMB_FILE_POSITION_INFORMATION:
4143 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4144 data_size = 8;
4145 SOFF_T(pdata,0,pos);
4146 break;
4148 case SMB_FILE_MODE_INFORMATION:
4149 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4150 SIVAL(pdata,0,mode);
4151 data_size = 4;
4152 break;
4154 case SMB_FILE_ALIGNMENT_INFORMATION:
4155 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4156 SIVAL(pdata,0,0); /* No alignment needed. */
4157 data_size = 4;
4158 break;
4160 #if 0
4162 * NT4 server just returns "invalid query" to this - if we try to answer
4163 * it then NTws gets a BSOD! (tridge).
4164 * W2K seems to want this. JRA.
4166 case SMB_QUERY_FILE_STREAM_INFO:
4167 #endif
4168 case SMB_FILE_STREAM_INFORMATION:
4169 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4170 if (mode & aDIR) {
4171 data_size = 0;
4172 } else {
4173 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4174 SIVAL(pdata,0,0); /* ??? */
4175 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4176 SOFF_T(pdata,8,file_size);
4177 SOFF_T(pdata,16,allocation_size);
4178 data_size = 24 + byte_len;
4180 break;
4182 case SMB_QUERY_COMPRESSION_INFO:
4183 case SMB_FILE_COMPRESSION_INFORMATION:
4184 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4185 SOFF_T(pdata,0,file_size);
4186 SIVAL(pdata,8,0); /* ??? */
4187 SIVAL(pdata,12,0); /* ??? */
4188 data_size = 16;
4189 break;
4191 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4192 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4193 put_long_date_timespec(pdata,create_time_ts);
4194 put_long_date_timespec(pdata+8,atime_ts);
4195 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4196 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4197 SOFF_T(pdata,32,allocation_size);
4198 SOFF_T(pdata,40,file_size);
4199 SIVAL(pdata,48,mode);
4200 SIVAL(pdata,52,0); /* ??? */
4201 data_size = 56;
4202 break;
4204 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4205 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4206 SIVAL(pdata,0,mode);
4207 SIVAL(pdata,4,0);
4208 data_size = 8;
4209 break;
4212 * CIFS UNIX Extensions.
4215 case SMB_QUERY_FILE_UNIX_BASIC:
4217 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4218 data_size = PTR_DIFF(pdata,(*ppdata));
4221 int i;
4222 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4224 for (i=0; i<100; i++)
4225 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4226 DEBUG(4,("\n"));
4229 break;
4231 case SMB_QUERY_FILE_UNIX_INFO2:
4233 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4234 data_size = PTR_DIFF(pdata,(*ppdata));
4237 int i;
4238 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4240 for (i=0; i<100; i++)
4241 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4242 DEBUG(4,("\n"));
4245 break;
4247 case SMB_QUERY_FILE_UNIX_LINK:
4249 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4251 if (!buffer) {
4252 reply_nterror(req, NT_STATUS_NO_MEMORY);
4253 return;
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4257 #ifdef S_ISLNK
4258 if(!S_ISLNK(sbuf.st_mode)) {
4259 reply_unixerror(req, ERRSRV,
4260 ERRbadlink);
4261 return;
4263 #else
4264 reply_unixerror(req, ERRDOS, ERRbadlink);
4265 return;
4266 #endif
4267 len = SMB_VFS_READLINK(conn,fullpathname,
4268 buffer, PATH_MAX);
4269 if (len == -1) {
4270 reply_unixerror(req, ERRDOS,
4271 ERRnoaccess);
4272 return;
4274 buffer[len] = 0;
4275 len = srvstr_push(dstart, req->flags2,
4276 pdata, buffer,
4277 PTR_DIFF(dend, pdata),
4278 STR_TERMINATE);
4279 pdata += len;
4280 data_size = PTR_DIFF(pdata,(*ppdata));
4282 break;
4285 #if defined(HAVE_POSIX_ACLS)
4286 case SMB_QUERY_POSIX_ACL:
4288 SMB_ACL_T file_acl = NULL;
4289 SMB_ACL_T def_acl = NULL;
4290 uint16 num_file_acls = 0;
4291 uint16 num_def_acls = 0;
4293 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4294 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4295 } else {
4296 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4299 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4300 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4301 fname ));
4302 reply_nterror(
4303 req,
4304 NT_STATUS_NOT_IMPLEMENTED);
4305 return;
4308 if (S_ISDIR(sbuf.st_mode)) {
4309 if (fsp && fsp->is_directory) {
4310 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4311 } else {
4312 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4314 def_acl = free_empty_sys_acl(conn, def_acl);
4317 num_file_acls = count_acl_entries(conn, file_acl);
4318 num_def_acls = count_acl_entries(conn, def_acl);
4320 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4321 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4322 data_size,
4323 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4324 SMB_POSIX_ACL_HEADER_SIZE) ));
4325 if (file_acl) {
4326 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4328 if (def_acl) {
4329 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4331 reply_nterror(
4332 req,
4333 NT_STATUS_BUFFER_TOO_SMALL);
4334 return;
4337 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4338 SSVAL(pdata,2,num_file_acls);
4339 SSVAL(pdata,4,num_def_acls);
4340 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4341 if (file_acl) {
4342 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4344 if (def_acl) {
4345 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4347 reply_nterror(
4348 req, NT_STATUS_INTERNAL_ERROR);
4349 return;
4351 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4352 if (file_acl) {
4353 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4355 if (def_acl) {
4356 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4358 reply_nterror(
4359 req,
4360 NT_STATUS_INTERNAL_ERROR);
4361 return;
4364 if (file_acl) {
4365 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4367 if (def_acl) {
4368 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4370 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4371 break;
4373 #endif
4376 case SMB_QUERY_POSIX_LOCK:
4378 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4379 SMB_BIG_UINT count;
4380 SMB_BIG_UINT offset;
4381 uint32 lock_pid;
4382 enum brl_type lock_type;
4384 if (total_data != POSIX_LOCK_DATA_SIZE) {
4385 reply_nterror(
4386 req, NT_STATUS_INVALID_PARAMETER);
4387 return;
4390 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4391 case POSIX_LOCK_TYPE_READ:
4392 lock_type = READ_LOCK;
4393 break;
4394 case POSIX_LOCK_TYPE_WRITE:
4395 lock_type = WRITE_LOCK;
4396 break;
4397 case POSIX_LOCK_TYPE_UNLOCK:
4398 default:
4399 /* There's no point in asking for an unlock... */
4400 reply_nterror(
4401 req,
4402 NT_STATUS_INVALID_PARAMETER);
4403 return;
4406 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4407 #if defined(HAVE_LONGLONG)
4408 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4409 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4410 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4411 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4412 #else /* HAVE_LONGLONG */
4413 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4414 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4415 #endif /* HAVE_LONGLONG */
4417 status = query_lock(fsp,
4418 &lock_pid,
4419 &count,
4420 &offset,
4421 &lock_type,
4422 POSIX_LOCK);
4424 if (ERROR_WAS_LOCK_DENIED(status)) {
4425 /* Here we need to report who has it locked... */
4426 data_size = POSIX_LOCK_DATA_SIZE;
4428 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4429 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4430 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4431 #if defined(HAVE_LONGLONG)
4432 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4433 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4434 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4435 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4436 #else /* HAVE_LONGLONG */
4437 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4438 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4439 #endif /* HAVE_LONGLONG */
4441 } else if (NT_STATUS_IS_OK(status)) {
4442 /* For success we just return a copy of what we sent
4443 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4444 data_size = POSIX_LOCK_DATA_SIZE;
4445 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4446 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4447 } else {
4448 reply_nterror(req, status);
4449 return;
4451 break;
4454 default:
4455 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4456 return;
4459 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4460 max_data_bytes);
4462 return;
4465 /****************************************************************************
4466 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4467 code.
4468 ****************************************************************************/
4470 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4471 connection_struct *conn,
4472 const char *oldname_in,
4473 const char *newname_in)
4475 SMB_STRUCT_STAT sbuf1, sbuf2;
4476 char *last_component_oldname = NULL;
4477 char *last_component_newname = NULL;
4478 char *oldname = NULL;
4479 char *newname = NULL;
4480 NTSTATUS status = NT_STATUS_OK;
4482 ZERO_STRUCT(sbuf1);
4483 ZERO_STRUCT(sbuf2);
4485 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4486 &last_component_oldname, &sbuf1);
4487 if (!NT_STATUS_IS_OK(status)) {
4488 return status;
4491 status = check_name(conn, oldname);
4492 if (!NT_STATUS_IS_OK(status)) {
4493 return status;
4496 /* source must already exist. */
4497 if (!VALID_STAT(sbuf1)) {
4498 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4501 status = unix_convert(ctx, conn, newname_in, False, &newname,
4502 &last_component_newname, &sbuf2);
4503 if (!NT_STATUS_IS_OK(status)) {
4504 return status;
4507 status = check_name(conn, newname);
4508 if (!NT_STATUS_IS_OK(status)) {
4509 return status;
4512 /* Disallow if newname already exists. */
4513 if (VALID_STAT(sbuf2)) {
4514 return NT_STATUS_OBJECT_NAME_COLLISION;
4517 /* No links from a directory. */
4518 if (S_ISDIR(sbuf1.st_mode)) {
4519 return NT_STATUS_FILE_IS_A_DIRECTORY;
4522 /* Ensure this is within the share. */
4523 status = check_reduced_name(conn, oldname);
4524 if (!NT_STATUS_IS_OK(status)) {
4525 return status;
4528 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4530 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4531 status = map_nt_error_from_unix(errno);
4532 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4533 nt_errstr(status), newname, oldname));
4536 return status;
4539 /****************************************************************************
4540 Deal with setting the time from any of the setfilepathinfo functions.
4541 ****************************************************************************/
4543 static NTSTATUS smb_set_file_time(connection_struct *conn,
4544 files_struct *fsp,
4545 const char *fname,
4546 const SMB_STRUCT_STAT *psbuf,
4547 struct timespec ts[2],
4548 bool setting_write_time)
4550 uint32 action =
4551 FILE_NOTIFY_CHANGE_LAST_ACCESS
4552 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4554 if (!VALID_STAT(*psbuf)) {
4555 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4558 /* get some defaults (no modifications) if any info is zero or -1. */
4559 if (null_timespec(ts[0])) {
4560 ts[0] = get_atimespec(psbuf);
4561 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4564 if (null_timespec(ts[1])) {
4565 ts[1] = get_mtimespec(psbuf);
4566 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4569 if (!setting_write_time) {
4570 /* ts[1] comes from change time, not write time. */
4571 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4574 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4575 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4578 * Try and set the times of this file if
4579 * they are different from the current values.
4583 struct timespec mts = get_mtimespec(psbuf);
4584 struct timespec ats = get_atimespec(psbuf);
4585 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4586 return NT_STATUS_OK;
4590 if(fsp != NULL) {
4592 * This was a setfileinfo on an open file.
4593 * NT does this a lot. We also need to
4594 * set the time here, as it can be read by
4595 * FindFirst/FindNext and with the patch for bug #2045
4596 * in smbd/fileio.c it ensures that this timestamp is
4597 * kept sticky even after a write. We save the request
4598 * away and will set it on file close and after a write. JRA.
4601 if (!null_timespec(ts[1])) {
4602 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4603 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4604 fsp_set_pending_modtime(fsp, ts[1]);
4608 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4610 if(file_ntimes(conn, fname, ts)!=0) {
4611 return map_nt_error_from_unix(errno);
4613 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4615 return NT_STATUS_OK;
4618 /****************************************************************************
4619 Deal with setting the dosmode from any of the setfilepathinfo functions.
4620 ****************************************************************************/
4622 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4623 const char *fname,
4624 SMB_STRUCT_STAT *psbuf,
4625 uint32 dosmode)
4627 if (!VALID_STAT(*psbuf)) {
4628 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4631 if (dosmode) {
4632 if (S_ISDIR(psbuf->st_mode)) {
4633 dosmode |= aDIR;
4634 } else {
4635 dosmode &= ~aDIR;
4639 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4641 /* check the mode isn't different, before changing it */
4642 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4644 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4645 fname, (unsigned int)dosmode ));
4647 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4648 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4649 fname, strerror(errno)));
4650 return map_nt_error_from_unix(errno);
4653 return NT_STATUS_OK;
4656 /****************************************************************************
4657 Deal with setting the size from any of the setfilepathinfo functions.
4658 ****************************************************************************/
4660 static NTSTATUS smb_set_file_size(connection_struct *conn,
4661 struct smb_request *req,
4662 files_struct *fsp,
4663 const char *fname,
4664 SMB_STRUCT_STAT *psbuf,
4665 SMB_OFF_T size)
4667 NTSTATUS status = NT_STATUS_OK;
4668 files_struct *new_fsp = NULL;
4670 if (!VALID_STAT(*psbuf)) {
4671 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4674 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4676 if (size == get_file_size(*psbuf)) {
4677 return NT_STATUS_OK;
4680 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4681 fname, (double)size ));
4683 if (fsp && fsp->fh->fd != -1) {
4684 /* Handle based call. */
4685 if (vfs_set_filelen(fsp, size) == -1) {
4686 return map_nt_error_from_unix(errno);
4688 return NT_STATUS_OK;
4691 status = open_file_ntcreate(conn, req, fname, psbuf,
4692 FILE_WRITE_DATA,
4693 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4694 FILE_OPEN,
4696 FILE_ATTRIBUTE_NORMAL,
4697 FORCE_OPLOCK_BREAK_TO_NONE,
4698 NULL, &new_fsp);
4700 if (!NT_STATUS_IS_OK(status)) {
4701 /* NB. We check for open_was_deferred in the caller. */
4702 return status;
4705 if (vfs_set_filelen(new_fsp, size) == -1) {
4706 status = map_nt_error_from_unix(errno);
4707 close_file(new_fsp,NORMAL_CLOSE);
4708 return status;
4711 close_file(new_fsp,NORMAL_CLOSE);
4712 return NT_STATUS_OK;
4715 /****************************************************************************
4716 Deal with SMB_INFO_SET_EA.
4717 ****************************************************************************/
4719 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4720 const char *pdata,
4721 int total_data,
4722 files_struct *fsp,
4723 const char *fname)
4725 struct ea_list *ea_list = NULL;
4726 TALLOC_CTX *ctx = NULL;
4727 NTSTATUS status = NT_STATUS_OK;
4729 if (total_data < 10) {
4731 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4732 length. They seem to have no effect. Bug #3212. JRA */
4734 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4735 /* We're done. We only get EA info in this call. */
4736 return NT_STATUS_OK;
4739 return NT_STATUS_INVALID_PARAMETER;
4742 if (IVAL(pdata,0) > total_data) {
4743 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4744 IVAL(pdata,0), (unsigned int)total_data));
4745 return NT_STATUS_INVALID_PARAMETER;
4748 ctx = talloc_init("SMB_INFO_SET_EA");
4749 if (!ctx) {
4750 return NT_STATUS_NO_MEMORY;
4752 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4753 if (!ea_list) {
4754 talloc_destroy(ctx);
4755 return NT_STATUS_INVALID_PARAMETER;
4757 status = set_ea(conn, fsp, fname, ea_list);
4758 talloc_destroy(ctx);
4760 return status;
4763 /****************************************************************************
4764 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4765 ****************************************************************************/
4767 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4768 const char *pdata,
4769 int total_data,
4770 files_struct *fsp,
4771 const char *fname,
4772 SMB_STRUCT_STAT *psbuf)
4774 NTSTATUS status = NT_STATUS_OK;
4775 bool delete_on_close;
4776 uint32 dosmode = 0;
4778 if (total_data < 1) {
4779 return NT_STATUS_INVALID_PARAMETER;
4782 if (fsp == NULL) {
4783 return NT_STATUS_INVALID_HANDLE;
4786 delete_on_close = (CVAL(pdata,0) ? True : False);
4787 dosmode = dos_mode(conn, fname, psbuf);
4789 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4790 "delete_on_close = %u\n",
4791 fsp->fsp_name,
4792 (unsigned int)dosmode,
4793 (unsigned int)delete_on_close ));
4795 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4797 if (!NT_STATUS_IS_OK(status)) {
4798 return status;
4801 /* The set is across all open files on this dev/inode pair. */
4802 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4803 return NT_STATUS_ACCESS_DENIED;
4805 return NT_STATUS_OK;
4808 /****************************************************************************
4809 Deal with SMB_FILE_POSITION_INFORMATION.
4810 ****************************************************************************/
4812 static NTSTATUS smb_file_position_information(connection_struct *conn,
4813 const char *pdata,
4814 int total_data,
4815 files_struct *fsp)
4817 SMB_BIG_UINT position_information;
4819 if (total_data < 8) {
4820 return NT_STATUS_INVALID_PARAMETER;
4823 if (fsp == NULL) {
4824 /* Ignore on pathname based set. */
4825 return NT_STATUS_OK;
4828 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4829 #ifdef LARGE_SMB_OFF_T
4830 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4831 #else /* LARGE_SMB_OFF_T */
4832 if (IVAL(pdata,4) != 0) {
4833 /* more than 32 bits? */
4834 return NT_STATUS_INVALID_PARAMETER;
4836 #endif /* LARGE_SMB_OFF_T */
4838 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4839 fsp->fsp_name, (double)position_information ));
4840 fsp->fh->position_information = position_information;
4841 return NT_STATUS_OK;
4844 /****************************************************************************
4845 Deal with SMB_FILE_MODE_INFORMATION.
4846 ****************************************************************************/
4848 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4849 const char *pdata,
4850 int total_data)
4852 uint32 mode;
4854 if (total_data < 4) {
4855 return NT_STATUS_INVALID_PARAMETER;
4857 mode = IVAL(pdata,0);
4858 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4859 return NT_STATUS_INVALID_PARAMETER;
4861 return NT_STATUS_OK;
4864 /****************************************************************************
4865 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4866 ****************************************************************************/
4868 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4869 struct smb_request *req,
4870 const char *pdata,
4871 int total_data,
4872 const char *fname)
4874 char *link_target = NULL;
4875 const char *newname = fname;
4876 NTSTATUS status = NT_STATUS_OK;
4877 TALLOC_CTX *ctx = talloc_tos();
4879 /* Set a symbolic link. */
4880 /* Don't allow this if follow links is false. */
4882 if (total_data == 0) {
4883 return NT_STATUS_INVALID_PARAMETER;
4886 if (!lp_symlinks(SNUM(conn))) {
4887 return NT_STATUS_ACCESS_DENIED;
4890 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4891 total_data, STR_TERMINATE);
4893 if (!link_target) {
4894 return NT_STATUS_INVALID_PARAMETER;
4897 /* !widelinks forces the target path to be within the share. */
4898 /* This means we can interpret the target as a pathname. */
4899 if (!lp_widelinks(SNUM(conn))) {
4900 char *rel_name = NULL;
4901 char *last_dirp = NULL;
4903 if (*link_target == '/') {
4904 /* No absolute paths allowed. */
4905 return NT_STATUS_ACCESS_DENIED;
4907 rel_name = talloc_strdup(ctx,newname);
4908 if (!rel_name) {
4909 return NT_STATUS_NO_MEMORY;
4911 last_dirp = strrchr_m(rel_name, '/');
4912 if (last_dirp) {
4913 last_dirp[1] = '\0';
4914 } else {
4915 rel_name = talloc_strdup(ctx,"./");
4916 if (!rel_name) {
4917 return NT_STATUS_NO_MEMORY;
4920 rel_name = talloc_asprintf_append(rel_name,
4921 "%s",
4922 link_target);
4923 if (!rel_name) {
4924 return NT_STATUS_NO_MEMORY;
4927 status = check_name(conn, rel_name);
4928 if (!NT_STATUS_IS_OK(status)) {
4929 return status;
4933 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4934 newname, link_target ));
4936 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4937 return map_nt_error_from_unix(errno);
4940 return NT_STATUS_OK;
4943 /****************************************************************************
4944 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4945 ****************************************************************************/
4947 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4948 struct smb_request *req,
4949 const char *pdata, int total_data,
4950 const char *fname)
4952 char *oldname = NULL;
4953 TALLOC_CTX *ctx = talloc_tos();
4954 NTSTATUS status = NT_STATUS_OK;
4956 /* Set a hard link. */
4957 if (total_data == 0) {
4958 return NT_STATUS_INVALID_PARAMETER;
4961 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4962 total_data, STR_TERMINATE, &status);
4963 if (!NT_STATUS_IS_OK(status)) {
4964 return status;
4967 status = resolve_dfspath(ctx, conn,
4968 req->flags2 & FLAGS2_DFS_PATHNAMES,
4969 oldname,
4970 &oldname);
4971 if (!NT_STATUS_IS_OK(status)) {
4972 return status;
4975 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4976 fname, oldname));
4978 return hardlink_internals(ctx, conn, oldname, fname);
4981 /****************************************************************************
4982 Deal with SMB_FILE_RENAME_INFORMATION.
4983 ****************************************************************************/
4985 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4986 struct smb_request *req,
4987 const char *pdata,
4988 int total_data,
4989 files_struct *fsp,
4990 const char *fname)
4992 bool overwrite;
4993 uint32 root_fid;
4994 uint32 len;
4995 char *newname = NULL;
4996 char *base_name = NULL;
4997 bool dest_has_wcard = False;
4998 NTSTATUS status = NT_STATUS_OK;
4999 char *p;
5000 TALLOC_CTX *ctx = talloc_tos();
5002 if (total_data < 13) {
5003 return NT_STATUS_INVALID_PARAMETER;
5006 overwrite = (CVAL(pdata,0) ? True : False);
5007 root_fid = IVAL(pdata,4);
5008 len = IVAL(pdata,8);
5010 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5011 return NT_STATUS_INVALID_PARAMETER;
5014 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5015 len, 0, &status,
5016 &dest_has_wcard);
5017 if (!NT_STATUS_IS_OK(status)) {
5018 return status;
5021 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5022 newname));
5024 status = resolve_dfspath_wcard(ctx, conn,
5025 req->flags2 & FLAGS2_DFS_PATHNAMES,
5026 newname,
5027 &newname,
5028 &dest_has_wcard);
5029 if (!NT_STATUS_IS_OK(status)) {
5030 return status;
5033 /* Check the new name has no '/' characters. */
5034 if (strchr_m(newname, '/')) {
5035 return NT_STATUS_NOT_SUPPORTED;
5038 /* Create the base directory. */
5039 base_name = talloc_strdup(ctx, fname);
5040 if (!base_name) {
5041 return NT_STATUS_NO_MEMORY;
5043 p = strrchr_m(base_name, '/');
5044 if (p) {
5045 p[1] = '\0';
5046 } else {
5047 base_name = talloc_strdup(ctx, "./");
5048 if (!base_name) {
5049 return NT_STATUS_NO_MEMORY;
5052 /* Append the new name. */
5053 base_name = talloc_asprintf_append(base_name,
5054 "%s",
5055 newname);
5056 if (!base_name) {
5057 return NT_STATUS_NO_MEMORY;
5060 if (fsp) {
5061 SMB_STRUCT_STAT sbuf;
5062 char *newname_last_component = NULL;
5064 ZERO_STRUCT(sbuf);
5066 status = unix_convert(ctx, conn, newname, False,
5067 &newname,
5068 &newname_last_component,
5069 &sbuf);
5071 /* If an error we expect this to be
5072 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5074 if (!NT_STATUS_IS_OK(status)
5075 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5076 status)) {
5077 return status;
5080 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5081 fsp->fnum, fsp->fsp_name, base_name ));
5082 status = rename_internals_fsp(conn, fsp, base_name,
5083 newname_last_component, 0,
5084 overwrite);
5085 } else {
5086 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5087 fname, base_name ));
5088 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5089 overwrite, False, dest_has_wcard);
5092 return status;
5095 /****************************************************************************
5096 Deal with SMB_SET_POSIX_ACL.
5097 ****************************************************************************/
5099 #if defined(HAVE_POSIX_ACLS)
5100 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5101 const char *pdata,
5102 int total_data,
5103 files_struct *fsp,
5104 const char *fname,
5105 SMB_STRUCT_STAT *psbuf)
5107 uint16 posix_acl_version;
5108 uint16 num_file_acls;
5109 uint16 num_def_acls;
5110 bool valid_file_acls = True;
5111 bool valid_def_acls = True;
5113 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5114 return NT_STATUS_INVALID_PARAMETER;
5116 posix_acl_version = SVAL(pdata,0);
5117 num_file_acls = SVAL(pdata,2);
5118 num_def_acls = SVAL(pdata,4);
5120 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5121 valid_file_acls = False;
5122 num_file_acls = 0;
5125 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5126 valid_def_acls = False;
5127 num_def_acls = 0;
5130 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5131 return NT_STATUS_INVALID_PARAMETER;
5134 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5135 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5136 return NT_STATUS_INVALID_PARAMETER;
5139 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5140 fname ? fname : fsp->fsp_name,
5141 (unsigned int)num_file_acls,
5142 (unsigned int)num_def_acls));
5144 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5145 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5146 return map_nt_error_from_unix(errno);
5149 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5150 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5151 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5152 return map_nt_error_from_unix(errno);
5154 return NT_STATUS_OK;
5156 #endif
5158 /****************************************************************************
5159 Deal with SMB_SET_POSIX_LOCK.
5160 ****************************************************************************/
5162 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5163 const uint8 *inbuf,
5164 int length,
5165 const char *pdata,
5166 int total_data,
5167 files_struct *fsp)
5169 SMB_BIG_UINT count;
5170 SMB_BIG_UINT offset;
5171 uint32 lock_pid;
5172 bool blocking_lock = False;
5173 enum brl_type lock_type;
5174 NTSTATUS status = NT_STATUS_OK;
5176 if (fsp == NULL || fsp->fh->fd == -1) {
5177 return NT_STATUS_INVALID_HANDLE;
5180 if (total_data != POSIX_LOCK_DATA_SIZE) {
5181 return NT_STATUS_INVALID_PARAMETER;
5184 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5185 case POSIX_LOCK_TYPE_READ:
5186 lock_type = READ_LOCK;
5187 break;
5188 case POSIX_LOCK_TYPE_WRITE:
5189 /* Return the right POSIX-mappable error code for files opened read-only. */
5190 if (!fsp->can_write) {
5191 return NT_STATUS_INVALID_HANDLE;
5193 lock_type = WRITE_LOCK;
5194 break;
5195 case POSIX_LOCK_TYPE_UNLOCK:
5196 lock_type = UNLOCK_LOCK;
5197 break;
5198 default:
5199 return NT_STATUS_INVALID_PARAMETER;
5202 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5203 blocking_lock = False;
5204 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5205 blocking_lock = True;
5206 } else {
5207 return NT_STATUS_INVALID_PARAMETER;
5210 if (!lp_blocking_locks(SNUM(conn))) {
5211 blocking_lock = False;
5214 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5215 #if defined(HAVE_LONGLONG)
5216 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5217 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5218 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5219 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5220 #else /* HAVE_LONGLONG */
5221 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5222 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5223 #endif /* HAVE_LONGLONG */
5225 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5226 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5227 fsp->fsp_name,
5228 (unsigned int)lock_type,
5229 (unsigned int)lock_pid,
5230 (double)count,
5231 (double)offset ));
5233 if (lock_type == UNLOCK_LOCK) {
5234 status = do_unlock(smbd_messaging_context(),
5235 fsp,
5236 lock_pid,
5237 count,
5238 offset,
5239 POSIX_LOCK);
5240 } else {
5241 uint32 block_smbpid;
5243 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5244 fsp,
5245 lock_pid,
5246 count,
5247 offset,
5248 lock_type,
5249 POSIX_LOCK,
5250 blocking_lock,
5251 &status,
5252 &block_smbpid);
5254 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5256 * A blocking lock was requested. Package up
5257 * this smb into a queued request and push it
5258 * onto the blocking lock queue.
5260 if(push_blocking_lock_request(br_lck,
5261 (char *)inbuf, length,
5262 fsp,
5263 -1, /* infinite timeout. */
5265 lock_pid,
5266 lock_type,
5267 POSIX_LOCK,
5268 offset,
5269 count,
5270 block_smbpid)) {
5271 TALLOC_FREE(br_lck);
5272 return status;
5275 TALLOC_FREE(br_lck);
5278 return status;
5281 /****************************************************************************
5282 Deal with SMB_INFO_STANDARD.
5283 ****************************************************************************/
5285 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5286 const char *pdata,
5287 int total_data,
5288 files_struct *fsp,
5289 const char *fname,
5290 const SMB_STRUCT_STAT *psbuf)
5292 struct timespec ts[2];
5294 if (total_data < 12) {
5295 return NT_STATUS_INVALID_PARAMETER;
5298 /* access time */
5299 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5300 /* write time */
5301 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5303 DEBUG(10,("smb_set_info_standard: file %s\n",
5304 fname ? fname : fsp->fsp_name ));
5306 return smb_set_file_time(conn,
5307 fsp,
5308 fname,
5309 psbuf,
5311 true);
5314 /****************************************************************************
5315 Deal with SMB_SET_FILE_BASIC_INFO.
5316 ****************************************************************************/
5318 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5319 const char *pdata,
5320 int total_data,
5321 files_struct *fsp,
5322 const char *fname,
5323 SMB_STRUCT_STAT *psbuf)
5325 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5326 struct timespec write_time;
5327 struct timespec changed_time;
5328 uint32 dosmode = 0;
5329 struct timespec ts[2];
5330 NTSTATUS status = NT_STATUS_OK;
5331 bool setting_write_time = true;
5333 if (total_data < 36) {
5334 return NT_STATUS_INVALID_PARAMETER;
5337 /* Set the attributes */
5338 dosmode = IVAL(pdata,32);
5339 status = smb_set_file_dosmode(conn,
5340 fname,
5341 psbuf,
5342 dosmode);
5343 if (!NT_STATUS_IS_OK(status)) {
5344 return status;
5347 /* Ignore create time at offset pdata. */
5349 /* access time */
5350 ts[0] = interpret_long_date(pdata+8);
5352 write_time = interpret_long_date(pdata+16);
5353 changed_time = interpret_long_date(pdata+24);
5355 /* mtime */
5356 ts[1] = timespec_min(&write_time, &changed_time);
5358 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5359 ts[1] = write_time;
5362 /* Prefer a defined time to an undefined one. */
5363 if (null_timespec(ts[1])) {
5364 if (null_timespec(write_time)) {
5365 ts[1] = changed_time;
5366 setting_write_time = false;
5367 } else {
5368 ts[1] = write_time;
5372 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5373 fname ? fname : fsp->fsp_name ));
5375 return smb_set_file_time(conn,
5376 fsp,
5377 fname,
5378 psbuf,
5380 setting_write_time);
5383 /****************************************************************************
5384 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5385 ****************************************************************************/
5387 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5388 struct smb_request *req,
5389 const char *pdata,
5390 int total_data,
5391 files_struct *fsp,
5392 const char *fname,
5393 SMB_STRUCT_STAT *psbuf)
5395 SMB_BIG_UINT allocation_size = 0;
5396 NTSTATUS status = NT_STATUS_OK;
5397 files_struct *new_fsp = NULL;
5399 if (!VALID_STAT(*psbuf)) {
5400 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5403 if (total_data < 8) {
5404 return NT_STATUS_INVALID_PARAMETER;
5407 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5408 #ifdef LARGE_SMB_OFF_T
5409 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5410 #else /* LARGE_SMB_OFF_T */
5411 if (IVAL(pdata,4) != 0) {
5412 /* more than 32 bits? */
5413 return NT_STATUS_INVALID_PARAMETER;
5415 #endif /* LARGE_SMB_OFF_T */
5417 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5418 fname, (double)allocation_size ));
5420 if (allocation_size) {
5421 allocation_size = smb_roundup(conn, allocation_size);
5424 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5425 fname, (double)allocation_size ));
5427 if (fsp && fsp->fh->fd != -1) {
5428 /* Open file handle. */
5429 /* Only change if needed. */
5430 if (allocation_size != get_file_size(*psbuf)) {
5431 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5432 return map_nt_error_from_unix(errno);
5435 /* But always update the time. */
5436 if (null_timespec(fsp->pending_modtime)) {
5438 * This is equivalent to a write. Ensure it's seen immediately
5439 * if there are no pending writes.
5441 set_filetime(fsp->conn, fsp->fsp_name,
5442 timespec_current());
5444 return NT_STATUS_OK;
5447 /* Pathname or stat or directory file. */
5449 status = open_file_ntcreate(conn, req, fname, psbuf,
5450 FILE_WRITE_DATA,
5451 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5452 FILE_OPEN,
5454 FILE_ATTRIBUTE_NORMAL,
5455 FORCE_OPLOCK_BREAK_TO_NONE,
5456 NULL, &new_fsp);
5458 if (!NT_STATUS_IS_OK(status)) {
5459 /* NB. We check for open_was_deferred in the caller. */
5460 return status;
5463 /* Only change if needed. */
5464 if (allocation_size != get_file_size(*psbuf)) {
5465 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5466 status = map_nt_error_from_unix(errno);
5467 close_file(new_fsp,NORMAL_CLOSE);
5468 return status;
5472 /* Changing the allocation size should set the last mod time. */
5473 /* Don't need to call set_filetime as this will be flushed on
5474 * close. */
5476 fsp_set_pending_modtime(new_fsp, timespec_current());
5478 close_file(new_fsp,NORMAL_CLOSE);
5479 return NT_STATUS_OK;
5482 /****************************************************************************
5483 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5484 ****************************************************************************/
5486 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5487 struct smb_request *req,
5488 const char *pdata,
5489 int total_data,
5490 files_struct *fsp,
5491 const char *fname,
5492 SMB_STRUCT_STAT *psbuf)
5494 SMB_OFF_T size;
5496 if (total_data < 8) {
5497 return NT_STATUS_INVALID_PARAMETER;
5500 size = IVAL(pdata,0);
5501 #ifdef LARGE_SMB_OFF_T
5502 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5503 #else /* LARGE_SMB_OFF_T */
5504 if (IVAL(pdata,4) != 0) {
5505 /* more than 32 bits? */
5506 return NT_STATUS_INVALID_PARAMETER;
5508 #endif /* LARGE_SMB_OFF_T */
5509 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5510 "file %s to %.0f\n", fname, (double)size ));
5512 return smb_set_file_size(conn, req,
5513 fsp,
5514 fname,
5515 psbuf,
5516 size);
5519 /****************************************************************************
5520 Allow a UNIX info mknod.
5521 ****************************************************************************/
5523 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5524 const char *pdata,
5525 int total_data,
5526 const char *fname,
5527 SMB_STRUCT_STAT *psbuf)
5529 uint32 file_type = IVAL(pdata,56);
5530 #if defined(HAVE_MAKEDEV)
5531 uint32 dev_major = IVAL(pdata,60);
5532 uint32 dev_minor = IVAL(pdata,68);
5533 #endif
5534 SMB_DEV_T dev = (SMB_DEV_T)0;
5535 uint32 raw_unixmode = IVAL(pdata,84);
5536 NTSTATUS status;
5537 mode_t unixmode;
5539 if (total_data < 100) {
5540 return NT_STATUS_INVALID_PARAMETER;
5543 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5544 if (!NT_STATUS_IS_OK(status)) {
5545 return status;
5548 #if defined(HAVE_MAKEDEV)
5549 dev = makedev(dev_major, dev_minor);
5550 #endif
5552 switch (file_type) {
5553 #if defined(S_IFIFO)
5554 case UNIX_TYPE_FIFO:
5555 unixmode |= S_IFIFO;
5556 break;
5557 #endif
5558 #if defined(S_IFSOCK)
5559 case UNIX_TYPE_SOCKET:
5560 unixmode |= S_IFSOCK;
5561 break;
5562 #endif
5563 #if defined(S_IFCHR)
5564 case UNIX_TYPE_CHARDEV:
5565 unixmode |= S_IFCHR;
5566 break;
5567 #endif
5568 #if defined(S_IFBLK)
5569 case UNIX_TYPE_BLKDEV:
5570 unixmode |= S_IFBLK;
5571 break;
5572 #endif
5573 default:
5574 return NT_STATUS_INVALID_PARAMETER;
5577 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5578 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5580 /* Ok - do the mknod. */
5581 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5582 return map_nt_error_from_unix(errno);
5585 /* If any of the other "set" calls fail we
5586 * don't want to end up with a half-constructed mknod.
5589 if (lp_inherit_perms(SNUM(conn))) {
5590 inherit_access_acl(
5591 conn, parent_dirname(fname),
5592 fname, unixmode);
5595 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5596 status = map_nt_error_from_unix(errno);
5597 SMB_VFS_UNLINK(conn,fname);
5598 return status;
5600 return NT_STATUS_OK;
5603 /****************************************************************************
5604 Deal with SMB_SET_FILE_UNIX_BASIC.
5605 ****************************************************************************/
5607 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5608 struct smb_request *req,
5609 const char *pdata,
5610 int total_data,
5611 files_struct *fsp,
5612 const char *fname,
5613 SMB_STRUCT_STAT *psbuf)
5615 struct timespec ts[2];
5616 uint32 raw_unixmode;
5617 mode_t unixmode;
5618 SMB_OFF_T size = 0;
5619 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5620 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5621 NTSTATUS status = NT_STATUS_OK;
5622 bool delete_on_fail = False;
5623 enum perm_type ptype;
5625 if (total_data < 100) {
5626 return NT_STATUS_INVALID_PARAMETER;
5629 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5630 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5631 size=IVAL(pdata,0); /* first 8 Bytes are size */
5632 #ifdef LARGE_SMB_OFF_T
5633 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5634 #else /* LARGE_SMB_OFF_T */
5635 if (IVAL(pdata,4) != 0) {
5636 /* more than 32 bits? */
5637 return NT_STATUS_INVALID_PARAMETER;
5639 #endif /* LARGE_SMB_OFF_T */
5642 ts[0] = interpret_long_date(pdata+24); /* access_time */
5643 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5644 set_owner = (uid_t)IVAL(pdata,40);
5645 set_grp = (gid_t)IVAL(pdata,48);
5646 raw_unixmode = IVAL(pdata,84);
5648 if (VALID_STAT(*psbuf)) {
5649 if (S_ISDIR(psbuf->st_mode)) {
5650 ptype = PERM_EXISTING_DIR;
5651 } else {
5652 ptype = PERM_EXISTING_FILE;
5654 } else {
5655 ptype = PERM_NEW_FILE;
5658 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5659 if (!NT_STATUS_IS_OK(status)) {
5660 return status;
5663 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5664 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5665 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5667 if (!VALID_STAT(*psbuf)) {
5669 * The only valid use of this is to create character and block
5670 * devices, and named pipes. This is deprecated (IMHO) and
5671 * a new info level should be used for mknod. JRA.
5674 status = smb_unix_mknod(conn,
5675 pdata,
5676 total_data,
5677 fname,
5678 psbuf);
5679 if (!NT_STATUS_IS_OK(status)) {
5680 return status;
5683 /* Ensure we don't try and change anything else. */
5684 raw_unixmode = SMB_MODE_NO_CHANGE;
5685 size = get_file_size(*psbuf);
5686 ts[0] = get_atimespec(psbuf);
5687 ts[1] = get_mtimespec(psbuf);
5689 * We continue here as we might want to change the
5690 * owner uid/gid.
5692 delete_on_fail = True;
5695 #if 1
5696 /* Horrible backwards compatibility hack as an old server bug
5697 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5698 * */
5700 if (!size) {
5701 size = get_file_size(*psbuf);
5703 #endif
5706 * Deal with the UNIX specific mode set.
5709 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5710 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5711 (unsigned int)unixmode, fname ));
5712 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5713 return map_nt_error_from_unix(errno);
5718 * Deal with the UNIX specific uid set.
5721 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5722 int ret;
5724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5725 (unsigned int)set_owner, fname ));
5727 if (S_ISLNK(psbuf->st_mode)) {
5728 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5729 } else {
5730 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5733 if (ret != 0) {
5734 status = map_nt_error_from_unix(errno);
5735 if (delete_on_fail) {
5736 SMB_VFS_UNLINK(conn,fname);
5738 return status;
5743 * Deal with the UNIX specific gid set.
5746 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5747 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5748 (unsigned int)set_owner, fname ));
5749 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5750 status = map_nt_error_from_unix(errno);
5751 if (delete_on_fail) {
5752 SMB_VFS_UNLINK(conn,fname);
5754 return status;
5758 /* Deal with any size changes. */
5760 status = smb_set_file_size(conn, req,
5761 fsp,
5762 fname,
5763 psbuf,
5764 size);
5765 if (!NT_STATUS_IS_OK(status)) {
5766 return status;
5769 /* Deal with any time changes. */
5771 return smb_set_file_time(conn,
5772 fsp,
5773 fname,
5774 psbuf,
5776 true);
5779 /****************************************************************************
5780 Deal with SMB_SET_FILE_UNIX_INFO2.
5781 ****************************************************************************/
5783 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5784 struct smb_request *req,
5785 const char *pdata,
5786 int total_data,
5787 files_struct *fsp,
5788 const char *fname,
5789 SMB_STRUCT_STAT *psbuf)
5791 NTSTATUS status;
5792 uint32 smb_fflags;
5793 uint32 smb_fmask;
5795 if (total_data < 116) {
5796 return NT_STATUS_INVALID_PARAMETER;
5799 /* Start by setting all the fields that are common between UNIX_BASIC
5800 * and UNIX_INFO2.
5802 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5803 fsp, fname, psbuf);
5804 if (!NT_STATUS_IS_OK(status)) {
5805 return status;
5808 smb_fflags = IVAL(pdata, 108);
5809 smb_fmask = IVAL(pdata, 112);
5811 /* NB: We should only attempt to alter the file flags if the client
5812 * sends a non-zero mask.
5814 if (smb_fmask != 0) {
5815 int stat_fflags = 0;
5817 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5818 &stat_fflags)) {
5819 /* Client asked to alter a flag we don't understand. */
5820 return NT_STATUS_INVALID_PARAMETER;
5823 if (fsp && fsp->fh->fd != -1) {
5824 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5825 return NT_STATUS_NOT_SUPPORTED;
5826 } else {
5827 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5828 return map_nt_error_from_unix(errno);
5833 /* XXX: need to add support for changing the create_time here. You
5834 * can do this for paths on Darwin with setattrlist(2). The right way
5835 * to hook this up is probably by extending the VFS utimes interface.
5838 return NT_STATUS_OK;
5841 /****************************************************************************
5842 Create a directory with POSIX semantics.
5843 ****************************************************************************/
5845 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5846 struct smb_request *req,
5847 char **ppdata,
5848 int total_data,
5849 const char *fname,
5850 SMB_STRUCT_STAT *psbuf,
5851 int *pdata_return_size)
5853 NTSTATUS status = NT_STATUS_OK;
5854 uint32 raw_unixmode = 0;
5855 uint32 mod_unixmode = 0;
5856 mode_t unixmode = (mode_t)0;
5857 files_struct *fsp = NULL;
5858 uint16 info_level_return = 0;
5859 int info;
5860 char *pdata = *ppdata;
5862 if (total_data < 18) {
5863 return NT_STATUS_INVALID_PARAMETER;
5866 raw_unixmode = IVAL(pdata,8);
5867 /* Next 4 bytes are not yet defined. */
5869 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5870 if (!NT_STATUS_IS_OK(status)) {
5871 return status;
5874 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5876 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5877 fname, (unsigned int)unixmode ));
5879 status = open_directory(conn, req,
5880 fname,
5881 psbuf,
5882 FILE_READ_ATTRIBUTES, /* Just a stat open */
5883 FILE_SHARE_NONE, /* Ignored for stat opens */
5884 FILE_CREATE,
5886 mod_unixmode,
5887 &info,
5888 &fsp);
5890 if (NT_STATUS_IS_OK(status)) {
5891 close_file(fsp, NORMAL_CLOSE);
5894 info_level_return = SVAL(pdata,16);
5896 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5897 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5898 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5899 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5900 } else {
5901 *pdata_return_size = 12;
5904 /* Realloc the data size */
5905 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5906 if (*ppdata == NULL) {
5907 *pdata_return_size = 0;
5908 return NT_STATUS_NO_MEMORY;
5910 pdata = *ppdata;
5912 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5913 SSVAL(pdata,2,0); /* No fnum. */
5914 SIVAL(pdata,4,info); /* Was directory created. */
5916 switch (info_level_return) {
5917 case SMB_QUERY_FILE_UNIX_BASIC:
5918 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5919 SSVAL(pdata,10,0); /* Padding. */
5920 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5921 break;
5922 case SMB_QUERY_FILE_UNIX_INFO2:
5923 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5924 SSVAL(pdata,10,0); /* Padding. */
5925 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5926 break;
5927 default:
5928 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5929 SSVAL(pdata,10,0); /* Padding. */
5930 break;
5933 return status;
5936 /****************************************************************************
5937 Open/Create a file with POSIX semantics.
5938 ****************************************************************************/
5940 static NTSTATUS smb_posix_open(connection_struct *conn,
5941 struct smb_request *req,
5942 char **ppdata,
5943 int total_data,
5944 const char *fname,
5945 SMB_STRUCT_STAT *psbuf,
5946 int *pdata_return_size)
5948 bool extended_oplock_granted = False;
5949 char *pdata = *ppdata;
5950 uint32 flags = 0;
5951 uint32 wire_open_mode = 0;
5952 uint32 raw_unixmode = 0;
5953 uint32 mod_unixmode = 0;
5954 uint32 create_disp = 0;
5955 uint32 access_mask = 0;
5956 uint32 create_options = 0;
5957 NTSTATUS status = NT_STATUS_OK;
5958 mode_t unixmode = (mode_t)0;
5959 files_struct *fsp = NULL;
5960 int oplock_request = 0;
5961 int info = 0;
5962 uint16 info_level_return = 0;
5964 if (total_data < 18) {
5965 return NT_STATUS_INVALID_PARAMETER;
5968 flags = IVAL(pdata,0);
5969 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5970 if (oplock_request) {
5971 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5974 wire_open_mode = IVAL(pdata,4);
5976 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5977 return smb_posix_mkdir(conn, req,
5978 ppdata,
5979 total_data,
5980 fname,
5981 psbuf,
5982 pdata_return_size);
5985 switch (wire_open_mode & SMB_ACCMODE) {
5986 case SMB_O_RDONLY:
5987 access_mask = FILE_READ_DATA;
5988 break;
5989 case SMB_O_WRONLY:
5990 access_mask = FILE_WRITE_DATA;
5991 break;
5992 case SMB_O_RDWR:
5993 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5994 break;
5995 default:
5996 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5997 (unsigned int)wire_open_mode ));
5998 return NT_STATUS_INVALID_PARAMETER;
6001 wire_open_mode &= ~SMB_ACCMODE;
6003 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6004 create_disp = FILE_CREATE;
6005 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6006 create_disp = FILE_OVERWRITE_IF;
6007 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6008 create_disp = FILE_OPEN_IF;
6009 } else {
6010 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6011 (unsigned int)wire_open_mode ));
6012 return NT_STATUS_INVALID_PARAMETER;
6015 raw_unixmode = IVAL(pdata,8);
6016 /* Next 4 bytes are not yet defined. */
6018 status = unix_perms_from_wire(conn,
6019 psbuf,
6020 raw_unixmode,
6021 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6022 &unixmode);
6024 if (!NT_STATUS_IS_OK(status)) {
6025 return status;
6028 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6030 if (wire_open_mode & SMB_O_SYNC) {
6031 create_options |= FILE_WRITE_THROUGH;
6033 if (wire_open_mode & SMB_O_APPEND) {
6034 access_mask |= FILE_APPEND_DATA;
6036 if (wire_open_mode & SMB_O_DIRECT) {
6037 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6040 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6041 fname,
6042 (unsigned int)wire_open_mode,
6043 (unsigned int)unixmode ));
6045 status = open_file_ntcreate(conn, req,
6046 fname,
6047 psbuf,
6048 access_mask,
6049 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6050 create_disp,
6051 0, /* no create options yet. */
6052 mod_unixmode,
6053 oplock_request,
6054 &info,
6055 &fsp);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 return status;
6061 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6062 extended_oplock_granted = True;
6065 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6066 extended_oplock_granted = True;
6069 info_level_return = SVAL(pdata,16);
6071 /* Allocate the correct return size. */
6073 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6074 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6075 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6076 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6077 } else {
6078 *pdata_return_size = 12;
6081 /* Realloc the data size */
6082 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6083 if (*ppdata == NULL) {
6084 close_file(fsp,ERROR_CLOSE);
6085 *pdata_return_size = 0;
6086 return NT_STATUS_NO_MEMORY;
6088 pdata = *ppdata;
6090 if (extended_oplock_granted) {
6091 if (flags & REQUEST_BATCH_OPLOCK) {
6092 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6093 } else {
6094 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6096 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6097 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6098 } else {
6099 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6102 SSVAL(pdata,2,fsp->fnum);
6103 SIVAL(pdata,4,info); /* Was file created etc. */
6105 switch (info_level_return) {
6106 case SMB_QUERY_FILE_UNIX_BASIC:
6107 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6108 SSVAL(pdata,10,0); /* padding. */
6109 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6110 break;
6111 case SMB_QUERY_FILE_UNIX_INFO2:
6112 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6113 SSVAL(pdata,10,0); /* padding. */
6114 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6115 break;
6116 default:
6117 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6118 SSVAL(pdata,10,0); /* padding. */
6119 break;
6121 return NT_STATUS_OK;
6124 /****************************************************************************
6125 Delete a file with POSIX semantics.
6126 ****************************************************************************/
6128 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6129 struct smb_request *req,
6130 const char *pdata,
6131 int total_data,
6132 const char *fname,
6133 SMB_STRUCT_STAT *psbuf)
6135 NTSTATUS status = NT_STATUS_OK;
6136 files_struct *fsp = NULL;
6137 uint16 flags = 0;
6138 char del = 1;
6139 int info = 0;
6140 int i;
6141 struct share_mode_lock *lck = NULL;
6143 if (total_data < 2) {
6144 return NT_STATUS_INVALID_PARAMETER;
6147 flags = SVAL(pdata,0);
6149 if (!VALID_STAT(*psbuf)) {
6150 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6153 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6154 !VALID_STAT_OF_DIR(*psbuf)) {
6155 return NT_STATUS_NOT_A_DIRECTORY;
6158 DEBUG(10,("smb_posix_unlink: %s %s\n",
6159 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6160 fname));
6162 if (VALID_STAT_OF_DIR(*psbuf)) {
6163 status = open_directory(conn, req,
6164 fname,
6165 psbuf,
6166 DELETE_ACCESS,
6167 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6168 FILE_OPEN,
6170 FILE_FLAG_POSIX_SEMANTICS|0777,
6171 &info,
6172 &fsp);
6173 } else {
6175 status = open_file_ntcreate(conn, req,
6176 fname,
6177 psbuf,
6178 DELETE_ACCESS,
6179 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6180 FILE_OPEN,
6182 FILE_FLAG_POSIX_SEMANTICS|0777,
6183 0, /* No oplock, but break existing ones. */
6184 &info,
6185 &fsp);
6188 if (!NT_STATUS_IS_OK(status)) {
6189 return status;
6193 * Don't lie to client. If we can't really delete due to
6194 * non-POSIX opens return SHARING_VIOLATION.
6197 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6198 if (lck == NULL) {
6199 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6200 "lock for file %s\n", fsp->fsp_name));
6201 close_file(fsp, NORMAL_CLOSE);
6202 return NT_STATUS_INVALID_PARAMETER;
6206 * See if others still have the file open. If this is the case, then
6207 * don't delete. If all opens are POSIX delete we can set the delete
6208 * on close disposition.
6210 for (i=0; i<lck->num_share_modes; i++) {
6211 struct share_mode_entry *e = &lck->share_modes[i];
6212 if (is_valid_share_mode_entry(e)) {
6213 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6214 continue;
6216 /* Fail with sharing violation. */
6217 close_file(fsp, NORMAL_CLOSE);
6218 TALLOC_FREE(lck);
6219 return NT_STATUS_SHARING_VIOLATION;
6224 * Set the delete on close.
6226 status = smb_set_file_disposition_info(conn,
6227 &del,
6229 fsp,
6230 fname,
6231 psbuf);
6233 if (!NT_STATUS_IS_OK(status)) {
6234 close_file(fsp, NORMAL_CLOSE);
6235 TALLOC_FREE(lck);
6236 return status;
6238 TALLOC_FREE(lck);
6239 return close_file(fsp, NORMAL_CLOSE);
6242 /****************************************************************************
6243 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6244 ****************************************************************************/
6246 static void call_trans2setfilepathinfo(connection_struct *conn,
6247 struct smb_request *req,
6248 unsigned int tran_call,
6249 char **pparams, int total_params,
6250 char **ppdata, int total_data,
6251 unsigned int max_data_bytes)
6253 char *params = *pparams;
6254 char *pdata = *ppdata;
6255 uint16 info_level;
6256 SMB_STRUCT_STAT sbuf;
6257 char *fname = NULL;
6258 files_struct *fsp = NULL;
6259 NTSTATUS status = NT_STATUS_OK;
6260 int data_return_size = 0;
6261 TALLOC_CTX *ctx = talloc_tos();
6263 if (!params) {
6264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6265 return;
6268 ZERO_STRUCT(sbuf);
6270 if (tran_call == TRANSACT2_SETFILEINFO) {
6271 if (total_params < 4) {
6272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6273 return;
6276 fsp = file_fsp(SVAL(params,0));
6277 /* Basic check for non-null fsp. */
6278 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6279 return;
6281 info_level = SVAL(params,2);
6283 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6284 if (!fname) {
6285 reply_nterror(req, NT_STATUS_NO_MEMORY);
6286 return;
6289 if(fsp->is_directory || fsp->fh->fd == -1) {
6291 * This is actually a SETFILEINFO on a directory
6292 * handle (returned from an NT SMB). NT5.0 seems
6293 * to do this call. JRA.
6295 if (INFO_LEVEL_IS_UNIX(info_level)) {
6296 /* Always do lstat for UNIX calls. */
6297 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6298 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6299 reply_unixerror(req,ERRDOS,ERRbadpath);
6300 return;
6302 } else {
6303 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6304 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6305 reply_unixerror(req,ERRDOS,ERRbadpath);
6306 return;
6309 } else if (fsp->print_file) {
6311 * Doing a DELETE_ON_CLOSE should cancel a print job.
6313 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6314 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6316 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6318 SSVAL(params,0,0);
6319 send_trans2_replies(req, params, 2,
6320 *ppdata, 0,
6321 max_data_bytes);
6322 return;
6323 } else {
6324 reply_unixerror(req, ERRDOS, ERRbadpath);
6325 return;
6327 } else {
6329 * Original code - this is an open file.
6331 if (!check_fsp(conn, req, fsp, &current_user)) {
6332 return;
6335 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6336 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6337 reply_unixerror(req, ERRDOS, ERRbadfid);
6338 return;
6341 } else {
6342 /* set path info */
6343 if (total_params < 7) {
6344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6345 return;
6348 info_level = SVAL(params,0);
6349 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6350 total_params - 6, STR_TERMINATE,
6351 &status);
6352 if (!NT_STATUS_IS_OK(status)) {
6353 reply_nterror(req, status);
6354 return;
6357 status = resolve_dfspath(ctx, conn,
6358 req->flags2 & FLAGS2_DFS_PATHNAMES,
6359 fname,
6360 &fname);
6361 if (!NT_STATUS_IS_OK(status)) {
6362 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6363 reply_botherror(req,
6364 NT_STATUS_PATH_NOT_COVERED,
6365 ERRSRV, ERRbadpath);
6366 return;
6368 reply_nterror(req, status);
6369 return;
6372 status = unix_convert(ctx, conn, fname, False,
6373 &fname, NULL, &sbuf);
6374 if (!NT_STATUS_IS_OK(status)) {
6375 reply_nterror(req, status);
6376 return;
6379 status = check_name(conn, fname);
6380 if (!NT_STATUS_IS_OK(status)) {
6381 reply_nterror(req, status);
6382 return;
6385 if (INFO_LEVEL_IS_UNIX(info_level)) {
6387 * For CIFS UNIX extensions the target name may not exist.
6390 /* Always do lstat for UNIX calls. */
6391 SMB_VFS_LSTAT(conn,fname,&sbuf);
6393 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6394 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6395 reply_unixerror(req, ERRDOS, ERRbadpath);
6396 return;
6400 if (!CAN_WRITE(conn)) {
6401 reply_doserror(req, ERRSRV, ERRaccess);
6402 return;
6405 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6406 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6407 return;
6410 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6411 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6413 /* Realloc the parameter size */
6414 *pparams = (char *)SMB_REALLOC(*pparams,2);
6415 if (*pparams == NULL) {
6416 reply_nterror(req, NT_STATUS_NO_MEMORY);
6417 return;
6419 params = *pparams;
6421 SSVAL(params,0,0);
6423 if (fsp && !null_timespec(fsp->pending_modtime)) {
6424 /* the pending modtime overrides the current modtime */
6425 set_mtimespec(&sbuf, fsp->pending_modtime);
6428 switch (info_level) {
6430 case SMB_INFO_STANDARD:
6432 status = smb_set_info_standard(conn,
6433 pdata,
6434 total_data,
6435 fsp,
6436 fname,
6437 &sbuf);
6438 break;
6441 case SMB_INFO_SET_EA:
6443 status = smb_info_set_ea(conn,
6444 pdata,
6445 total_data,
6446 fsp,
6447 fname);
6448 break;
6451 case SMB_SET_FILE_BASIC_INFO:
6452 case SMB_FILE_BASIC_INFORMATION:
6454 status = smb_set_file_basic_info(conn,
6455 pdata,
6456 total_data,
6457 fsp,
6458 fname,
6459 &sbuf);
6460 break;
6463 case SMB_FILE_ALLOCATION_INFORMATION:
6464 case SMB_SET_FILE_ALLOCATION_INFO:
6466 status = smb_set_file_allocation_info(conn, req,
6467 pdata,
6468 total_data,
6469 fsp,
6470 fname,
6471 &sbuf);
6472 break;
6475 case SMB_FILE_END_OF_FILE_INFORMATION:
6476 case SMB_SET_FILE_END_OF_FILE_INFO:
6478 status = smb_set_file_end_of_file_info(conn, req,
6479 pdata,
6480 total_data,
6481 fsp,
6482 fname,
6483 &sbuf);
6484 break;
6487 case SMB_FILE_DISPOSITION_INFORMATION:
6488 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6490 #if 0
6491 /* JRA - We used to just ignore this on a path ?
6492 * Shouldn't this be invalid level on a pathname
6493 * based call ?
6495 if (tran_call != TRANSACT2_SETFILEINFO) {
6496 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6498 #endif
6499 status = smb_set_file_disposition_info(conn,
6500 pdata,
6501 total_data,
6502 fsp,
6503 fname,
6504 &sbuf);
6505 break;
6508 case SMB_FILE_POSITION_INFORMATION:
6510 status = smb_file_position_information(conn,
6511 pdata,
6512 total_data,
6513 fsp);
6514 break;
6517 /* From tridge Samba4 :
6518 * MODE_INFORMATION in setfileinfo (I have no
6519 * idea what "mode information" on a file is - it takes a value of 0,
6520 * 2, 4 or 6. What could it be?).
6523 case SMB_FILE_MODE_INFORMATION:
6525 status = smb_file_mode_information(conn,
6526 pdata,
6527 total_data);
6528 break;
6532 * CIFS UNIX extensions.
6535 case SMB_SET_FILE_UNIX_BASIC:
6537 status = smb_set_file_unix_basic(conn, req,
6538 pdata,
6539 total_data,
6540 fsp,
6541 fname,
6542 &sbuf);
6543 break;
6546 case SMB_SET_FILE_UNIX_INFO2:
6548 status = smb_set_file_unix_info2(conn, req,
6549 pdata,
6550 total_data,
6551 fsp,
6552 fname,
6553 &sbuf);
6554 break;
6557 case SMB_SET_FILE_UNIX_LINK:
6559 if (tran_call != TRANSACT2_SETPATHINFO) {
6560 /* We must have a pathname for this. */
6561 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6562 return;
6564 status = smb_set_file_unix_link(conn, req, pdata,
6565 total_data, fname);
6566 break;
6569 case SMB_SET_FILE_UNIX_HLINK:
6571 if (tran_call != TRANSACT2_SETPATHINFO) {
6572 /* We must have a pathname for this. */
6573 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6574 return;
6576 status = smb_set_file_unix_hlink(conn, req,
6577 pdata, total_data,
6578 fname);
6579 break;
6582 case SMB_FILE_RENAME_INFORMATION:
6584 status = smb_file_rename_information(conn, req,
6585 pdata, total_data,
6586 fsp, fname);
6587 break;
6590 #if defined(HAVE_POSIX_ACLS)
6591 case SMB_SET_POSIX_ACL:
6593 status = smb_set_posix_acl(conn,
6594 pdata,
6595 total_data,
6596 fsp,
6597 fname,
6598 &sbuf);
6599 break;
6601 #endif
6603 case SMB_SET_POSIX_LOCK:
6605 if (tran_call != TRANSACT2_SETFILEINFO) {
6606 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6607 return;
6609 status = smb_set_posix_lock(conn, req->inbuf,
6610 smb_len(req->inbuf) + 4,
6611 pdata, total_data, fsp);
6612 break;
6615 case SMB_POSIX_PATH_OPEN:
6617 if (tran_call != TRANSACT2_SETPATHINFO) {
6618 /* We must have a pathname for this. */
6619 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6620 return;
6623 status = smb_posix_open(conn, req,
6624 ppdata,
6625 total_data,
6626 fname,
6627 &sbuf,
6628 &data_return_size);
6629 break;
6632 case SMB_POSIX_PATH_UNLINK:
6634 if (tran_call != TRANSACT2_SETPATHINFO) {
6635 /* We must have a pathname for this. */
6636 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6637 return;
6640 status = smb_posix_unlink(conn, req,
6641 pdata,
6642 total_data,
6643 fname,
6644 &sbuf);
6645 break;
6648 default:
6649 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6650 return;
6654 if (!NT_STATUS_IS_OK(status)) {
6655 if (open_was_deferred(req->mid)) {
6656 /* We have re-scheduled this call. */
6657 return;
6659 if (blocking_lock_was_deferred(req->mid)) {
6660 /* We have re-scheduled this call. */
6661 return;
6663 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6664 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6665 ERRSRV, ERRbadpath);
6666 return;
6668 if (info_level == SMB_POSIX_PATH_OPEN) {
6669 reply_openerror(req, status);
6670 return;
6673 reply_nterror(req, status);
6674 return;
6677 SSVAL(params,0,0);
6678 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6679 max_data_bytes);
6681 return;
6684 /****************************************************************************
6685 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6686 ****************************************************************************/
6688 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6689 char **pparams, int total_params,
6690 char **ppdata, int total_data,
6691 unsigned int max_data_bytes)
6693 char *params = *pparams;
6694 char *pdata = *ppdata;
6695 char *directory = NULL;
6696 SMB_STRUCT_STAT sbuf;
6697 NTSTATUS status = NT_STATUS_OK;
6698 struct ea_list *ea_list = NULL;
6699 TALLOC_CTX *ctx = talloc_tos();
6701 if (!CAN_WRITE(conn)) {
6702 reply_doserror(req, ERRSRV, ERRaccess);
6703 return;
6706 if (total_params < 5) {
6707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6708 return;
6711 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
6712 total_params - 4, STR_TERMINATE,
6713 &status);
6714 if (!NT_STATUS_IS_OK(status)) {
6715 reply_nterror(req, status);
6716 return;
6719 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6721 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6722 if (!NT_STATUS_IS_OK(status)) {
6723 reply_nterror(req, status);
6724 return;
6727 status = check_name(conn, directory);
6728 if (!NT_STATUS_IS_OK(status)) {
6729 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6730 reply_nterror(req, status);
6731 return;
6734 /* Any data in this call is an EA list. */
6735 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6736 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6737 return;
6741 * OS/2 workplace shell seems to send SET_EA requests of "null"
6742 * length (4 bytes containing IVAL 4).
6743 * They seem to have no effect. Bug #3212. JRA.
6746 if (total_data != 4) {
6747 if (total_data < 10) {
6748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6749 return;
6752 if (IVAL(pdata,0) > total_data) {
6753 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6754 IVAL(pdata,0), (unsigned int)total_data));
6755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6756 return;
6759 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6760 total_data - 4);
6761 if (!ea_list) {
6762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6763 return;
6765 } else if (IVAL(pdata,0) != 4) {
6766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6767 return;
6770 status = create_directory(conn, directory);
6772 if (!NT_STATUS_IS_OK(status)) {
6773 reply_nterror(req, status);
6774 return;
6777 /* Try and set any given EA. */
6778 if (ea_list) {
6779 status = set_ea(conn, NULL, directory, ea_list);
6780 if (!NT_STATUS_IS_OK(status)) {
6781 reply_nterror(req, status);
6782 return;
6786 /* Realloc the parameter and data sizes */
6787 *pparams = (char *)SMB_REALLOC(*pparams,2);
6788 if(*pparams == NULL) {
6789 reply_nterror(req, NT_STATUS_NO_MEMORY);
6790 return;
6792 params = *pparams;
6794 SSVAL(params,0,0);
6796 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6798 return;
6801 /****************************************************************************
6802 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6803 We don't actually do this - we just send a null response.
6804 ****************************************************************************/
6806 static void call_trans2findnotifyfirst(connection_struct *conn,
6807 struct smb_request *req,
6808 char **pparams, int total_params,
6809 char **ppdata, int total_data,
6810 unsigned int max_data_bytes)
6812 static uint16 fnf_handle = 257;
6813 char *params = *pparams;
6814 uint16 info_level;
6816 if (total_params < 6) {
6817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6818 return;
6821 info_level = SVAL(params,4);
6822 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6824 switch (info_level) {
6825 case 1:
6826 case 2:
6827 break;
6828 default:
6829 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6830 return;
6833 /* Realloc the parameter and data sizes */
6834 *pparams = (char *)SMB_REALLOC(*pparams,6);
6835 if (*pparams == NULL) {
6836 reply_nterror(req, NT_STATUS_NO_MEMORY);
6837 return;
6839 params = *pparams;
6841 SSVAL(params,0,fnf_handle);
6842 SSVAL(params,2,0); /* No changes */
6843 SSVAL(params,4,0); /* No EA errors */
6845 fnf_handle++;
6847 if(fnf_handle == 0)
6848 fnf_handle = 257;
6850 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6852 return;
6855 /****************************************************************************
6856 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6857 changes). Currently this does nothing.
6858 ****************************************************************************/
6860 static void call_trans2findnotifynext(connection_struct *conn,
6861 struct smb_request *req,
6862 char **pparams, int total_params,
6863 char **ppdata, int total_data,
6864 unsigned int max_data_bytes)
6866 char *params = *pparams;
6868 DEBUG(3,("call_trans2findnotifynext\n"));
6870 /* Realloc the parameter and data sizes */
6871 *pparams = (char *)SMB_REALLOC(*pparams,4);
6872 if (*pparams == NULL) {
6873 reply_nterror(req, NT_STATUS_NO_MEMORY);
6874 return;
6876 params = *pparams;
6878 SSVAL(params,0,0); /* No changes */
6879 SSVAL(params,2,0); /* No EA errors */
6881 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6883 return;
6886 /****************************************************************************
6887 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6888 ****************************************************************************/
6890 static void call_trans2getdfsreferral(connection_struct *conn,
6891 struct smb_request *req,
6892 char **pparams, int total_params,
6893 char **ppdata, int total_data,
6894 unsigned int max_data_bytes)
6896 char *params = *pparams;
6897 char *pathname = NULL;
6898 int reply_size = 0;
6899 int max_referral_level;
6900 NTSTATUS status = NT_STATUS_OK;
6901 TALLOC_CTX *ctx = talloc_tos();
6903 DEBUG(10,("call_trans2getdfsreferral\n"));
6905 if (total_params < 3) {
6906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6907 return;
6910 max_referral_level = SVAL(params,0);
6912 if(!lp_host_msdfs()) {
6913 reply_doserror(req, ERRDOS, ERRbadfunc);
6914 return;
6917 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
6918 total_params - 2, STR_TERMINATE);
6919 if (!pathname) {
6920 reply_nterror(req, NT_STATUS_NOT_FOUND);
6921 return;
6923 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6924 ppdata,&status)) < 0) {
6925 reply_nterror(req, status);
6926 return;
6929 SSVAL(req->inbuf, smb_flg2,
6930 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6931 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6933 return;
6936 #define LMCAT_SPL 0x53
6937 #define LMFUNC_GETJOBID 0x60
6939 /****************************************************************************
6940 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6941 ****************************************************************************/
6943 static void call_trans2ioctl(connection_struct *conn,
6944 struct smb_request *req,
6945 char **pparams, int total_params,
6946 char **ppdata, int total_data,
6947 unsigned int max_data_bytes)
6949 char *pdata = *ppdata;
6950 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6952 /* check for an invalid fid before proceeding */
6954 if (!fsp) {
6955 reply_doserror(req, ERRDOS, ERRbadfid);
6956 return;
6959 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6960 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6961 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6962 if (*ppdata == NULL) {
6963 reply_nterror(req, NT_STATUS_NO_MEMORY);
6964 return;
6966 pdata = *ppdata;
6968 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6969 CAN ACCEPT THIS IN UNICODE. JRA. */
6971 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6972 srvstr_push(pdata, req->flags2, pdata + 2,
6973 global_myname(), 15,
6974 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6975 srvstr_push(pdata, req->flags2, pdata+18,
6976 lp_servicename(SNUM(conn)), 13,
6977 STR_ASCII|STR_TERMINATE); /* Service name */
6978 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6979 max_data_bytes);
6980 return;
6983 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6984 reply_doserror(req, ERRSRV, ERRerror);
6987 /****************************************************************************
6988 Reply to a SMBfindclose (stop trans2 directory search).
6989 ****************************************************************************/
6991 void reply_findclose(connection_struct *conn, struct smb_request *req)
6993 int dptr_num;
6995 START_PROFILE(SMBfindclose);
6997 if (req->wct < 1) {
6998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6999 END_PROFILE(SMBfindclose);
7000 return;
7003 dptr_num = SVALS(req->inbuf,smb_vwv0);
7005 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7007 dptr_close(&dptr_num);
7009 reply_outbuf(req, 0, 0);
7011 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7013 END_PROFILE(SMBfindclose);
7014 return;
7017 /****************************************************************************
7018 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7019 ****************************************************************************/
7021 void reply_findnclose(connection_struct *conn, struct smb_request *req)
7023 int dptr_num;
7025 START_PROFILE(SMBfindnclose);
7027 if (req->wct < 1) {
7028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7029 END_PROFILE(SMBfindnclose);
7030 return;
7033 dptr_num = SVAL(req->inbuf,smb_vwv0);
7035 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7037 /* We never give out valid handles for a
7038 findnotifyfirst - so any dptr_num is ok here.
7039 Just ignore it. */
7041 reply_outbuf(req, 0, 0);
7043 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7045 END_PROFILE(SMBfindnclose);
7046 return;
7049 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7050 struct trans_state *state)
7052 if (Protocol >= PROTOCOL_NT1) {
7053 req->flags2 |= 0x40; /* IS_LONG_NAME */
7054 SSVAL(req->inbuf,smb_flg2,req->flags2);
7057 if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
7058 if (state->call != TRANSACT2_QFSINFO &&
7059 state->call != TRANSACT2_SETFSINFO) {
7060 DEBUG(0,("handle_trans2: encryption required "
7061 "with call 0x%x\n",
7062 (unsigned int)state->call));
7063 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7064 return;
7068 /* Now we must call the relevant TRANS2 function */
7069 switch(state->call) {
7070 case TRANSACT2_OPEN:
7072 START_PROFILE(Trans2_open);
7073 call_trans2open(conn, req,
7074 &state->param, state->total_param,
7075 &state->data, state->total_data,
7076 state->max_data_return);
7077 END_PROFILE(Trans2_open);
7078 break;
7081 case TRANSACT2_FINDFIRST:
7083 START_PROFILE(Trans2_findfirst);
7084 call_trans2findfirst(conn, req,
7085 &state->param, state->total_param,
7086 &state->data, state->total_data,
7087 state->max_data_return);
7088 END_PROFILE(Trans2_findfirst);
7089 break;
7092 case TRANSACT2_FINDNEXT:
7094 START_PROFILE(Trans2_findnext);
7095 call_trans2findnext(conn, req,
7096 &state->param, state->total_param,
7097 &state->data, state->total_data,
7098 state->max_data_return);
7099 END_PROFILE(Trans2_findnext);
7100 break;
7103 case TRANSACT2_QFSINFO:
7105 START_PROFILE(Trans2_qfsinfo);
7106 call_trans2qfsinfo(conn, req,
7107 &state->param, state->total_param,
7108 &state->data, state->total_data,
7109 state->max_data_return);
7110 END_PROFILE(Trans2_qfsinfo);
7111 break;
7114 case TRANSACT2_SETFSINFO:
7116 START_PROFILE(Trans2_setfsinfo);
7117 call_trans2setfsinfo(conn, req,
7118 &state->param, state->total_param,
7119 &state->data, state->total_data,
7120 state->max_data_return);
7121 END_PROFILE(Trans2_setfsinfo);
7122 break;
7125 case TRANSACT2_QPATHINFO:
7126 case TRANSACT2_QFILEINFO:
7128 START_PROFILE(Trans2_qpathinfo);
7129 call_trans2qfilepathinfo(conn, req, state->call,
7130 &state->param, state->total_param,
7131 &state->data, state->total_data,
7132 state->max_data_return);
7133 END_PROFILE(Trans2_qpathinfo);
7134 break;
7137 case TRANSACT2_SETPATHINFO:
7138 case TRANSACT2_SETFILEINFO:
7140 START_PROFILE(Trans2_setpathinfo);
7141 call_trans2setfilepathinfo(conn, req, state->call,
7142 &state->param, state->total_param,
7143 &state->data, state->total_data,
7144 state->max_data_return);
7145 END_PROFILE(Trans2_setpathinfo);
7146 break;
7149 case TRANSACT2_FINDNOTIFYFIRST:
7151 START_PROFILE(Trans2_findnotifyfirst);
7152 call_trans2findnotifyfirst(conn, req,
7153 &state->param, state->total_param,
7154 &state->data, state->total_data,
7155 state->max_data_return);
7156 END_PROFILE(Trans2_findnotifyfirst);
7157 break;
7160 case TRANSACT2_FINDNOTIFYNEXT:
7162 START_PROFILE(Trans2_findnotifynext);
7163 call_trans2findnotifynext(conn, req,
7164 &state->param, state->total_param,
7165 &state->data, state->total_data,
7166 state->max_data_return);
7167 END_PROFILE(Trans2_findnotifynext);
7168 break;
7171 case TRANSACT2_MKDIR:
7173 START_PROFILE(Trans2_mkdir);
7174 call_trans2mkdir(conn, req,
7175 &state->param, state->total_param,
7176 &state->data, state->total_data,
7177 state->max_data_return);
7178 END_PROFILE(Trans2_mkdir);
7179 break;
7182 case TRANSACT2_GET_DFS_REFERRAL:
7184 START_PROFILE(Trans2_get_dfs_referral);
7185 call_trans2getdfsreferral(conn, req,
7186 &state->param, state->total_param,
7187 &state->data, state->total_data,
7188 state->max_data_return);
7189 END_PROFILE(Trans2_get_dfs_referral);
7190 break;
7193 case TRANSACT2_IOCTL:
7195 START_PROFILE(Trans2_ioctl);
7196 call_trans2ioctl(conn, req,
7197 &state->param, state->total_param,
7198 &state->data, state->total_data,
7199 state->max_data_return);
7200 END_PROFILE(Trans2_ioctl);
7201 break;
7204 default:
7205 /* Error in request */
7206 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7207 reply_doserror(req, ERRSRV,ERRerror);
7211 /****************************************************************************
7212 Reply to a SMBtrans2.
7213 ****************************************************************************/
7215 void reply_trans2(connection_struct *conn, struct smb_request *req)
7217 unsigned int dsoff;
7218 unsigned int dscnt;
7219 unsigned int psoff;
7220 unsigned int pscnt;
7221 unsigned int tran_call;
7222 int size;
7223 struct trans_state *state;
7224 NTSTATUS result;
7226 START_PROFILE(SMBtrans2);
7228 if (req->wct < 14) {
7229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7230 END_PROFILE(SMBtrans2);
7231 return;
7234 dsoff = SVAL(req->inbuf, smb_dsoff);
7235 dscnt = SVAL(req->inbuf, smb_dscnt);
7236 psoff = SVAL(req->inbuf, smb_psoff);
7237 pscnt = SVAL(req->inbuf, smb_pscnt);
7238 tran_call = SVAL(req->inbuf, smb_setup0);
7239 size = smb_len(req->inbuf) + 4;
7241 result = allow_new_trans(conn->pending_trans, req->mid);
7242 if (!NT_STATUS_IS_OK(result)) {
7243 DEBUG(2, ("Got invalid trans2 request: %s\n",
7244 nt_errstr(result)));
7245 reply_nterror(req, result);
7246 END_PROFILE(SMBtrans2);
7247 return;
7250 if (IS_IPC(conn)) {
7251 switch (tran_call) {
7252 /* List the allowed trans2 calls on IPC$ */
7253 case TRANSACT2_OPEN:
7254 case TRANSACT2_GET_DFS_REFERRAL:
7255 case TRANSACT2_QFILEINFO:
7256 case TRANSACT2_QFSINFO:
7257 case TRANSACT2_SETFSINFO:
7258 break;
7259 default:
7260 reply_doserror(req, ERRSRV, ERRaccess);
7261 END_PROFILE(SMBtrans2);
7262 return;
7266 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7267 DEBUG(0, ("talloc failed\n"));
7268 reply_nterror(req, NT_STATUS_NO_MEMORY);
7269 END_PROFILE(SMBtrans2);
7270 return;
7273 state->cmd = SMBtrans2;
7275 state->mid = req->mid;
7276 state->vuid = req->vuid;
7277 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7278 state->setup = NULL;
7279 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7280 state->param = NULL;
7281 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7282 state->data = NULL;
7283 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7284 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7285 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7286 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7287 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7289 state->call = tran_call;
7291 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7292 is so as a sanity check */
7293 if (state->setup_count != 1) {
7295 * Need to have rc=0 for ioctl to get job id for OS/2.
7296 * Network printing will fail if function is not successful.
7297 * Similar function in reply.c will be used if protocol
7298 * is LANMAN1.0 instead of LM1.2X002.
7299 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7300 * outbuf doesn't have to be set(only job id is used).
7302 if ( (state->setup_count == 4)
7303 && (tran_call == TRANSACT2_IOCTL)
7304 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7305 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7306 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7307 } else {
7308 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7309 DEBUG(2,("Transaction is %d\n",tran_call));
7310 TALLOC_FREE(state);
7311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7312 END_PROFILE(SMBtrans2);
7313 return;
7317 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7318 goto bad_param;
7320 if (state->total_data) {
7321 /* Can't use talloc here, the core routines do realloc on the
7322 * params and data. */
7323 state->data = (char *)SMB_MALLOC(state->total_data);
7324 if (state->data == NULL) {
7325 DEBUG(0,("reply_trans2: data malloc fail for %u "
7326 "bytes !\n", (unsigned int)state->total_data));
7327 TALLOC_FREE(state);
7328 reply_nterror(req, NT_STATUS_NO_MEMORY);
7329 END_PROFILE(SMBtrans2);
7330 return;
7332 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7333 goto bad_param;
7334 if ((smb_base(req->inbuf)+dsoff+dscnt
7335 > (char *)req->inbuf + size) ||
7336 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7337 goto bad_param;
7339 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7342 if (state->total_param) {
7343 /* Can't use talloc here, the core routines do realloc on the
7344 * params and data. */
7345 state->param = (char *)SMB_MALLOC(state->total_param);
7346 if (state->param == NULL) {
7347 DEBUG(0,("reply_trans: param malloc fail for %u "
7348 "bytes !\n", (unsigned int)state->total_param));
7349 SAFE_FREE(state->data);
7350 TALLOC_FREE(state);
7351 reply_nterror(req, NT_STATUS_NO_MEMORY);
7352 END_PROFILE(SMBtrans2);
7353 return;
7355 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7356 goto bad_param;
7357 if ((smb_base(req->inbuf)+psoff+pscnt
7358 > (char *)req->inbuf + size) ||
7359 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7360 goto bad_param;
7362 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7365 state->received_data = dscnt;
7366 state->received_param = pscnt;
7368 if ((state->received_param == state->total_param) &&
7369 (state->received_data == state->total_data)) {
7371 handle_trans2(conn, req, state);
7373 SAFE_FREE(state->data);
7374 SAFE_FREE(state->param);
7375 TALLOC_FREE(state);
7376 END_PROFILE(SMBtrans2);
7377 return;
7380 DLIST_ADD(conn->pending_trans, state);
7382 /* We need to send an interim response then receive the rest
7383 of the parameter/data bytes */
7384 reply_outbuf(req, 0, 0);
7385 show_msg((char *)req->outbuf);
7386 END_PROFILE(SMBtrans2);
7387 return;
7389 bad_param:
7391 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7392 SAFE_FREE(state->data);
7393 SAFE_FREE(state->param);
7394 TALLOC_FREE(state);
7395 END_PROFILE(SMBtrans2);
7396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7400 /****************************************************************************
7401 Reply to a SMBtranss2
7402 ****************************************************************************/
7404 void reply_transs2(connection_struct *conn, struct smb_request *req)
7406 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7407 struct trans_state *state;
7408 int size;
7410 START_PROFILE(SMBtranss2);
7412 show_msg((char *)req->inbuf);
7414 if (req->wct < 8) {
7415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7416 END_PROFILE(SMBtranss2);
7417 return;
7420 size = smb_len(req->inbuf)+4;
7422 for (state = conn->pending_trans; state != NULL;
7423 state = state->next) {
7424 if (state->mid == req->mid) {
7425 break;
7429 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7430 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7431 END_PROFILE(SMBtranss2);
7432 return;
7435 /* Revise state->total_param and state->total_data in case they have
7436 changed downwards */
7438 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7439 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7440 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7441 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7443 pcnt = SVAL(req->inbuf, smb_spscnt);
7444 poff = SVAL(req->inbuf, smb_spsoff);
7445 pdisp = SVAL(req->inbuf, smb_spsdisp);
7447 dcnt = SVAL(req->inbuf, smb_sdscnt);
7448 doff = SVAL(req->inbuf, smb_sdsoff);
7449 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7451 state->received_param += pcnt;
7452 state->received_data += dcnt;
7454 if ((state->received_data > state->total_data) ||
7455 (state->received_param > state->total_param))
7456 goto bad_param;
7458 if (pcnt) {
7459 if (pdisp+pcnt > state->total_param)
7460 goto bad_param;
7461 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7462 goto bad_param;
7463 if (pdisp > state->total_param)
7464 goto bad_param;
7465 if ((smb_base(req->inbuf) + poff + pcnt
7466 > (char *)req->inbuf + size) ||
7467 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7468 goto bad_param;
7469 if (state->param + pdisp < state->param)
7470 goto bad_param;
7472 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7473 pcnt);
7476 if (dcnt) {
7477 if (ddisp+dcnt > state->total_data)
7478 goto bad_param;
7479 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7480 goto bad_param;
7481 if (ddisp > state->total_data)
7482 goto bad_param;
7483 if ((smb_base(req->inbuf) + doff + dcnt
7484 > (char *)req->inbuf + size) ||
7485 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7486 goto bad_param;
7487 if (state->data + ddisp < state->data)
7488 goto bad_param;
7490 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7491 dcnt);
7494 if ((state->received_param < state->total_param) ||
7495 (state->received_data < state->total_data)) {
7496 END_PROFILE(SMBtranss2);
7497 return;
7501 * construct_reply_common will copy smb_com from inbuf to
7502 * outbuf. SMBtranss2 is wrong here.
7504 SCVAL(req->inbuf,smb_com,SMBtrans2);
7506 handle_trans2(conn, req, state);
7508 DLIST_REMOVE(conn->pending_trans, state);
7509 SAFE_FREE(state->data);
7510 SAFE_FREE(state->param);
7511 TALLOC_FREE(state);
7513 END_PROFILE(SMBtranss2);
7514 return;
7516 bad_param:
7518 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7519 DLIST_REMOVE(conn->pending_trans, state);
7520 SAFE_FREE(state->data);
7521 SAFE_FREE(state->param);
7522 TALLOC_FREE(state);
7523 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7524 END_PROFILE(SMBtranss2);
7525 return;