Make get_ea_value public
[Samba.git] / source / smbd / trans2.c
blob12b0f20879953a5b267e5deca172d747baf1f9b0
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 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
118 files_struct *fsp, const char *fname,
119 const char *ea_name, struct ea_struct *pea)
121 /* Get the value of this xattr. Max size is 64k. */
122 size_t attr_size = 256;
123 char *val = NULL;
124 ssize_t sizeret;
126 again:
128 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
129 if (!val) {
130 return NT_STATUS_NO_MEMORY;
133 if (fsp && fsp->fh->fd != -1) {
134 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
135 } else {
136 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
139 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
140 attr_size = 65536;
141 goto again;
144 if (sizeret == -1) {
145 return map_nt_error_from_unix(errno);
148 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
149 dump_data(10, (uint8 *)val, sizeret);
151 pea->flags = 0;
152 if (strnequal(ea_name, "user.", 5)) {
153 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
154 } else {
155 pea->name = talloc_strdup(mem_ctx, ea_name);
157 if (pea->name == NULL) {
158 TALLOC_FREE(val);
159 return NT_STATUS_NO_MEMORY;
161 pea->value.data = (unsigned char *)val;
162 pea->value.length = (size_t)sizeret;
163 return NT_STATUS_OK;
166 /****************************************************************************
167 Return a linked list of the total EA's. Plus the total size
168 ****************************************************************************/
170 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
171 const char *fname, size_t *pea_total_len)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size = 1024;
175 char *ea_namelist;
176 char *p;
177 ssize_t sizeret;
178 int i;
179 struct ea_list *ea_list_head = NULL;
181 *pea_total_len = 0;
183 if (!lp_ea_support(SNUM(conn))) {
184 return NULL;
187 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
188 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
190 if (!ea_namelist) {
191 return NULL;
194 if (fsp && fsp->fh->fd != -1) {
195 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist, ea_namelist_size);
196 } else {
197 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
200 if (sizeret == -1 && errno == ERANGE) {
201 ea_namelist_size *= 2;
202 } else {
203 break;
207 if (sizeret == -1)
208 return NULL;
210 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
212 if (sizeret) {
213 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
214 struct ea_list *listp;
216 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
217 continue;
219 listp = TALLOC_P(mem_ctx, struct ea_list);
220 if (!listp)
221 return NULL;
223 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
224 fname, p,
225 &listp->ea))) {
226 return NULL;
230 fstring dos_ea_name;
231 push_ascii_fstring(dos_ea_name, listp->ea.name);
232 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
233 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
234 (unsigned int)*pea_total_len, dos_ea_name,
235 (unsigned int)listp->ea.value.length ));
237 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
239 /* Add on 4 for total length. */
240 if (*pea_total_len) {
241 *pea_total_len += 4;
245 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
246 return ea_list_head;
249 /****************************************************************************
250 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
251 that was filled.
252 ****************************************************************************/
254 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
255 connection_struct *conn, struct ea_list *ea_list)
257 unsigned int ret_data_size = 4;
258 char *p = pdata;
260 SMB_ASSERT(total_data_size >= 4);
262 if (!lp_ea_support(SNUM(conn))) {
263 SIVAL(pdata,4,0);
264 return 4;
267 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
268 size_t dos_namelen;
269 fstring dos_ea_name;
270 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
271 dos_namelen = strlen(dos_ea_name);
272 if (dos_namelen > 255 || dos_namelen == 0) {
273 break;
275 if (ea_list->ea.value.length > 65535) {
276 break;
278 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
279 break;
282 /* We know we have room. */
283 SCVAL(p,0,ea_list->ea.flags);
284 SCVAL(p,1,dos_namelen);
285 SSVAL(p,2,ea_list->ea.value.length);
286 fstrcpy(p+4, dos_ea_name);
287 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
289 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
290 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
293 ret_data_size = PTR_DIFF(p, pdata);
294 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
295 SIVAL(pdata,0,ret_data_size);
296 return ret_data_size;
299 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
301 size_t total_ea_len = 0;
302 TALLOC_CTX *mem_ctx = NULL;
304 if (!lp_ea_support(SNUM(conn))) {
305 return 0;
307 mem_ctx = talloc_tos();
308 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
309 return total_ea_len;
312 /****************************************************************************
313 Ensure the EA name is case insensitive by matching any existing EA name.
314 ****************************************************************************/
316 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
318 size_t total_ea_len;
319 TALLOC_CTX *mem_ctx = talloc_tos();
320 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
322 for (; ea_list; ea_list = ea_list->next) {
323 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
324 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
325 &unix_ea_name[5], ea_list->ea.name));
326 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
327 break;
332 /****************************************************************************
333 Set or delete an extended attribute.
334 ****************************************************************************/
336 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
338 if (!lp_ea_support(SNUM(conn))) {
339 return NT_STATUS_EAS_NOT_SUPPORTED;
342 for (;ea_list; ea_list = ea_list->next) {
343 int ret;
344 fstring unix_ea_name;
346 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
347 fstrcat(unix_ea_name, ea_list->ea.name);
349 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
351 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
353 if (samba_private_attr_name(unix_ea_name)) {
354 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
355 return NT_STATUS_ACCESS_DENIED;
358 if (ea_list->ea.value.length == 0) {
359 /* Remove the attribute. */
360 if (fsp && (fsp->fh->fd != -1)) {
361 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
362 unix_ea_name, fsp->fsp_name));
363 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
364 } else {
365 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
366 unix_ea_name, fname));
367 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
369 #ifdef ENOATTR
370 /* Removing a non existent attribute always succeeds. */
371 if (ret == -1 && errno == ENOATTR) {
372 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
373 unix_ea_name));
374 ret = 0;
376 #endif
377 } else {
378 if (fsp && (fsp->fh->fd != -1)) {
379 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
380 unix_ea_name, fsp->fsp_name));
381 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
382 ea_list->ea.value.data, ea_list->ea.value.length, 0);
383 } else {
384 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
385 unix_ea_name, fname));
386 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
387 ea_list->ea.value.data, ea_list->ea.value.length, 0);
391 if (ret == -1) {
392 #ifdef ENOTSUP
393 if (errno == ENOTSUP) {
394 return NT_STATUS_EAS_NOT_SUPPORTED;
396 #endif
397 return map_nt_error_from_unix(errno);
401 return NT_STATUS_OK;
403 /****************************************************************************
404 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
405 ****************************************************************************/
407 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
409 struct ea_list *ea_list_head = NULL;
410 size_t offset = 0;
412 while (offset + 2 < data_size) {
413 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
414 unsigned int namelen = CVAL(pdata,offset);
416 offset++; /* Go past the namelen byte. */
418 /* integer wrap paranioa. */
419 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
420 (offset > data_size) || (namelen > data_size) ||
421 (offset + namelen >= data_size)) {
422 break;
424 /* Ensure the name is null terminated. */
425 if (pdata[offset + namelen] != '\0') {
426 return NULL;
428 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
429 if (!eal->ea.name) {
430 return NULL;
433 offset += (namelen + 1); /* Go past the name + terminating zero. */
434 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
435 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
438 return ea_list_head;
441 /****************************************************************************
442 Read one EA list entry from the buffer.
443 ****************************************************************************/
445 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
447 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
448 uint16 val_len;
449 unsigned int namelen;
451 if (!eal) {
452 return NULL;
455 if (data_size < 6) {
456 return NULL;
459 eal->ea.flags = CVAL(pdata,0);
460 namelen = CVAL(pdata,1);
461 val_len = SVAL(pdata,2);
463 if (4 + namelen + 1 + val_len > data_size) {
464 return NULL;
467 /* Ensure the name is null terminated. */
468 if (pdata[namelen + 4] != '\0') {
469 return NULL;
471 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
472 if (!eal->ea.name) {
473 return NULL;
476 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
477 if (!eal->ea.value.data) {
478 return NULL;
481 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
483 /* Ensure we're null terminated just in case we print the value. */
484 eal->ea.value.data[val_len] = '\0';
485 /* But don't count the null. */
486 eal->ea.value.length--;
488 if (pbytes_used) {
489 *pbytes_used = 4 + namelen + 1 + val_len;
492 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
493 dump_data(10, eal->ea.value.data, eal->ea.value.length);
495 return eal;
498 /****************************************************************************
499 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
500 ****************************************************************************/
502 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
504 struct ea_list *ea_list_head = NULL;
505 size_t offset = 0;
506 size_t bytes_used = 0;
508 while (offset < data_size) {
509 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
511 if (!eal) {
512 return NULL;
515 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
516 offset += bytes_used;
519 return ea_list_head;
522 /****************************************************************************
523 Count the total EA size needed.
524 ****************************************************************************/
526 static size_t ea_list_size(struct ea_list *ealist)
528 fstring dos_ea_name;
529 struct ea_list *listp;
530 size_t ret = 0;
532 for (listp = ealist; listp; listp = listp->next) {
533 push_ascii_fstring(dos_ea_name, listp->ea.name);
534 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
536 /* Add on 4 for total length. */
537 if (ret) {
538 ret += 4;
541 return ret;
544 /****************************************************************************
545 Return a union of EA's from a file list and a list of names.
546 The TALLOC context for the two lists *MUST* be identical as we steal
547 memory from one list to add to another. JRA.
548 ****************************************************************************/
550 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
552 struct ea_list *nlistp, *flistp;
554 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
555 for (flistp = file_list; flistp; flistp = flistp->next) {
556 if (strequal(nlistp->ea.name, flistp->ea.name)) {
557 break;
561 if (flistp) {
562 /* Copy the data from this entry. */
563 nlistp->ea.flags = flistp->ea.flags;
564 nlistp->ea.value = flistp->ea.value;
565 } else {
566 /* Null entry. */
567 nlistp->ea.flags = 0;
568 ZERO_STRUCT(nlistp->ea.value);
572 *total_ea_len = ea_list_size(name_list);
573 return name_list;
576 /****************************************************************************
577 Send the required number of replies back.
578 We assume all fields other than the data fields are
579 set correctly for the type of call.
580 HACK ! Always assumes smb_setup field is zero.
581 ****************************************************************************/
583 void send_trans2_replies(connection_struct *conn,
584 struct smb_request *req,
585 const char *params,
586 int paramsize,
587 const char *pdata,
588 int datasize,
589 int max_data_bytes)
591 /* As we are using a protocol > LANMAN1 then the max_send
592 variable must have been set in the sessetupX call.
593 This takes precedence over the max_xmit field in the
594 global struct. These different max_xmit variables should
595 be merged as this is now too confusing */
597 int data_to_send = datasize;
598 int params_to_send = paramsize;
599 int useable_space;
600 const char *pp = params;
601 const char *pd = pdata;
602 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
603 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
604 int data_alignment_offset = 0;
605 bool overflow = False;
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
610 for OS/2. */
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 overflow = True;
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
622 reply_outbuf(req, 10, 0);
623 show_msg((char *)req->outbuf);
624 return;
627 /* When sending params and data ensure that both are nicely aligned */
628 /* Only do this alignment when there is also data to send - else
629 can cause NT redirector problems. */
631 if (((params_to_send % 4) != 0) && (data_to_send != 0))
632 data_alignment_offset = 4 - (params_to_send % 4);
634 /* Space is bufsize minus Netbios over TCP header minus SMB header */
635 /* The alignment_offset is to align the param bytes on an even byte
636 boundary. NT 4.0 Beta needs this to work correctly. */
638 useable_space = max_send - (smb_size
639 + 2 * 10 /* wct */
640 + alignment_offset
641 + data_alignment_offset);
643 /* useable_space can never be more than max_send minus the alignment offset. */
645 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
647 while (params_to_send || data_to_send) {
648 /* Calculate whether we will totally or partially fill this packet */
650 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
652 /* We can never send more than useable_space */
654 * Note that 'useable_space' does not include the alignment offsets,
655 * but we must include the alignment offsets in the calculation of
656 * the length of the data we send over the wire, as the alignment offsets
657 * are sent here. Fix from Marc_Jacobsen@hp.com.
660 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
662 reply_outbuf(req, 10, total_sent_thistime);
664 /* Set total params and data to be sent */
665 SSVAL(req->outbuf,smb_tprcnt,paramsize);
666 SSVAL(req->outbuf,smb_tdrcnt,datasize);
668 /* Calculate how many parameters and data we can fit into
669 * this packet. Parameters get precedence
672 params_sent_thistime = MIN(params_to_send,useable_space);
673 data_sent_thistime = useable_space - params_sent_thistime;
674 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
676 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
678 /* smb_proff is the offset from the start of the SMB header to the
679 parameter bytes, however the first 4 bytes of outbuf are
680 the Netbios over TCP header. Thus use smb_base() to subtract
681 them from the calculation */
683 SSVAL(req->outbuf,smb_proff,
684 ((smb_buf(req->outbuf)+alignment_offset)
685 - smb_base(req->outbuf)));
687 if(params_sent_thistime == 0)
688 SSVAL(req->outbuf,smb_prdisp,0);
689 else
690 /* Absolute displacement of param bytes sent in this packet */
691 SSVAL(req->outbuf,smb_prdisp,pp - params);
693 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
694 if(data_sent_thistime == 0) {
695 SSVAL(req->outbuf,smb_droff,0);
696 SSVAL(req->outbuf,smb_drdisp, 0);
697 } else {
698 /* The offset of the data bytes is the offset of the
699 parameter bytes plus the number of parameters being sent this time */
700 SSVAL(req->outbuf, smb_droff,
701 ((smb_buf(req->outbuf)+alignment_offset)
702 - smb_base(req->outbuf))
703 + params_sent_thistime + data_alignment_offset);
704 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
707 /* Initialize the padding for alignment */
709 if (alignment_offset != 0) {
710 memset(smb_buf(req->outbuf), 0, alignment_offset);
713 /* Copy the param bytes into the packet */
715 if(params_sent_thistime) {
716 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
717 params_sent_thistime);
720 /* Copy in the data bytes */
721 if(data_sent_thistime) {
722 if (data_alignment_offset != 0) {
723 memset((smb_buf(req->outbuf)+alignment_offset+
724 params_sent_thistime), 0,
725 data_alignment_offset);
727 memcpy(smb_buf(req->outbuf)+alignment_offset
728 +params_sent_thistime+data_alignment_offset,
729 pd,data_sent_thistime);
732 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
733 params_sent_thistime, data_sent_thistime, useable_space));
734 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
735 params_to_send, data_to_send, paramsize, datasize));
737 if (overflow) {
738 error_packet_set((char *)req->outbuf,
739 ERRDOS,ERRbufferoverflow,
740 STATUS_BUFFER_OVERFLOW,
741 __LINE__,__FILE__);
744 /* Send the packet */
745 show_msg((char *)req->outbuf);
746 if (!srv_send_smb(smbd_server_fd(),
747 (char *)req->outbuf,
748 IS_CONN_ENCRYPTED(conn)))
749 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
751 TALLOC_FREE(req->outbuf);
753 pp += params_sent_thistime;
754 pd += data_sent_thistime;
756 params_to_send -= params_sent_thistime;
757 data_to_send -= data_sent_thistime;
759 /* Sanity check */
760 if(params_to_send < 0 || data_to_send < 0) {
761 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
762 params_to_send, data_to_send));
763 return;
767 return;
770 /****************************************************************************
771 Reply to a TRANSACT2_OPEN.
772 ****************************************************************************/
774 static void call_trans2open(connection_struct *conn,
775 struct smb_request *req,
776 char **pparams, int total_params,
777 char **ppdata, int total_data,
778 unsigned int max_data_bytes)
780 char *params = *pparams;
781 char *pdata = *ppdata;
782 int deny_mode;
783 int32 open_attr;
784 bool oplock_request;
785 #if 0
786 bool return_additional_info;
787 int16 open_sattr;
788 time_t open_time;
789 #endif
790 int open_ofun;
791 uint32 open_size;
792 char *pname;
793 char *fname = NULL;
794 SMB_OFF_T size=0;
795 int fattr=0,mtime=0;
796 SMB_INO_T inode = 0;
797 SMB_STRUCT_STAT sbuf;
798 int smb_action = 0;
799 files_struct *fsp;
800 struct ea_list *ea_list = NULL;
801 uint16 flags = 0;
802 NTSTATUS status;
803 uint32 access_mask;
804 uint32 share_mode;
805 uint32 create_disposition;
806 uint32 create_options = 0;
807 TALLOC_CTX *ctx = talloc_tos();
810 * Ensure we have enough parameters to perform the operation.
813 if (total_params < 29) {
814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
815 return;
818 flags = SVAL(params, 0);
819 deny_mode = SVAL(params, 2);
820 open_attr = SVAL(params,6);
821 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
822 if (oplock_request) {
823 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
826 #if 0
827 return_additional_info = BITSETW(params,0);
828 open_sattr = SVAL(params, 4);
829 open_time = make_unix_date3(params+8);
830 #endif
831 open_ofun = SVAL(params,12);
832 open_size = IVAL(params,14);
833 pname = &params[28];
835 if (IS_IPC(conn)) {
836 reply_doserror(req, ERRSRV, ERRaccess);
837 return;
840 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
841 total_params - 28, STR_TERMINATE,
842 &status);
843 if (!NT_STATUS_IS_OK(status)) {
844 reply_nterror(req, status);
845 return;
848 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
849 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
850 (unsigned int)open_ofun, open_size));
852 if (open_ofun == 0) {
853 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
854 return;
857 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
858 &access_mask,
859 &share_mode,
860 &create_disposition,
861 &create_options)) {
862 reply_doserror(req, ERRDOS, ERRbadaccess);
863 return;
866 /* Any data in this call is an EA list. */
867 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
868 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
869 return;
872 if (total_data != 4) {
873 if (total_data < 10) {
874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
875 return;
878 if (IVAL(pdata,0) > total_data) {
879 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
880 IVAL(pdata,0), (unsigned int)total_data));
881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
882 return;
885 ea_list = read_ea_list(talloc_tos(), pdata + 4,
886 total_data - 4);
887 if (!ea_list) {
888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889 return;
891 } else if (IVAL(pdata,0) != 4) {
892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
893 return;
896 status = create_file(conn, /* conn */
897 req, /* req */
898 0, /* root_dir_fid */
899 fname, /* fname */
900 access_mask, /* access_mask */
901 share_mode, /* share_access */
902 create_disposition, /* create_disposition*/
903 create_options, /* create_options */
904 open_attr, /* file_attributes */
905 oplock_request, /* oplock_request */
906 open_size, /* allocation_size */
907 NULL, /* sd */
908 ea_list, /* ea_list */
909 &fsp, /* result */
910 &smb_action, /* pinfo */
911 &sbuf); /* psbuf */
913 if (!NT_STATUS_IS_OK(status)) {
914 if (open_was_deferred(req->mid)) {
915 /* We have re-scheduled this call. */
916 return;
918 reply_openerror(req, status);
919 return;
922 size = get_file_size(sbuf);
923 fattr = dos_mode(conn,fname,&sbuf);
924 mtime = sbuf.st_mtime;
925 inode = sbuf.st_ino;
926 if (fattr & aDIR) {
927 close_file(fsp,ERROR_CLOSE);
928 reply_doserror(req, ERRDOS,ERRnoaccess);
929 return;
932 /* Realloc the size of parameters and data we will return */
933 *pparams = (char *)SMB_REALLOC(*pparams, 30);
934 if(*pparams == NULL ) {
935 reply_nterror(req, NT_STATUS_NO_MEMORY);
936 return;
938 params = *pparams;
940 SSVAL(params,0,fsp->fnum);
941 SSVAL(params,2,fattr);
942 srv_put_dos_date2(params,4, mtime);
943 SIVAL(params,8, (uint32)size);
944 SSVAL(params,12,deny_mode);
945 SSVAL(params,14,0); /* open_type - file or directory. */
946 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
948 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
949 smb_action |= EXTENDED_OPLOCK_GRANTED;
952 SSVAL(params,18,smb_action);
955 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
957 SIVAL(params,20,inode);
958 SSVAL(params,24,0); /* Padding. */
959 if (flags & 8) {
960 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
961 SIVAL(params, 26, ea_size);
962 } else {
963 SIVAL(params, 26, 0);
966 /* Send the required number of replies */
967 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
970 /*********************************************************
971 Routine to check if a given string matches exactly.
972 as a special case a mask of "." does NOT match. That
973 is required for correct wildcard semantics
974 Case can be significant or not.
975 **********************************************************/
977 static bool exact_match(connection_struct *conn,
978 const char *str,
979 const char *mask)
981 if (mask[0] == '.' && mask[1] == 0)
982 return False;
983 if (conn->case_sensitive)
984 return strcmp(str,mask)==0;
985 if (StrCaseCmp(str,mask) != 0) {
986 return False;
988 if (dptr_has_wild(conn->dirptr)) {
989 return False;
991 return True;
994 /****************************************************************************
995 Return the filetype for UNIX extensions.
996 ****************************************************************************/
998 static uint32 unix_filetype(mode_t mode)
1000 if(S_ISREG(mode))
1001 return UNIX_TYPE_FILE;
1002 else if(S_ISDIR(mode))
1003 return UNIX_TYPE_DIR;
1004 #ifdef S_ISLNK
1005 else if(S_ISLNK(mode))
1006 return UNIX_TYPE_SYMLINK;
1007 #endif
1008 #ifdef S_ISCHR
1009 else if(S_ISCHR(mode))
1010 return UNIX_TYPE_CHARDEV;
1011 #endif
1012 #ifdef S_ISBLK
1013 else if(S_ISBLK(mode))
1014 return UNIX_TYPE_BLKDEV;
1015 #endif
1016 #ifdef S_ISFIFO
1017 else if(S_ISFIFO(mode))
1018 return UNIX_TYPE_FIFO;
1019 #endif
1020 #ifdef S_ISSOCK
1021 else if(S_ISSOCK(mode))
1022 return UNIX_TYPE_SOCKET;
1023 #endif
1025 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1026 return UNIX_TYPE_UNKNOWN;
1029 /****************************************************************************
1030 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1031 ****************************************************************************/
1033 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1035 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1036 SMB_STRUCT_STAT *psbuf,
1037 uint32 perms,
1038 enum perm_type ptype,
1039 mode_t *ret_perms)
1041 mode_t ret = 0;
1043 if (perms == SMB_MODE_NO_CHANGE) {
1044 if (!VALID_STAT(*psbuf)) {
1045 return NT_STATUS_INVALID_PARAMETER;
1046 } else {
1047 *ret_perms = psbuf->st_mode;
1048 return NT_STATUS_OK;
1052 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1053 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1054 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1055 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1056 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1057 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1058 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1059 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1060 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1061 #ifdef S_ISVTX
1062 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1063 #endif
1064 #ifdef S_ISGID
1065 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1066 #endif
1067 #ifdef S_ISUID
1068 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1069 #endif
1071 switch (ptype) {
1072 case PERM_NEW_FILE:
1073 /* Apply mode mask */
1074 ret &= lp_create_mask(SNUM(conn));
1075 /* Add in force bits */
1076 ret |= lp_force_create_mode(SNUM(conn));
1077 break;
1078 case PERM_NEW_DIR:
1079 ret &= lp_dir_mask(SNUM(conn));
1080 /* Add in force bits */
1081 ret |= lp_force_dir_mode(SNUM(conn));
1082 break;
1083 case PERM_EXISTING_FILE:
1084 /* Apply mode mask */
1085 ret &= lp_security_mask(SNUM(conn));
1086 /* Add in force bits */
1087 ret |= lp_force_security_mode(SNUM(conn));
1088 break;
1089 case PERM_EXISTING_DIR:
1090 /* Apply mode mask */
1091 ret &= lp_dir_security_mask(SNUM(conn));
1092 /* Add in force bits */
1093 ret |= lp_force_dir_security_mode(SNUM(conn));
1094 break;
1097 *ret_perms = ret;
1098 return NT_STATUS_OK;
1101 /****************************************************************************
1102 Get a level dependent lanman2 dir entry.
1103 ****************************************************************************/
1105 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1106 connection_struct *conn,
1107 uint16 flags2,
1108 const char *path_mask,
1109 uint32 dirtype,
1110 int info_level,
1111 int requires_resume_key,
1112 bool dont_descend,
1113 char **ppdata,
1114 char *base_data,
1115 char *end_data,
1116 int space_remaining,
1117 bool *out_of_space,
1118 bool *got_exact_match,
1119 int *last_entry_off,
1120 struct ea_list *name_list)
1122 const char *dname;
1123 bool found = False;
1124 SMB_STRUCT_STAT sbuf;
1125 const char *mask = NULL;
1126 char *pathreal = NULL;
1127 const char *fname = NULL;
1128 char *p, *q, *pdata = *ppdata;
1129 uint32 reskey=0;
1130 long prev_dirpos=0;
1131 uint32 mode=0;
1132 SMB_OFF_T file_size = 0;
1133 SMB_BIG_UINT allocation_size = 0;
1134 uint32 len;
1135 struct timespec mdate_ts, adate_ts, create_date_ts;
1136 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1137 char *nameptr;
1138 char *last_entry_ptr;
1139 bool was_8_3;
1140 uint32 nt_extmode; /* Used for NT connections instead of mode */
1141 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1142 bool check_mangled_names = lp_manglednames(conn->params);
1143 char mangled_name[13]; /* mangled 8.3 name. */
1145 *out_of_space = False;
1146 *got_exact_match = False;
1148 ZERO_STRUCT(mdate_ts);
1149 ZERO_STRUCT(adate_ts);
1150 ZERO_STRUCT(create_date_ts);
1152 if (!conn->dirptr) {
1153 return(False);
1156 p = strrchr_m(path_mask,'/');
1157 if(p != NULL) {
1158 if(p[1] == '\0') {
1159 mask = talloc_strdup(ctx,"*.*");
1160 } else {
1161 mask = p+1;
1163 } else {
1164 mask = path_mask;
1167 while (!found) {
1168 bool got_match;
1169 bool ms_dfs_link = False;
1171 /* Needed if we run out of space */
1172 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1173 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1176 * Due to bugs in NT client redirectors we are not using
1177 * resume keys any more - set them to zero.
1178 * Check out the related comments in findfirst/findnext.
1179 * JRA.
1182 reskey = 0;
1184 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1185 (long)conn->dirptr,curr_dirpos));
1187 if (!dname) {
1188 return(False);
1192 * fname may get mangled, dname is never mangled.
1193 * Whenever we're accessing the filesystem we use
1194 * pathreal which is composed from dname.
1197 pathreal = NULL;
1198 fname = dname;
1200 /* Mangle fname if it's an illegal name. */
1201 if (mangle_must_mangle(dname,conn->params)) {
1202 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1203 continue; /* Error - couldn't mangle. */
1205 fname = mangled_name;
1208 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1209 got_match = mask_match(fname, mask, conn->case_sensitive);
1212 if(!got_match && check_mangled_names &&
1213 !mangle_is_8_3(fname, False, conn->params)) {
1215 * It turns out that NT matches wildcards against
1216 * both long *and* short names. This may explain some
1217 * of the wildcard wierdness from old DOS clients
1218 * that some people have been seeing.... JRA.
1220 /* Force the mangling into 8.3. */
1221 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1222 continue; /* Error - couldn't mangle. */
1225 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1226 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1230 if (got_match) {
1231 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1233 if (dont_descend && !isdots) {
1234 continue;
1237 if (needslash) {
1238 pathreal = NULL;
1239 pathreal = talloc_asprintf(ctx,
1240 "%s/%s",
1241 conn->dirpath,
1242 dname);
1243 } else {
1244 pathreal = talloc_asprintf(ctx,
1245 "%s%s",
1246 conn->dirpath,
1247 dname);
1250 if (!pathreal) {
1251 return False;
1254 if (INFO_LEVEL_IS_UNIX(info_level)) {
1255 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1256 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1257 pathreal,strerror(errno)));
1258 TALLOC_FREE(pathreal);
1259 continue;
1261 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1262 /* Needed to show the msdfs symlinks as
1263 * directories */
1265 if(lp_host_msdfs() &&
1266 lp_msdfs_root(SNUM(conn)) &&
1267 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1268 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1269 "as a directory\n",
1270 pathreal));
1271 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1273 } else {
1275 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1276 pathreal,strerror(errno)));
1277 TALLOC_FREE(pathreal);
1278 continue;
1282 if (ms_dfs_link) {
1283 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1284 } else {
1285 mode = dos_mode(conn,pathreal,&sbuf);
1288 if (!dir_check_ftype(conn,mode,dirtype)) {
1289 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1290 TALLOC_FREE(pathreal);
1291 continue;
1294 if (!(mode & aDIR)) {
1295 file_size = get_file_size(sbuf);
1297 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1299 mdate_ts = get_mtimespec(&sbuf);
1300 adate_ts = get_atimespec(&sbuf);
1301 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1303 if (lp_dos_filetime_resolution(SNUM(conn))) {
1304 dos_filetime_timespec(&create_date_ts);
1305 dos_filetime_timespec(&mdate_ts);
1306 dos_filetime_timespec(&adate_ts);
1309 create_date = convert_timespec_to_time_t(create_date_ts);
1310 mdate = convert_timespec_to_time_t(mdate_ts);
1311 adate = convert_timespec_to_time_t(adate_ts);
1313 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1315 found = True;
1317 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1321 p = pdata;
1322 last_entry_ptr = p;
1324 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1326 switch (info_level) {
1327 case SMB_FIND_INFO_STANDARD:
1328 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1329 if(requires_resume_key) {
1330 SIVAL(p,0,reskey);
1331 p += 4;
1333 srv_put_dos_date2(p,0,create_date);
1334 srv_put_dos_date2(p,4,adate);
1335 srv_put_dos_date2(p,8,mdate);
1336 SIVAL(p,12,(uint32)file_size);
1337 SIVAL(p,16,(uint32)allocation_size);
1338 SSVAL(p,20,mode);
1339 p += 23;
1340 nameptr = p;
1341 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1342 p += ucs2_align(base_data, p, 0);
1344 len = srvstr_push(base_data, flags2, p,
1345 fname, PTR_DIFF(end_data, p),
1346 STR_TERMINATE);
1347 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1348 if (len > 2) {
1349 SCVAL(nameptr, -1, len - 2);
1350 } else {
1351 SCVAL(nameptr, -1, 0);
1353 } else {
1354 if (len > 1) {
1355 SCVAL(nameptr, -1, len - 1);
1356 } else {
1357 SCVAL(nameptr, -1, 0);
1360 p += len;
1361 break;
1363 case SMB_FIND_EA_SIZE:
1364 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1365 if(requires_resume_key) {
1366 SIVAL(p,0,reskey);
1367 p += 4;
1369 srv_put_dos_date2(p,0,create_date);
1370 srv_put_dos_date2(p,4,adate);
1371 srv_put_dos_date2(p,8,mdate);
1372 SIVAL(p,12,(uint32)file_size);
1373 SIVAL(p,16,(uint32)allocation_size);
1374 SSVAL(p,20,mode);
1376 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1377 SIVAL(p,22,ea_size); /* Extended attributes */
1379 p += 27;
1380 nameptr = p - 1;
1381 len = srvstr_push(base_data, flags2,
1382 p, fname, PTR_DIFF(end_data, p),
1383 STR_TERMINATE | STR_NOALIGN);
1384 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1385 if (len > 2) {
1386 len -= 2;
1387 } else {
1388 len = 0;
1390 } else {
1391 if (len > 1) {
1392 len -= 1;
1393 } else {
1394 len = 0;
1397 SCVAL(nameptr,0,len);
1398 p += len;
1399 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1400 break;
1402 case SMB_FIND_EA_LIST:
1404 struct ea_list *file_list = NULL;
1405 size_t ea_len = 0;
1407 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1408 if (!name_list) {
1409 return False;
1411 if(requires_resume_key) {
1412 SIVAL(p,0,reskey);
1413 p += 4;
1415 srv_put_dos_date2(p,0,create_date);
1416 srv_put_dos_date2(p,4,adate);
1417 srv_put_dos_date2(p,8,mdate);
1418 SIVAL(p,12,(uint32)file_size);
1419 SIVAL(p,16,(uint32)allocation_size);
1420 SSVAL(p,20,mode);
1421 p += 22; /* p now points to the EA area. */
1423 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1424 name_list = ea_list_union(name_list, file_list, &ea_len);
1426 /* We need to determine if this entry will fit in the space available. */
1427 /* Max string size is 255 bytes. */
1428 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1429 /* Move the dirptr back to prev_dirpos */
1430 dptr_SeekDir(conn->dirptr, prev_dirpos);
1431 *out_of_space = True;
1432 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1433 return False; /* Not finished - just out of space */
1436 /* Push the ea_data followed by the name. */
1437 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1438 nameptr = p;
1439 len = srvstr_push(base_data, flags2,
1440 p + 1, fname, PTR_DIFF(end_data, p+1),
1441 STR_TERMINATE | STR_NOALIGN);
1442 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1443 if (len > 2) {
1444 len -= 2;
1445 } else {
1446 len = 0;
1448 } else {
1449 if (len > 1) {
1450 len -= 1;
1451 } else {
1452 len = 0;
1455 SCVAL(nameptr,0,len);
1456 p += len + 1;
1457 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1458 break;
1461 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1462 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1463 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1464 p += 4;
1465 SIVAL(p,0,reskey); p += 4;
1466 put_long_date_timespec(p,create_date_ts); p += 8;
1467 put_long_date_timespec(p,adate_ts); p += 8;
1468 put_long_date_timespec(p,mdate_ts); p += 8;
1469 put_long_date_timespec(p,mdate_ts); p += 8;
1470 SOFF_T(p,0,file_size); p += 8;
1471 SOFF_T(p,0,allocation_size); p += 8;
1472 SIVAL(p,0,nt_extmode); p += 4;
1473 q = p; p += 4; /* q is placeholder for name length. */
1475 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1476 SIVAL(p,0,ea_size); /* Extended attributes */
1477 p += 4;
1479 /* Clear the short name buffer. This is
1480 * IMPORTANT as not doing so will trigger
1481 * a Win2k client bug. JRA.
1483 if (!was_8_3 && check_mangled_names) {
1484 if (!name_to_8_3(fname,mangled_name,True,
1485 conn->params)) {
1486 /* Error - mangle failed ! */
1487 memset(mangled_name,'\0',12);
1489 mangled_name[12] = 0;
1490 len = srvstr_push(base_data, flags2,
1491 p+2, mangled_name, 24,
1492 STR_UPPER|STR_UNICODE);
1493 if (len < 24) {
1494 memset(p + 2 + len,'\0',24 - len);
1496 SSVAL(p, 0, len);
1497 } else {
1498 memset(p,'\0',26);
1500 p += 2 + 24;
1501 len = srvstr_push(base_data, flags2, p,
1502 fname, PTR_DIFF(end_data, p),
1503 STR_TERMINATE_ASCII);
1504 SIVAL(q,0,len);
1505 p += len;
1506 SIVAL(p,0,0); /* Ensure any padding is null. */
1507 len = PTR_DIFF(p, pdata);
1508 len = (len + 3) & ~3;
1509 SIVAL(pdata,0,len);
1510 p = pdata + len;
1511 break;
1513 case SMB_FIND_FILE_DIRECTORY_INFO:
1514 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1515 p += 4;
1516 SIVAL(p,0,reskey); p += 4;
1517 put_long_date_timespec(p,create_date_ts); p += 8;
1518 put_long_date_timespec(p,adate_ts); p += 8;
1519 put_long_date_timespec(p,mdate_ts); p += 8;
1520 put_long_date_timespec(p,mdate_ts); p += 8;
1521 SOFF_T(p,0,file_size); p += 8;
1522 SOFF_T(p,0,allocation_size); p += 8;
1523 SIVAL(p,0,nt_extmode); p += 4;
1524 len = srvstr_push(base_data, flags2,
1525 p + 4, fname, PTR_DIFF(end_data, p+4),
1526 STR_TERMINATE_ASCII);
1527 SIVAL(p,0,len);
1528 p += 4 + len;
1529 SIVAL(p,0,0); /* Ensure any padding is null. */
1530 len = PTR_DIFF(p, pdata);
1531 len = (len + 3) & ~3;
1532 SIVAL(pdata,0,len);
1533 p = pdata + len;
1534 break;
1536 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1537 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1538 p += 4;
1539 SIVAL(p,0,reskey); p += 4;
1540 put_long_date_timespec(p,create_date_ts); p += 8;
1541 put_long_date_timespec(p,adate_ts); p += 8;
1542 put_long_date_timespec(p,mdate_ts); p += 8;
1543 put_long_date_timespec(p,mdate_ts); p += 8;
1544 SOFF_T(p,0,file_size); p += 8;
1545 SOFF_T(p,0,allocation_size); p += 8;
1546 SIVAL(p,0,nt_extmode); p += 4;
1547 q = p; p += 4; /* q is placeholder for name length. */
1549 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1550 SIVAL(p,0,ea_size); /* Extended attributes */
1551 p +=4;
1553 len = srvstr_push(base_data, flags2, p,
1554 fname, PTR_DIFF(end_data, p),
1555 STR_TERMINATE_ASCII);
1556 SIVAL(q, 0, len);
1557 p += len;
1559 SIVAL(p,0,0); /* Ensure any padding is null. */
1560 len = PTR_DIFF(p, pdata);
1561 len = (len + 3) & ~3;
1562 SIVAL(pdata,0,len);
1563 p = pdata + len;
1564 break;
1566 case SMB_FIND_FILE_NAMES_INFO:
1567 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1568 p += 4;
1569 SIVAL(p,0,reskey); p += 4;
1570 p += 4;
1571 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1572 acl on a dir (tridge) */
1573 len = srvstr_push(base_data, flags2, p,
1574 fname, PTR_DIFF(end_data, p),
1575 STR_TERMINATE_ASCII);
1576 SIVAL(p, -4, len);
1577 p += len;
1578 SIVAL(p,0,0); /* Ensure any padding is null. */
1579 len = PTR_DIFF(p, pdata);
1580 len = (len + 3) & ~3;
1581 SIVAL(pdata,0,len);
1582 p = pdata + len;
1583 break;
1585 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1586 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1587 p += 4;
1588 SIVAL(p,0,reskey); p += 4;
1589 put_long_date_timespec(p,create_date_ts); p += 8;
1590 put_long_date_timespec(p,adate_ts); p += 8;
1591 put_long_date_timespec(p,mdate_ts); p += 8;
1592 put_long_date_timespec(p,mdate_ts); p += 8;
1593 SOFF_T(p,0,file_size); p += 8;
1594 SOFF_T(p,0,allocation_size); p += 8;
1595 SIVAL(p,0,nt_extmode); p += 4;
1596 q = p; p += 4; /* q is placeholder for name length. */
1598 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1599 SIVAL(p,0,ea_size); /* Extended attributes */
1600 p +=4;
1602 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1603 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1604 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1605 len = srvstr_push(base_data, flags2, p,
1606 fname, PTR_DIFF(end_data, p),
1607 STR_TERMINATE_ASCII);
1608 SIVAL(q, 0, len);
1609 p += len;
1610 SIVAL(p,0,0); /* Ensure any padding is null. */
1611 len = PTR_DIFF(p, pdata);
1612 len = (len + 3) & ~3;
1613 SIVAL(pdata,0,len);
1614 p = pdata + len;
1615 break;
1617 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1618 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1619 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1620 p += 4;
1621 SIVAL(p,0,reskey); p += 4;
1622 put_long_date_timespec(p,create_date_ts); p += 8;
1623 put_long_date_timespec(p,adate_ts); p += 8;
1624 put_long_date_timespec(p,mdate_ts); p += 8;
1625 put_long_date_timespec(p,mdate_ts); p += 8;
1626 SOFF_T(p,0,file_size); p += 8;
1627 SOFF_T(p,0,allocation_size); p += 8;
1628 SIVAL(p,0,nt_extmode); p += 4;
1629 q = p; p += 4; /* q is placeholder for name length */
1631 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1632 SIVAL(p,0,ea_size); /* Extended attributes */
1633 p +=4;
1635 /* Clear the short name buffer. This is
1636 * IMPORTANT as not doing so will trigger
1637 * a Win2k client bug. JRA.
1639 if (!was_8_3 && check_mangled_names) {
1640 if (!name_to_8_3(fname,mangled_name,True,
1641 conn->params)) {
1642 /* Error - mangle failed ! */
1643 memset(mangled_name,'\0',12);
1645 mangled_name[12] = 0;
1646 len = srvstr_push(base_data, flags2,
1647 p+2, mangled_name, 24,
1648 STR_UPPER|STR_UNICODE);
1649 SSVAL(p, 0, len);
1650 if (len < 24) {
1651 memset(p + 2 + len,'\0',24 - len);
1653 SSVAL(p, 0, len);
1654 } else {
1655 memset(p,'\0',26);
1657 p += 26;
1658 SSVAL(p,0,0); p += 2; /* Reserved ? */
1659 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1660 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1661 len = srvstr_push(base_data, flags2, p,
1662 fname, PTR_DIFF(end_data, p),
1663 STR_TERMINATE_ASCII);
1664 SIVAL(q,0,len);
1665 p += len;
1666 SIVAL(p,0,0); /* Ensure any padding is null. */
1667 len = PTR_DIFF(p, pdata);
1668 len = (len + 3) & ~3;
1669 SIVAL(pdata,0,len);
1670 p = pdata + len;
1671 break;
1673 /* CIFS UNIX Extension. */
1675 case SMB_FIND_FILE_UNIX:
1676 case SMB_FIND_FILE_UNIX_INFO2:
1677 p+= 4;
1678 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1680 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1682 if (info_level == SMB_FIND_FILE_UNIX) {
1683 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1684 p = store_file_unix_basic(conn, p,
1685 NULL, &sbuf);
1686 len = srvstr_push(base_data, flags2, p,
1687 fname, PTR_DIFF(end_data, p),
1688 STR_TERMINATE);
1689 } else {
1690 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1691 p = store_file_unix_basic_info2(conn, p,
1692 NULL, &sbuf);
1693 nameptr = p;
1694 p += 4;
1695 len = srvstr_push(base_data, flags2, p, fname,
1696 PTR_DIFF(end_data, p), 0);
1697 SIVAL(nameptr, 0, len);
1700 p += len;
1701 SIVAL(p,0,0); /* Ensure any padding is null. */
1703 len = PTR_DIFF(p, pdata);
1704 len = (len + 3) & ~3;
1705 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1706 p = pdata + len;
1707 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1709 break;
1711 default:
1712 return(False);
1716 if (PTR_DIFF(p,pdata) > space_remaining) {
1717 /* Move the dirptr back to prev_dirpos */
1718 dptr_SeekDir(conn->dirptr, prev_dirpos);
1719 *out_of_space = True;
1720 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1721 return False; /* Not finished - just out of space */
1724 /* Setup the last entry pointer, as an offset from base_data */
1725 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1726 /* Advance the data pointer to the next slot */
1727 *ppdata = p;
1729 return(found);
1732 /****************************************************************************
1733 Reply to a TRANS2_FINDFIRST.
1734 ****************************************************************************/
1736 static void call_trans2findfirst(connection_struct *conn,
1737 struct smb_request *req,
1738 char **pparams, int total_params,
1739 char **ppdata, int total_data,
1740 unsigned int max_data_bytes)
1742 /* We must be careful here that we don't return more than the
1743 allowed number of data bytes. If this means returning fewer than
1744 maxentries then so be it. We assume that the redirector has
1745 enough room for the fixed number of parameter bytes it has
1746 requested. */
1747 char *params = *pparams;
1748 char *pdata = *ppdata;
1749 char *data_end;
1750 uint32 dirtype;
1751 int maxentries;
1752 uint16 findfirst_flags;
1753 bool close_after_first;
1754 bool close_if_end;
1755 bool requires_resume_key;
1756 int info_level;
1757 char *directory = NULL;
1758 const char *mask = NULL;
1759 char *p;
1760 int last_entry_off=0;
1761 int dptr_num = -1;
1762 int numentries = 0;
1763 int i;
1764 bool finished = False;
1765 bool dont_descend = False;
1766 bool out_of_space = False;
1767 int space_remaining;
1768 bool mask_contains_wcard = False;
1769 SMB_STRUCT_STAT sbuf;
1770 struct ea_list *ea_list = NULL;
1771 NTSTATUS ntstatus = NT_STATUS_OK;
1772 TALLOC_CTX *ctx = talloc_tos();
1774 if (total_params < 13) {
1775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1776 return;
1779 dirtype = SVAL(params,0);
1780 maxentries = SVAL(params,2);
1781 findfirst_flags = SVAL(params,4);
1782 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1783 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1784 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1785 info_level = SVAL(params,6);
1787 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1788 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1789 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1790 info_level, max_data_bytes));
1792 if (!maxentries) {
1793 /* W2K3 seems to treat zero as 1. */
1794 maxentries = 1;
1797 switch (info_level) {
1798 case SMB_FIND_INFO_STANDARD:
1799 case SMB_FIND_EA_SIZE:
1800 case SMB_FIND_EA_LIST:
1801 case SMB_FIND_FILE_DIRECTORY_INFO:
1802 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1803 case SMB_FIND_FILE_NAMES_INFO:
1804 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1805 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1806 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1807 break;
1808 case SMB_FIND_FILE_UNIX:
1809 case SMB_FIND_FILE_UNIX_INFO2:
1810 if (!lp_unix_extensions()) {
1811 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1812 return;
1814 break;
1815 default:
1816 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1817 return;
1820 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1821 params+12, total_params - 12,
1822 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1823 if (!NT_STATUS_IS_OK(ntstatus)) {
1824 reply_nterror(req, ntstatus);
1825 return;
1828 ntstatus = resolve_dfspath_wcard(ctx, conn,
1829 req->flags2 & FLAGS2_DFS_PATHNAMES,
1830 directory,
1831 &directory,
1832 &mask_contains_wcard);
1833 if (!NT_STATUS_IS_OK(ntstatus)) {
1834 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1835 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1836 ERRSRV, ERRbadpath);
1837 return;
1839 reply_nterror(req, ntstatus);
1840 return;
1843 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1844 if (!NT_STATUS_IS_OK(ntstatus)) {
1845 reply_nterror(req, ntstatus);
1846 return;
1849 ntstatus = check_name(conn, directory);
1850 if (!NT_STATUS_IS_OK(ntstatus)) {
1851 reply_nterror(req, ntstatus);
1852 return;
1855 p = strrchr_m(directory,'/');
1856 if(p == NULL) {
1857 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1858 if((directory[0] == '.') && (directory[1] == '\0')) {
1859 mask = "*";
1860 mask_contains_wcard = True;
1861 } else {
1862 mask = directory;
1864 directory = talloc_strdup(talloc_tos(), "./");
1865 if (!directory) {
1866 reply_nterror(req, NT_STATUS_NO_MEMORY);
1867 return;
1869 } else {
1870 mask = p+1;
1871 *p = 0;
1874 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1876 if (info_level == SMB_FIND_EA_LIST) {
1877 uint32 ea_size;
1879 if (total_data < 4) {
1880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1881 return;
1884 ea_size = IVAL(pdata,0);
1885 if (ea_size != total_data) {
1886 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1887 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1889 return;
1892 if (!lp_ea_support(SNUM(conn))) {
1893 reply_doserror(req, ERRDOS, ERReasnotsupported);
1894 return;
1897 /* Pull out the list of names. */
1898 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1899 if (!ea_list) {
1900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1901 return;
1905 *ppdata = (char *)SMB_REALLOC(
1906 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1907 if(*ppdata == NULL ) {
1908 reply_nterror(req, NT_STATUS_NO_MEMORY);
1909 return;
1911 pdata = *ppdata;
1912 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1914 /* Realloc the params space */
1915 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1916 if (*pparams == NULL) {
1917 reply_nterror(req, NT_STATUS_NO_MEMORY);
1918 return;
1920 params = *pparams;
1922 /* Save the wildcard match and attribs we are using on this directory -
1923 needed as lanman2 assumes these are being saved between calls */
1925 ntstatus = dptr_create(conn,
1926 directory,
1927 False,
1928 True,
1929 req->smbpid,
1930 mask,
1931 mask_contains_wcard,
1932 dirtype,
1933 &conn->dirptr);
1935 if (!NT_STATUS_IS_OK(ntstatus)) {
1936 reply_nterror(req, ntstatus);
1937 return;
1940 dptr_num = dptr_dnum(conn->dirptr);
1941 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1943 /* We don't need to check for VOL here as this is returned by
1944 a different TRANS2 call. */
1946 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1947 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1948 dont_descend = True;
1950 p = pdata;
1951 space_remaining = max_data_bytes;
1952 out_of_space = False;
1954 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1955 bool got_exact_match = False;
1957 /* this is a heuristic to avoid seeking the dirptr except when
1958 absolutely necessary. It allows for a filename of about 40 chars */
1959 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1960 out_of_space = True;
1961 finished = False;
1962 } else {
1963 finished = !get_lanman2_dir_entry(ctx,
1964 conn,
1965 req->flags2,
1966 mask,dirtype,info_level,
1967 requires_resume_key,dont_descend,
1968 &p,pdata,data_end,
1969 space_remaining, &out_of_space,
1970 &got_exact_match,
1971 &last_entry_off, ea_list);
1974 if (finished && out_of_space)
1975 finished = False;
1977 if (!finished && !out_of_space)
1978 numentries++;
1981 * As an optimisation if we know we aren't looking
1982 * for a wildcard name (ie. the name matches the wildcard exactly)
1983 * then we can finish on any (first) match.
1984 * This speeds up large directory searches. JRA.
1987 if(got_exact_match)
1988 finished = True;
1990 /* Ensure space_remaining never goes -ve. */
1991 if (PTR_DIFF(p,pdata) > max_data_bytes) {
1992 space_remaining = 0;
1993 out_of_space = true;
1994 } else {
1995 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1999 /* Check if we can close the dirptr */
2000 if(close_after_first || (finished && close_if_end)) {
2001 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2002 dptr_close(&dptr_num);
2006 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2007 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2008 * the protocol level is less than NT1. Tested with smbclient. JRA.
2009 * This should fix the OS/2 client bug #2335.
2012 if(numentries == 0) {
2013 dptr_close(&dptr_num);
2014 if (Protocol < PROTOCOL_NT1) {
2015 reply_doserror(req, ERRDOS, ERRnofiles);
2016 return;
2017 } else {
2018 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2019 ERRDOS, ERRbadfile);
2020 return;
2024 /* At this point pdata points to numentries directory entries. */
2026 /* Set up the return parameter block */
2027 SSVAL(params,0,dptr_num);
2028 SSVAL(params,2,numentries);
2029 SSVAL(params,4,finished);
2030 SSVAL(params,6,0); /* Never an EA error */
2031 SSVAL(params,8,last_entry_off);
2033 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2034 max_data_bytes);
2036 if ((! *directory) && dptr_path(dptr_num)) {
2037 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2038 if (!directory) {
2039 reply_nterror(req, NT_STATUS_NO_MEMORY);
2043 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2044 smb_fn_name(CVAL(req->inbuf,smb_com)),
2045 mask, directory, dirtype, numentries ) );
2048 * Force a name mangle here to ensure that the
2049 * mask as an 8.3 name is top of the mangled cache.
2050 * The reasons for this are subtle. Don't remove
2051 * this code unless you know what you are doing
2052 * (see PR#13758). JRA.
2055 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2056 char mangled_name[13];
2057 name_to_8_3(mask, mangled_name, True, conn->params);
2060 return;
2063 /****************************************************************************
2064 Reply to a TRANS2_FINDNEXT.
2065 ****************************************************************************/
2067 static void call_trans2findnext(connection_struct *conn,
2068 struct smb_request *req,
2069 char **pparams, int total_params,
2070 char **ppdata, int total_data,
2071 unsigned int max_data_bytes)
2073 /* We must be careful here that we don't return more than the
2074 allowed number of data bytes. If this means returning fewer than
2075 maxentries then so be it. We assume that the redirector has
2076 enough room for the fixed number of parameter bytes it has
2077 requested. */
2078 char *params = *pparams;
2079 char *pdata = *ppdata;
2080 char *data_end;
2081 int dptr_num;
2082 int maxentries;
2083 uint16 info_level;
2084 uint32 resume_key;
2085 uint16 findnext_flags;
2086 bool close_after_request;
2087 bool close_if_end;
2088 bool requires_resume_key;
2089 bool continue_bit;
2090 bool mask_contains_wcard = False;
2091 char *resume_name = NULL;
2092 const char *mask = NULL;
2093 const char *directory = NULL;
2094 char *p = NULL;
2095 uint16 dirtype;
2096 int numentries = 0;
2097 int i, last_entry_off=0;
2098 bool finished = False;
2099 bool dont_descend = False;
2100 bool out_of_space = False;
2101 int space_remaining;
2102 struct ea_list *ea_list = NULL;
2103 NTSTATUS ntstatus = NT_STATUS_OK;
2104 TALLOC_CTX *ctx = talloc_tos();
2106 if (total_params < 13) {
2107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2108 return;
2111 dptr_num = SVAL(params,0);
2112 maxentries = SVAL(params,2);
2113 info_level = SVAL(params,4);
2114 resume_key = IVAL(params,6);
2115 findnext_flags = SVAL(params,10);
2116 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2117 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2118 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2119 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2121 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2122 params+12,
2123 total_params - 12, STR_TERMINATE, &ntstatus,
2124 &mask_contains_wcard);
2125 if (!NT_STATUS_IS_OK(ntstatus)) {
2126 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2127 complain (it thinks we're asking for the directory above the shared
2128 path or an invalid name). Catch this as the resume name is only compared, never used in
2129 a file access. JRA. */
2130 srvstr_pull_talloc(ctx, params, req->flags2,
2131 &resume_name, params+12,
2132 total_params - 12,
2133 STR_TERMINATE);
2135 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2136 reply_nterror(req, ntstatus);
2137 return;
2141 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2142 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2143 resume_key = %d resume name = %s continue=%d level = %d\n",
2144 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2145 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2147 if (!maxentries) {
2148 /* W2K3 seems to treat zero as 1. */
2149 maxentries = 1;
2152 switch (info_level) {
2153 case SMB_FIND_INFO_STANDARD:
2154 case SMB_FIND_EA_SIZE:
2155 case SMB_FIND_EA_LIST:
2156 case SMB_FIND_FILE_DIRECTORY_INFO:
2157 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2158 case SMB_FIND_FILE_NAMES_INFO:
2159 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2160 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2161 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2162 break;
2163 case SMB_FIND_FILE_UNIX:
2164 case SMB_FIND_FILE_UNIX_INFO2:
2165 if (!lp_unix_extensions()) {
2166 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2167 return;
2169 break;
2170 default:
2171 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2172 return;
2175 if (info_level == SMB_FIND_EA_LIST) {
2176 uint32 ea_size;
2178 if (total_data < 4) {
2179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2180 return;
2183 ea_size = IVAL(pdata,0);
2184 if (ea_size != total_data) {
2185 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2186 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2188 return;
2191 if (!lp_ea_support(SNUM(conn))) {
2192 reply_doserror(req, ERRDOS, ERReasnotsupported);
2193 return;
2196 /* Pull out the list of names. */
2197 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2198 if (!ea_list) {
2199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2200 return;
2204 *ppdata = (char *)SMB_REALLOC(
2205 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2206 if(*ppdata == NULL) {
2207 reply_nterror(req, NT_STATUS_NO_MEMORY);
2208 return;
2211 pdata = *ppdata;
2212 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2214 /* Realloc the params space */
2215 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2216 if(*pparams == NULL ) {
2217 reply_nterror(req, NT_STATUS_NO_MEMORY);
2218 return;
2221 params = *pparams;
2223 /* Check that the dptr is valid */
2224 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2225 reply_doserror(req, ERRDOS, ERRnofiles);
2226 return;
2229 string_set(&conn->dirpath,dptr_path(dptr_num));
2231 /* Get the wildcard mask from the dptr */
2232 if((p = dptr_wcard(dptr_num))== NULL) {
2233 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2234 reply_doserror(req, ERRDOS, ERRnofiles);
2235 return;
2238 mask = p;
2239 directory = conn->dirpath;
2241 /* Get the attr mask from the dptr */
2242 dirtype = dptr_attr(dptr_num);
2244 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2245 dptr_num, mask, dirtype,
2246 (long)conn->dirptr,
2247 dptr_TellDir(conn->dirptr)));
2249 /* We don't need to check for VOL here as this is returned by
2250 a different TRANS2 call. */
2252 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2253 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2254 dont_descend = True;
2256 p = pdata;
2257 space_remaining = max_data_bytes;
2258 out_of_space = False;
2261 * Seek to the correct position. We no longer use the resume key but
2262 * depend on the last file name instead.
2265 if(*resume_name && !continue_bit) {
2266 SMB_STRUCT_STAT st;
2268 long current_pos = 0;
2270 * Remember, name_to_8_3 is called by
2271 * get_lanman2_dir_entry(), so the resume name
2272 * could be mangled. Ensure we check the unmangled name.
2275 if (mangle_is_mangled(resume_name, conn->params)) {
2276 char *new_resume_name = NULL;
2277 mangle_lookup_name_from_8_3(ctx,
2278 resume_name,
2279 &new_resume_name,
2280 conn->params);
2281 if (new_resume_name) {
2282 resume_name = new_resume_name;
2287 * Fix for NT redirector problem triggered by resume key indexes
2288 * changing between directory scans. We now return a resume key of 0
2289 * and instead look for the filename to continue from (also given
2290 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2291 * findfirst/findnext (as is usual) then the directory pointer
2292 * should already be at the correct place.
2295 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2296 } /* end if resume_name && !continue_bit */
2298 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2299 bool got_exact_match = False;
2301 /* this is a heuristic to avoid seeking the dirptr except when
2302 absolutely necessary. It allows for a filename of about 40 chars */
2303 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2304 out_of_space = True;
2305 finished = False;
2306 } else {
2307 finished = !get_lanman2_dir_entry(ctx,
2308 conn,
2309 req->flags2,
2310 mask,dirtype,info_level,
2311 requires_resume_key,dont_descend,
2312 &p,pdata,data_end,
2313 space_remaining, &out_of_space,
2314 &got_exact_match,
2315 &last_entry_off, ea_list);
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(conn, 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 uint32 additional_flags = 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 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2394 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2395 "info level (0x%x) on IPC$.\n",
2396 (unsigned int)info_level));
2397 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2398 return;
2402 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2403 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2404 DEBUG(0,("call_trans2qfsinfo: encryption required "
2405 "and info level 0x%x sent.\n",
2406 (unsigned int)info_level));
2407 exit_server_cleanly("encryption required "
2408 "on connection");
2409 return;
2413 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2415 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2416 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2417 reply_doserror(req, ERRSRV, ERRinvdevice);
2418 return;
2421 *ppdata = (char *)SMB_REALLOC(
2422 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2423 if (*ppdata == NULL ) {
2424 reply_nterror(req, NT_STATUS_NO_MEMORY);
2425 return;
2428 pdata = *ppdata;
2429 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2430 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2432 switch (info_level) {
2433 case SMB_INFO_ALLOCATION:
2435 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2436 data_len = 18;
2437 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2438 reply_unixerror(req, ERRHRD, ERRgeneral);
2439 return;
2442 block_size = lp_block_size(snum);
2443 if (bsize < block_size) {
2444 SMB_BIG_UINT factor = block_size/bsize;
2445 bsize = block_size;
2446 dsize /= factor;
2447 dfree /= factor;
2449 if (bsize > block_size) {
2450 SMB_BIG_UINT factor = bsize/block_size;
2451 bsize = block_size;
2452 dsize *= factor;
2453 dfree *= factor;
2455 bytes_per_sector = 512;
2456 sectors_per_unit = bsize/bytes_per_sector;
2458 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2459 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2460 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2462 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2463 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2464 SIVAL(pdata,l1_cUnit,dsize);
2465 SIVAL(pdata,l1_cUnitAvail,dfree);
2466 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2467 break;
2470 case SMB_INFO_VOLUME:
2471 /* Return volume name */
2473 * Add volume serial number - hash of a combination of
2474 * the called hostname and the service name.
2476 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2478 * Win2k3 and previous mess this up by sending a name length
2479 * one byte short. I believe only older clients (OS/2 Win9x) use
2480 * this call so try fixing this by adding a terminating null to
2481 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2483 len = srvstr_push(
2484 pdata, req->flags2,
2485 pdata+l2_vol_szVolLabel, vname,
2486 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2487 STR_NOALIGN|STR_TERMINATE);
2488 SCVAL(pdata,l2_vol_cch,len);
2489 data_len = l2_vol_szVolLabel + len;
2490 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2491 (unsigned)st.st_ctime, len, vname));
2492 break;
2494 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2495 case SMB_FS_ATTRIBUTE_INFORMATION:
2497 additional_flags = 0;
2498 #if defined(HAVE_SYS_QUOTAS)
2499 additional_flags |= FILE_VOLUME_QUOTAS;
2500 #endif
2502 if(lp_nt_acl_support(SNUM(conn))) {
2503 additional_flags |= FILE_PERSISTENT_ACLS;
2506 /* Capabilities are filled in at connection time through STATVFS call */
2507 additional_flags |= conn->fs_capabilities;
2509 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2510 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2511 additional_flags); /* FS ATTRIBUTES */
2513 SIVAL(pdata,4,255); /* Max filename component length */
2514 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2515 and will think we can't do long filenames */
2516 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2517 PTR_DIFF(end_data, pdata+12),
2518 STR_UNICODE);
2519 SIVAL(pdata,8,len);
2520 data_len = 12 + len;
2521 break;
2523 case SMB_QUERY_FS_LABEL_INFO:
2524 case SMB_FS_LABEL_INFORMATION:
2525 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2526 PTR_DIFF(end_data, pdata+4), 0);
2527 data_len = 4 + len;
2528 SIVAL(pdata,0,len);
2529 break;
2531 case SMB_QUERY_FS_VOLUME_INFO:
2532 case SMB_FS_VOLUME_INFORMATION:
2535 * Add volume serial number - hash of a combination of
2536 * the called hostname and the service name.
2538 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2539 (str_checksum(get_local_machine_name())<<16));
2541 /* Max label len is 32 characters. */
2542 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2543 PTR_DIFF(end_data, pdata+18),
2544 STR_UNICODE);
2545 SIVAL(pdata,12,len);
2546 data_len = 18+len;
2548 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2549 (int)strlen(vname),vname, lp_servicename(snum)));
2550 break;
2552 case SMB_QUERY_FS_SIZE_INFO:
2553 case SMB_FS_SIZE_INFORMATION:
2555 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2556 data_len = 24;
2557 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2558 reply_unixerror(req, ERRHRD, ERRgeneral);
2559 return;
2561 block_size = lp_block_size(snum);
2562 if (bsize < block_size) {
2563 SMB_BIG_UINT factor = block_size/bsize;
2564 bsize = block_size;
2565 dsize /= factor;
2566 dfree /= factor;
2568 if (bsize > block_size) {
2569 SMB_BIG_UINT factor = bsize/block_size;
2570 bsize = block_size;
2571 dsize *= factor;
2572 dfree *= factor;
2574 bytes_per_sector = 512;
2575 sectors_per_unit = bsize/bytes_per_sector;
2576 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2577 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2578 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2579 SBIG_UINT(pdata,0,dsize);
2580 SBIG_UINT(pdata,8,dfree);
2581 SIVAL(pdata,16,sectors_per_unit);
2582 SIVAL(pdata,20,bytes_per_sector);
2583 break;
2586 case SMB_FS_FULL_SIZE_INFORMATION:
2588 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2589 data_len = 32;
2590 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2591 reply_unixerror(req, ERRHRD, ERRgeneral);
2592 return;
2594 block_size = lp_block_size(snum);
2595 if (bsize < block_size) {
2596 SMB_BIG_UINT factor = block_size/bsize;
2597 bsize = block_size;
2598 dsize /= factor;
2599 dfree /= factor;
2601 if (bsize > block_size) {
2602 SMB_BIG_UINT factor = bsize/block_size;
2603 bsize = block_size;
2604 dsize *= factor;
2605 dfree *= factor;
2607 bytes_per_sector = 512;
2608 sectors_per_unit = bsize/bytes_per_sector;
2609 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2610 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2611 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2612 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2613 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2614 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2615 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2616 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2617 break;
2620 case SMB_QUERY_FS_DEVICE_INFO:
2621 case SMB_FS_DEVICE_INFORMATION:
2622 data_len = 8;
2623 SIVAL(pdata,0,0); /* dev type */
2624 SIVAL(pdata,4,0); /* characteristics */
2625 break;
2627 #ifdef HAVE_SYS_QUOTAS
2628 case SMB_FS_QUOTA_INFORMATION:
2630 * what we have to send --metze:
2632 * Unknown1: 24 NULL bytes
2633 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2634 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2635 * Quota Flags: 2 byte :
2636 * Unknown3: 6 NULL bytes
2638 * 48 bytes total
2640 * details for Quota Flags:
2642 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2643 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2644 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2645 * 0x0001 Enable Quotas: enable quota for this fs
2649 /* we need to fake up a fsp here,
2650 * because its not send in this call
2652 files_struct fsp;
2653 SMB_NTQUOTA_STRUCT quotas;
2655 ZERO_STRUCT(fsp);
2656 ZERO_STRUCT(quotas);
2658 fsp.conn = conn;
2659 fsp.fnum = -1;
2661 /* access check */
2662 if (current_user.ut.uid != 0) {
2663 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2664 lp_servicename(SNUM(conn)),conn->user));
2665 reply_doserror(req, ERRDOS, ERRnoaccess);
2666 return;
2669 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2670 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2671 reply_doserror(req, ERRSRV, ERRerror);
2672 return;
2675 data_len = 48;
2677 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2679 /* Unknown1 24 NULL bytes*/
2680 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2681 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2682 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2684 /* Default Soft Quota 8 bytes */
2685 SBIG_UINT(pdata,24,quotas.softlim);
2687 /* Default Hard Quota 8 bytes */
2688 SBIG_UINT(pdata,32,quotas.hardlim);
2690 /* Quota flag 2 bytes */
2691 SSVAL(pdata,40,quotas.qflags);
2693 /* Unknown3 6 NULL bytes */
2694 SSVAL(pdata,42,0);
2695 SIVAL(pdata,44,0);
2697 break;
2699 #endif /* HAVE_SYS_QUOTAS */
2700 case SMB_FS_OBJECTID_INFORMATION:
2702 unsigned char objid[16];
2703 memcpy(pdata,create_volume_objectid(conn, objid),16);
2704 data_len = 64;
2705 break;
2709 * Query the version and capabilities of the CIFS UNIX extensions
2710 * in use.
2713 case SMB_QUERY_CIFS_UNIX_INFO:
2715 bool large_write = lp_min_receive_file_size() &&
2716 !srv_is_signing_active();
2717 bool large_read = !srv_is_signing_active();
2718 int encrypt_caps = 0;
2720 if (!lp_unix_extensions()) {
2721 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2722 return;
2725 switch (conn->encrypt_level) {
2726 case 0:
2727 encrypt_caps = 0;
2728 break;
2729 case 1:
2730 case Auto:
2731 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2732 break;
2733 case Required:
2734 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2735 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2736 large_write = false;
2737 large_read = false;
2738 break;
2741 data_len = 12;
2742 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2743 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2745 /* We have POSIX ACLs, pathname, encryption,
2746 * large read/write, and locking capability. */
2748 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2749 CIFS_UNIX_POSIX_ACLS_CAP|
2750 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2751 CIFS_UNIX_FCNTL_LOCKS_CAP|
2752 CIFS_UNIX_EXTATTR_CAP|
2753 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2754 encrypt_caps|
2755 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2756 (large_write ?
2757 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2758 break;
2761 case SMB_QUERY_POSIX_FS_INFO:
2763 int rc;
2764 vfs_statvfs_struct svfs;
2766 if (!lp_unix_extensions()) {
2767 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2768 return;
2771 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2773 if (!rc) {
2774 data_len = 56;
2775 SIVAL(pdata,0,svfs.OptimalTransferSize);
2776 SIVAL(pdata,4,svfs.BlockSize);
2777 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2778 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2779 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2780 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2781 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2782 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2783 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2784 #ifdef EOPNOTSUPP
2785 } else if (rc == EOPNOTSUPP) {
2786 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2787 return;
2788 #endif /* EOPNOTSUPP */
2789 } else {
2790 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2791 reply_doserror(req, ERRSRV, ERRerror);
2792 return;
2794 break;
2797 case SMB_QUERY_POSIX_WHOAMI:
2799 uint32_t flags = 0;
2800 uint32_t sid_bytes;
2801 int i;
2803 if (!lp_unix_extensions()) {
2804 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2805 return;
2808 if (max_data_bytes < 40) {
2809 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2810 return;
2813 /* We ARE guest if global_sid_Builtin_Guests is
2814 * in our list of SIDs.
2816 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2817 current_user.nt_user_token)) {
2818 flags |= SMB_WHOAMI_GUEST;
2821 /* We are NOT guest if global_sid_Authenticated_Users
2822 * is in our list of SIDs.
2824 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2825 current_user.nt_user_token)) {
2826 flags &= ~SMB_WHOAMI_GUEST;
2829 /* NOTE: 8 bytes for UID/GID, irrespective of native
2830 * platform size. This matches
2831 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2833 data_len = 4 /* flags */
2834 + 4 /* flag mask */
2835 + 8 /* uid */
2836 + 8 /* gid */
2837 + 4 /* ngroups */
2838 + 4 /* num_sids */
2839 + 4 /* SID bytes */
2840 + 4 /* pad/reserved */
2841 + (current_user.ut.ngroups * 8)
2842 /* groups list */
2843 + (current_user.nt_user_token->num_sids *
2844 SID_MAX_SIZE)
2845 /* SID list */;
2847 SIVAL(pdata, 0, flags);
2848 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2849 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2850 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2853 if (data_len >= max_data_bytes) {
2854 /* Potential overflow, skip the GIDs and SIDs. */
2856 SIVAL(pdata, 24, 0); /* num_groups */
2857 SIVAL(pdata, 28, 0); /* num_sids */
2858 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2859 SIVAL(pdata, 36, 0); /* reserved */
2861 data_len = 40;
2862 break;
2865 SIVAL(pdata, 24, current_user.ut.ngroups);
2866 SIVAL(pdata, 28,
2867 current_user.nt_user_token->num_sids);
2869 /* We walk the SID list twice, but this call is fairly
2870 * infrequent, and I don't expect that it's performance
2871 * sensitive -- jpeach
2873 for (i = 0, sid_bytes = 0;
2874 i < current_user.nt_user_token->num_sids; ++i) {
2875 sid_bytes += ndr_size_dom_sid(
2876 &current_user.nt_user_token->user_sids[i], 0);
2879 /* SID list byte count */
2880 SIVAL(pdata, 32, sid_bytes);
2882 /* 4 bytes pad/reserved - must be zero */
2883 SIVAL(pdata, 36, 0);
2884 data_len = 40;
2886 /* GID list */
2887 for (i = 0; i < current_user.ut.ngroups; ++i) {
2888 SBIG_UINT(pdata, data_len,
2889 (SMB_BIG_UINT)current_user.ut.groups[i]);
2890 data_len += 8;
2893 /* SID list */
2894 for (i = 0;
2895 i < current_user.nt_user_token->num_sids; ++i) {
2896 int sid_len = ndr_size_dom_sid(
2897 &current_user.nt_user_token->user_sids[i], 0);
2899 sid_linearize(pdata + data_len, sid_len,
2900 &current_user.nt_user_token->user_sids[i]);
2901 data_len += sid_len;
2904 break;
2907 case SMB_MAC_QUERY_FS_INFO:
2909 * Thursby MAC extension... ONLY on NTFS filesystems
2910 * once we do streams then we don't need this
2912 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2913 data_len = 88;
2914 SIVAL(pdata,84,0x100); /* Don't support mac... */
2915 break;
2917 /* drop through */
2918 default:
2919 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2920 return;
2924 send_trans2_replies(conn, req, params, 0, pdata, data_len,
2925 max_data_bytes);
2927 DEBUG( 4, ( "%s info_level = %d\n",
2928 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2930 return;
2933 /****************************************************************************
2934 Reply to a TRANS2_SETFSINFO (set filesystem info).
2935 ****************************************************************************/
2937 static void call_trans2setfsinfo(connection_struct *conn,
2938 struct smb_request *req,
2939 char **pparams, int total_params,
2940 char **ppdata, int total_data,
2941 unsigned int max_data_bytes)
2943 char *pdata = *ppdata;
2944 char *params = *pparams;
2945 uint16 info_level;
2947 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2949 /* */
2950 if (total_params < 4) {
2951 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2952 total_params));
2953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2954 return;
2957 info_level = SVAL(params,2);
2959 if (IS_IPC(conn)) {
2960 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
2961 info_level != SMB_SET_CIFS_UNIX_INFO) {
2962 DEBUG(0,("call_trans2setfsinfo: not an allowed "
2963 "info level (0x%x) on IPC$.\n",
2964 (unsigned int)info_level));
2965 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2966 return;
2970 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2971 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
2972 DEBUG(0,("call_trans2setfsinfo: encryption required "
2973 "and info level 0x%x sent.\n",
2974 (unsigned int)info_level));
2975 exit_server_cleanly("encryption required "
2976 "on connection");
2977 return;
2981 switch(info_level) {
2982 case SMB_SET_CIFS_UNIX_INFO:
2984 uint16 client_unix_major;
2985 uint16 client_unix_minor;
2986 uint32 client_unix_cap_low;
2987 uint32 client_unix_cap_high;
2989 if (!lp_unix_extensions()) {
2990 reply_nterror(req,
2991 NT_STATUS_INVALID_LEVEL);
2992 return;
2995 /* There should be 12 bytes of capabilities set. */
2996 if (total_data < 8) {
2997 reply_nterror(
2998 req,
2999 NT_STATUS_INVALID_PARAMETER);
3000 return;
3002 client_unix_major = SVAL(pdata,0);
3003 client_unix_minor = SVAL(pdata,2);
3004 client_unix_cap_low = IVAL(pdata,4);
3005 client_unix_cap_high = IVAL(pdata,8);
3006 /* Just print these values for now. */
3007 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3008 cap_low = 0x%x, cap_high = 0x%x\n",
3009 (unsigned int)client_unix_major,
3010 (unsigned int)client_unix_minor,
3011 (unsigned int)client_unix_cap_low,
3012 (unsigned int)client_unix_cap_high ));
3014 /* Here is where we must switch to posix pathname processing... */
3015 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3016 lp_set_posix_pathnames();
3017 mangle_change_to_posix();
3020 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3021 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3022 /* Client that knows how to do posix locks,
3023 * but not posix open/mkdir operations. Set a
3024 * default type for read/write checks. */
3026 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3029 break;
3032 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3034 NTSTATUS status;
3035 size_t param_len = 0;
3036 size_t data_len = total_data;
3038 if (!lp_unix_extensions()) {
3039 reply_nterror(
3040 req,
3041 NT_STATUS_INVALID_LEVEL);
3042 return;
3045 if (lp_smb_encrypt(SNUM(conn)) == false) {
3046 reply_nterror(
3047 req,
3048 NT_STATUS_NOT_SUPPORTED);
3049 return;
3052 DEBUG( 4,("call_trans2setfsinfo: "
3053 "request transport encrption.\n"));
3055 status = srv_request_encryption_setup(conn,
3056 (unsigned char **)ppdata,
3057 &data_len,
3058 (unsigned char **)pparams,
3059 &param_len);
3061 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3062 !NT_STATUS_IS_OK(status)) {
3063 reply_nterror(req, status);
3064 return;
3067 send_trans2_replies(conn, req,
3068 *pparams,
3069 param_len,
3070 *ppdata,
3071 data_len,
3072 max_data_bytes);
3074 if (NT_STATUS_IS_OK(status)) {
3075 /* Server-side transport
3076 * encryption is now *on*. */
3077 status = srv_encryption_start(conn);
3078 if (!NT_STATUS_IS_OK(status)) {
3079 exit_server_cleanly(
3080 "Failure in setting "
3081 "up encrypted transport");
3084 return;
3087 case SMB_FS_QUOTA_INFORMATION:
3089 files_struct *fsp = NULL;
3090 SMB_NTQUOTA_STRUCT quotas;
3092 ZERO_STRUCT(quotas);
3094 /* access check */
3095 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3096 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3097 lp_servicename(SNUM(conn)),conn->user));
3098 reply_doserror(req, ERRSRV, ERRaccess);
3099 return;
3102 /* note: normaly there're 48 bytes,
3103 * but we didn't use the last 6 bytes for now
3104 * --metze
3106 fsp = file_fsp(SVAL(params,0));
3107 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3108 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3109 reply_nterror(
3110 req, NT_STATUS_INVALID_HANDLE);
3111 return;
3114 if (total_data < 42) {
3115 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3116 total_data));
3117 reply_nterror(
3118 req,
3119 NT_STATUS_INVALID_PARAMETER);
3120 return;
3123 /* unknown_1 24 NULL bytes in pdata*/
3125 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3126 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3127 #ifdef LARGE_SMB_OFF_T
3128 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3129 #else /* LARGE_SMB_OFF_T */
3130 if ((IVAL(pdata,28) != 0)&&
3131 ((quotas.softlim != 0xFFFFFFFF)||
3132 (IVAL(pdata,28)!=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 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3142 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3143 #ifdef LARGE_SMB_OFF_T
3144 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3145 #else /* LARGE_SMB_OFF_T */
3146 if ((IVAL(pdata,36) != 0)&&
3147 ((quotas.hardlim != 0xFFFFFFFF)||
3148 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3149 /* more than 32 bits? */
3150 reply_nterror(
3151 req,
3152 NT_STATUS_INVALID_PARAMETER);
3153 return;
3155 #endif /* LARGE_SMB_OFF_T */
3157 /* quota_flags 2 bytes **/
3158 quotas.qflags = SVAL(pdata,40);
3160 /* unknown_2 6 NULL bytes follow*/
3162 /* now set the quotas */
3163 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3164 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3165 reply_doserror(req, ERRSRV, ERRerror);
3166 return;
3169 break;
3171 default:
3172 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3173 info_level));
3174 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3175 return;
3176 break;
3180 * sending this reply works fine,
3181 * but I'm not sure it's the same
3182 * like windows do...
3183 * --metze
3185 reply_outbuf(req, 10, 0);
3188 #if defined(HAVE_POSIX_ACLS)
3189 /****************************************************************************
3190 Utility function to count the number of entries in a POSIX acl.
3191 ****************************************************************************/
3193 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3195 unsigned int ace_count = 0;
3196 int entry_id = SMB_ACL_FIRST_ENTRY;
3197 SMB_ACL_ENTRY_T entry;
3199 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3200 /* get_next... */
3201 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3202 entry_id = SMB_ACL_NEXT_ENTRY;
3204 ace_count++;
3206 return ace_count;
3209 /****************************************************************************
3210 Utility function to marshall a POSIX acl into wire format.
3211 ****************************************************************************/
3213 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3215 int entry_id = SMB_ACL_FIRST_ENTRY;
3216 SMB_ACL_ENTRY_T entry;
3218 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3219 SMB_ACL_TAG_T tagtype;
3220 SMB_ACL_PERMSET_T permset;
3221 unsigned char perms = 0;
3222 unsigned int own_grp;
3224 /* get_next... */
3225 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3226 entry_id = SMB_ACL_NEXT_ENTRY;
3229 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3230 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3231 return False;
3234 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3235 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3236 return False;
3239 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3240 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3241 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3243 SCVAL(pdata,1,perms);
3245 switch (tagtype) {
3246 case SMB_ACL_USER_OBJ:
3247 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3248 own_grp = (unsigned int)pst->st_uid;
3249 SIVAL(pdata,2,own_grp);
3250 SIVAL(pdata,6,0);
3251 break;
3252 case SMB_ACL_USER:
3254 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3255 if (!puid) {
3256 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3257 return False;
3259 own_grp = (unsigned int)*puid;
3260 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3261 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3262 SIVAL(pdata,2,own_grp);
3263 SIVAL(pdata,6,0);
3264 break;
3266 case SMB_ACL_GROUP_OBJ:
3267 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3268 own_grp = (unsigned int)pst->st_gid;
3269 SIVAL(pdata,2,own_grp);
3270 SIVAL(pdata,6,0);
3271 break;
3272 case SMB_ACL_GROUP:
3274 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3275 if (!pgid) {
3276 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3277 return False;
3279 own_grp = (unsigned int)*pgid;
3280 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3281 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3282 SIVAL(pdata,2,own_grp);
3283 SIVAL(pdata,6,0);
3284 break;
3286 case SMB_ACL_MASK:
3287 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3288 SIVAL(pdata,2,0xFFFFFFFF);
3289 SIVAL(pdata,6,0xFFFFFFFF);
3290 break;
3291 case SMB_ACL_OTHER:
3292 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3293 SIVAL(pdata,2,0xFFFFFFFF);
3294 SIVAL(pdata,6,0xFFFFFFFF);
3295 break;
3296 default:
3297 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3298 return False;
3300 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3303 return True;
3305 #endif
3307 /****************************************************************************
3308 Store the FILE_UNIX_BASIC info.
3309 ****************************************************************************/
3311 static char *store_file_unix_basic(connection_struct *conn,
3312 char *pdata,
3313 files_struct *fsp,
3314 const SMB_STRUCT_STAT *psbuf)
3316 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3317 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3319 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3320 pdata += 8;
3322 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3323 pdata += 8;
3325 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3326 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3327 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3328 pdata += 24;
3330 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3331 SIVAL(pdata,4,0);
3332 pdata += 8;
3334 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3335 SIVAL(pdata,4,0);
3336 pdata += 8;
3338 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3339 pdata += 4;
3341 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3342 SIVAL(pdata,4,0);
3343 pdata += 8;
3345 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3346 SIVAL(pdata,4,0);
3347 pdata += 8;
3349 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3350 pdata += 8;
3352 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3353 SIVAL(pdata,4,0);
3354 pdata += 8;
3356 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3357 SIVAL(pdata,4,0);
3358 pdata += 8;
3360 return pdata;
3363 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3364 * the chflags(2) (or equivalent) flags.
3366 * XXX: this really should be behind the VFS interface. To do this, we would
3367 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3368 * Each VFS module could then implement its own mapping as appropriate for the
3369 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3371 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3372 info2_flags_map[] =
3374 #ifdef UF_NODUMP
3375 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3376 #endif
3378 #ifdef UF_IMMUTABLE
3379 { UF_IMMUTABLE, EXT_IMMUTABLE },
3380 #endif
3382 #ifdef UF_APPEND
3383 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3384 #endif
3386 #ifdef UF_HIDDEN
3387 { UF_HIDDEN, EXT_HIDDEN },
3388 #endif
3390 /* Do not remove. We need to guarantee that this array has at least one
3391 * entry to build on HP-UX.
3393 { 0, 0 }
3397 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3398 uint32 *smb_fflags, uint32 *smb_fmask)
3400 #ifdef HAVE_STAT_ST_FLAGS
3401 int i;
3403 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3404 *smb_fmask |= info2_flags_map[i].smb_fflag;
3405 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3406 *smb_fflags |= info2_flags_map[i].smb_fflag;
3409 #endif /* HAVE_STAT_ST_FLAGS */
3412 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3413 const uint32 smb_fflags,
3414 const uint32 smb_fmask,
3415 int *stat_fflags)
3417 #ifdef HAVE_STAT_ST_FLAGS
3418 uint32 max_fmask = 0;
3419 int i;
3421 *stat_fflags = psbuf->st_flags;
3423 /* For each flags requested in smb_fmask, check the state of the
3424 * corresponding flag in smb_fflags and set or clear the matching
3425 * stat flag.
3428 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3429 max_fmask |= info2_flags_map[i].smb_fflag;
3430 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3431 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3432 *stat_fflags |= info2_flags_map[i].stat_fflag;
3433 } else {
3434 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3439 /* If smb_fmask is asking to set any bits that are not supported by
3440 * our flag mappings, we should fail.
3442 if ((smb_fmask & max_fmask) != smb_fmask) {
3443 return False;
3446 return True;
3447 #else
3448 return False;
3449 #endif /* HAVE_STAT_ST_FLAGS */
3453 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3454 * of file flags and birth (create) time.
3456 static char *store_file_unix_basic_info2(connection_struct *conn,
3457 char *pdata,
3458 files_struct *fsp,
3459 const SMB_STRUCT_STAT *psbuf)
3461 uint32 file_flags = 0;
3462 uint32 flags_mask = 0;
3464 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3466 /* Create (birth) time 64 bit */
3467 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3468 pdata += 8;
3470 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3471 SIVAL(pdata, 0, file_flags); /* flags */
3472 SIVAL(pdata, 4, flags_mask); /* mask */
3473 pdata += 8;
3475 return pdata;
3478 /****************************************************************************
3479 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3480 ****************************************************************************/
3482 static void call_trans2qpipeinfo(connection_struct *conn,
3483 struct smb_request *req,
3484 unsigned int tran_call,
3485 char **pparams, int total_params,
3486 char **ppdata, int total_data,
3487 unsigned int max_data_bytes)
3489 char *params = *pparams;
3490 char *pdata = *ppdata;
3491 unsigned int data_size = 0;
3492 unsigned int param_size = 2;
3493 uint16 info_level;
3494 smb_np_struct *p_pipe = NULL;
3496 if (!params) {
3497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3498 return;
3501 if (total_params < 4) {
3502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3503 return;
3506 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3507 if (p_pipe == NULL) {
3508 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3509 return;
3512 info_level = SVAL(params,2);
3514 *pparams = (char *)SMB_REALLOC(*pparams,2);
3515 if (*pparams == NULL) {
3516 reply_nterror(req, NT_STATUS_NO_MEMORY);
3517 return;
3519 params = *pparams;
3520 SSVAL(params,0,0);
3521 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3522 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3523 if (*ppdata == NULL ) {
3524 reply_nterror(req, NT_STATUS_NO_MEMORY);
3525 return;
3527 pdata = *ppdata;
3529 switch (info_level) {
3530 case SMB_FILE_STANDARD_INFORMATION:
3531 memset(pdata,0,24);
3532 SOFF_T(pdata,0,4096LL);
3533 SIVAL(pdata,16,1);
3534 SIVAL(pdata,20,1);
3535 data_size = 24;
3536 break;
3538 default:
3539 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3540 return;
3543 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3544 max_data_bytes);
3546 return;
3549 /****************************************************************************
3550 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3551 file name or file id).
3552 ****************************************************************************/
3554 static void call_trans2qfilepathinfo(connection_struct *conn,
3555 struct smb_request *req,
3556 unsigned int tran_call,
3557 char **pparams, int total_params,
3558 char **ppdata, int total_data,
3559 unsigned int max_data_bytes)
3561 char *params = *pparams;
3562 char *pdata = *ppdata;
3563 char *dstart, *dend;
3564 uint16 info_level;
3565 int mode=0;
3566 int nlink;
3567 SMB_OFF_T file_size=0;
3568 SMB_BIG_UINT allocation_size=0;
3569 unsigned int data_size = 0;
3570 unsigned int param_size = 2;
3571 SMB_STRUCT_STAT sbuf;
3572 char *dos_fname = NULL;
3573 char *fname = NULL;
3574 char *fullpathname;
3575 char *base_name;
3576 char *p;
3577 SMB_OFF_T pos = 0;
3578 bool delete_pending = False;
3579 int len;
3580 time_t create_time, mtime, atime;
3581 struct timespec create_time_ts, mtime_ts, atime_ts;
3582 files_struct *fsp = NULL;
3583 struct file_id fileid;
3584 struct ea_list *ea_list = NULL;
3585 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3586 char *lock_data = NULL;
3587 TALLOC_CTX *ctx = talloc_tos();
3589 if (!params) {
3590 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3591 return;
3594 ZERO_STRUCT(sbuf);
3596 if (tran_call == TRANSACT2_QFILEINFO) {
3597 if (total_params < 4) {
3598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3599 return;
3602 if (IS_IPC(conn)) {
3603 call_trans2qpipeinfo(conn, req, tran_call,
3604 pparams, total_params,
3605 ppdata, total_data,
3606 max_data_bytes);
3607 return;
3610 fsp = file_fsp(SVAL(params,0));
3611 info_level = SVAL(params,2);
3613 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3615 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3616 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3617 return;
3620 /* Initial check for valid fsp ptr. */
3621 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3622 return;
3625 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3626 if (!fname) {
3627 reply_nterror(req, NT_STATUS_NO_MEMORY);
3628 return;
3631 if(fsp->fake_file_handle) {
3633 * This is actually for the QUOTA_FAKE_FILE --metze
3636 /* We know this name is ok, it's already passed the checks. */
3638 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3640 * This is actually a QFILEINFO on a directory
3641 * handle (returned from an NT SMB). NT5.0 seems
3642 * to do this call. JRA.
3645 if (INFO_LEVEL_IS_UNIX(info_level)) {
3646 /* Always do lstat for UNIX calls. */
3647 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3648 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3649 reply_unixerror(req,ERRDOS,ERRbadpath);
3650 return;
3652 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3653 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3654 reply_unixerror(req, ERRDOS, ERRbadpath);
3655 return;
3658 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3659 delete_pending = get_delete_on_close_flag(fileid);
3660 } else {
3662 * Original code - this is an open file.
3664 if (!check_fsp(conn, req, fsp, &current_user)) {
3665 return;
3668 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3669 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3670 reply_unixerror(req, ERRDOS, ERRbadfid);
3671 return;
3673 pos = fsp->fh->position_information;
3674 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3675 delete_pending = get_delete_on_close_flag(fileid);
3676 access_mask = fsp->access_mask;
3679 } else {
3680 NTSTATUS status = NT_STATUS_OK;
3682 /* qpathinfo */
3683 if (total_params < 7) {
3684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3685 return;
3688 info_level = SVAL(params,0);
3690 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3692 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3693 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3694 return;
3697 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3698 total_params - 6,
3699 STR_TERMINATE, &status);
3700 if (!NT_STATUS_IS_OK(status)) {
3701 reply_nterror(req, status);
3702 return;
3705 status = resolve_dfspath(ctx,
3706 conn,
3707 req->flags2 & FLAGS2_DFS_PATHNAMES,
3708 fname,
3709 &fname);
3710 if (!NT_STATUS_IS_OK(status)) {
3711 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3712 reply_botherror(req,
3713 NT_STATUS_PATH_NOT_COVERED,
3714 ERRSRV, ERRbadpath);
3716 reply_nterror(req, status);
3717 return;
3720 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3721 if (!NT_STATUS_IS_OK(status)) {
3722 reply_nterror(req, status);
3723 return;
3725 status = check_name(conn, fname);
3726 if (!NT_STATUS_IS_OK(status)) {
3727 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3728 reply_nterror(req, status);
3729 return;
3732 if (INFO_LEVEL_IS_UNIX(info_level)) {
3733 /* Always do lstat for UNIX calls. */
3734 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3735 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3736 reply_unixerror(req, ERRDOS, ERRbadpath);
3737 return;
3739 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3740 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3741 reply_unixerror(req, ERRDOS, ERRbadpath);
3742 return;
3745 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3746 delete_pending = get_delete_on_close_flag(fileid);
3747 if (delete_pending) {
3748 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3749 return;
3753 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3754 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3755 return;
3758 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3759 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3761 p = strrchr_m(fname,'/');
3762 if (!p)
3763 base_name = fname;
3764 else
3765 base_name = p+1;
3767 mode = dos_mode(conn,fname,&sbuf);
3768 if (!mode)
3769 mode = FILE_ATTRIBUTE_NORMAL;
3771 nlink = sbuf.st_nlink;
3773 if (nlink && (mode&aDIR)) {
3774 nlink = 1;
3777 if ((nlink > 0) && delete_pending) {
3778 nlink -= 1;
3781 fullpathname = fname;
3782 if (!(mode & aDIR))
3783 file_size = get_file_size(sbuf);
3785 /* Pull out any data sent here before we realloc. */
3786 switch (info_level) {
3787 case SMB_INFO_QUERY_EAS_FROM_LIST:
3789 /* Pull any EA list from the data portion. */
3790 uint32 ea_size;
3792 if (total_data < 4) {
3793 reply_nterror(
3794 req, NT_STATUS_INVALID_PARAMETER);
3795 return;
3797 ea_size = IVAL(pdata,0);
3799 if (total_data > 0 && ea_size != total_data) {
3800 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3801 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3802 reply_nterror(
3803 req, NT_STATUS_INVALID_PARAMETER);
3804 return;
3807 if (!lp_ea_support(SNUM(conn))) {
3808 reply_doserror(req, ERRDOS,
3809 ERReasnotsupported);
3810 return;
3813 /* Pull out the list of names. */
3814 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3815 if (!ea_list) {
3816 reply_nterror(
3817 req, NT_STATUS_INVALID_PARAMETER);
3818 return;
3820 break;
3823 case SMB_QUERY_POSIX_LOCK:
3825 if (fsp == NULL || fsp->fh->fd == -1) {
3826 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3827 return;
3830 if (total_data != POSIX_LOCK_DATA_SIZE) {
3831 reply_nterror(
3832 req, NT_STATUS_INVALID_PARAMETER);
3833 return;
3836 /* Copy the lock range data. */
3837 lock_data = (char *)TALLOC_MEMDUP(
3838 ctx, pdata, total_data);
3839 if (!lock_data) {
3840 reply_nterror(req, NT_STATUS_NO_MEMORY);
3841 return;
3844 default:
3845 break;
3848 *pparams = (char *)SMB_REALLOC(*pparams,2);
3849 if (*pparams == NULL) {
3850 reply_nterror(req, NT_STATUS_NO_MEMORY);
3851 return;
3853 params = *pparams;
3854 SSVAL(params,0,0);
3855 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3856 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3857 if (*ppdata == NULL ) {
3858 reply_nterror(req, NT_STATUS_NO_MEMORY);
3859 return;
3861 pdata = *ppdata;
3862 dstart = pdata;
3863 dend = dstart + data_size - 1;
3865 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3866 mtime_ts = get_mtimespec(&sbuf);
3867 atime_ts = get_atimespec(&sbuf);
3869 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3871 if (fsp) {
3872 if (!null_timespec(fsp->pending_modtime)) {
3873 /* the pending modtime overrides the current modtime */
3874 mtime_ts = fsp->pending_modtime;
3876 } else {
3877 files_struct *fsp1;
3878 /* Do we have this path open ? */
3879 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3880 fsp1 = file_find_di_first(fileid);
3881 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3882 /* the pending modtime overrides the current modtime */
3883 mtime_ts = fsp1->pending_modtime;
3885 if (fsp1 && fsp1->initial_allocation_size) {
3886 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3890 if (lp_dos_filetime_resolution(SNUM(conn))) {
3891 dos_filetime_timespec(&create_time_ts);
3892 dos_filetime_timespec(&mtime_ts);
3893 dos_filetime_timespec(&atime_ts);
3896 create_time = convert_timespec_to_time_t(create_time_ts);
3897 mtime = convert_timespec_to_time_t(mtime_ts);
3898 atime = convert_timespec_to_time_t(atime_ts);
3900 /* NT expects the name to be in an exact form of the *full*
3901 filename. See the trans2 torture test */
3902 if (ISDOT(base_name)) {
3903 dos_fname = talloc_strdup(ctx, "\\");
3904 if (!dos_fname) {
3905 reply_nterror(req, NT_STATUS_NO_MEMORY);
3906 return;
3908 } else {
3909 dos_fname = talloc_asprintf(ctx,
3910 "\\%s",
3911 fname);
3912 if (!dos_fname) {
3913 reply_nterror(req, NT_STATUS_NO_MEMORY);
3914 return;
3916 string_replace(dos_fname, '/', '\\');
3919 switch (info_level) {
3920 case SMB_INFO_STANDARD:
3921 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3922 data_size = 22;
3923 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3924 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3925 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3926 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3927 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3928 SSVAL(pdata,l1_attrFile,mode);
3929 break;
3931 case SMB_INFO_QUERY_EA_SIZE:
3933 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3934 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3935 data_size = 26;
3936 srv_put_dos_date2(pdata,0,create_time);
3937 srv_put_dos_date2(pdata,4,atime);
3938 srv_put_dos_date2(pdata,8,mtime); /* write time */
3939 SIVAL(pdata,12,(uint32)file_size);
3940 SIVAL(pdata,16,(uint32)allocation_size);
3941 SSVAL(pdata,20,mode);
3942 SIVAL(pdata,22,ea_size);
3943 break;
3946 case SMB_INFO_IS_NAME_VALID:
3947 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3948 if (tran_call == TRANSACT2_QFILEINFO) {
3949 /* os/2 needs this ? really ?*/
3950 reply_doserror(req, ERRDOS, ERRbadfunc);
3951 return;
3953 data_size = 0;
3954 param_size = 0;
3955 break;
3957 case SMB_INFO_QUERY_EAS_FROM_LIST:
3959 size_t total_ea_len = 0;
3960 struct ea_list *ea_file_list = NULL;
3962 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3964 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3965 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3967 if (!ea_list || (total_ea_len > data_size)) {
3968 data_size = 4;
3969 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3970 break;
3973 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3974 break;
3977 case SMB_INFO_QUERY_ALL_EAS:
3979 /* We have data_size bytes to put EA's into. */
3980 size_t total_ea_len = 0;
3982 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3984 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3985 if (!ea_list || (total_ea_len > data_size)) {
3986 data_size = 4;
3987 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3988 break;
3991 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3992 break;
3995 case SMB_FILE_BASIC_INFORMATION:
3996 case SMB_QUERY_FILE_BASIC_INFO:
3998 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3999 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4000 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4001 } else {
4002 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4003 data_size = 40;
4004 SIVAL(pdata,36,0);
4006 put_long_date_timespec(pdata,create_time_ts);
4007 put_long_date_timespec(pdata+8,atime_ts);
4008 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4009 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4010 SIVAL(pdata,32,mode);
4012 DEBUG(5,("SMB_QFBI - "));
4013 DEBUG(5,("create: %s ", ctime(&create_time)));
4014 DEBUG(5,("access: %s ", ctime(&atime)));
4015 DEBUG(5,("write: %s ", ctime(&mtime)));
4016 DEBUG(5,("change: %s ", ctime(&mtime)));
4017 DEBUG(5,("mode: %x\n", mode));
4018 break;
4020 case SMB_FILE_STANDARD_INFORMATION:
4021 case SMB_QUERY_FILE_STANDARD_INFO:
4023 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4024 data_size = 24;
4025 SOFF_T(pdata,0,allocation_size);
4026 SOFF_T(pdata,8,file_size);
4027 SIVAL(pdata,16,nlink);
4028 SCVAL(pdata,20,delete_pending?1:0);
4029 SCVAL(pdata,21,(mode&aDIR)?1:0);
4030 SSVAL(pdata,22,0); /* Padding. */
4031 break;
4033 case SMB_FILE_EA_INFORMATION:
4034 case SMB_QUERY_FILE_EA_INFO:
4036 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4037 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4038 data_size = 4;
4039 SIVAL(pdata,0,ea_size);
4040 break;
4043 /* Get the 8.3 name - used if NT SMB was negotiated. */
4044 case SMB_QUERY_FILE_ALT_NAME_INFO:
4045 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4047 char mangled_name[13];
4048 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4049 if (!name_to_8_3(base_name,mangled_name,
4050 True,conn->params)) {
4051 reply_nterror(
4052 req,
4053 NT_STATUS_NO_MEMORY);
4055 len = srvstr_push(dstart, req->flags2,
4056 pdata+4, mangled_name,
4057 PTR_DIFF(dend, pdata+4),
4058 STR_UNICODE);
4059 data_size = 4 + len;
4060 SIVAL(pdata,0,len);
4061 break;
4064 case SMB_QUERY_FILE_NAME_INFO:
4066 this must be *exactly* right for ACLs on mapped drives to work
4068 len = srvstr_push(dstart, req->flags2,
4069 pdata+4, dos_fname,
4070 PTR_DIFF(dend, pdata+4),
4071 STR_UNICODE);
4072 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4073 data_size = 4 + len;
4074 SIVAL(pdata,0,len);
4075 break;
4077 case SMB_FILE_ALLOCATION_INFORMATION:
4078 case SMB_QUERY_FILE_ALLOCATION_INFO:
4079 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4080 data_size = 8;
4081 SOFF_T(pdata,0,allocation_size);
4082 break;
4084 case SMB_FILE_END_OF_FILE_INFORMATION:
4085 case SMB_QUERY_FILE_END_OF_FILEINFO:
4086 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4087 data_size = 8;
4088 SOFF_T(pdata,0,file_size);
4089 break;
4091 case SMB_QUERY_FILE_ALL_INFO:
4092 case SMB_FILE_ALL_INFORMATION:
4094 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4095 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4096 put_long_date_timespec(pdata,create_time_ts);
4097 put_long_date_timespec(pdata+8,atime_ts);
4098 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4099 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4100 SIVAL(pdata,32,mode);
4101 SIVAL(pdata,36,0); /* padding. */
4102 pdata += 40;
4103 SOFF_T(pdata,0,allocation_size);
4104 SOFF_T(pdata,8,file_size);
4105 SIVAL(pdata,16,nlink);
4106 SCVAL(pdata,20,delete_pending);
4107 SCVAL(pdata,21,(mode&aDIR)?1:0);
4108 SSVAL(pdata,22,0);
4109 pdata += 24;
4110 SIVAL(pdata,0,ea_size);
4111 pdata += 4; /* EA info */
4112 len = srvstr_push(dstart, req->flags2,
4113 pdata+4, dos_fname,
4114 PTR_DIFF(dend, pdata+4),
4115 STR_UNICODE);
4116 SIVAL(pdata,0,len);
4117 pdata += 4 + len;
4118 data_size = PTR_DIFF(pdata,(*ppdata));
4119 break;
4121 case SMB_FILE_INTERNAL_INFORMATION:
4122 /* This should be an index number - looks like
4123 dev/ino to me :-)
4125 I think this causes us to fail the IFSKIT
4126 BasicFileInformationTest. -tpot */
4128 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4129 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4130 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4131 data_size = 8;
4132 break;
4134 case SMB_FILE_ACCESS_INFORMATION:
4135 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4136 SIVAL(pdata,0,access_mask);
4137 data_size = 4;
4138 break;
4140 case SMB_FILE_NAME_INFORMATION:
4141 /* Pathname with leading '\'. */
4143 size_t byte_len;
4144 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4145 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4146 SIVAL(pdata,0,byte_len);
4147 data_size = 4 + byte_len;
4148 break;
4151 case SMB_FILE_DISPOSITION_INFORMATION:
4152 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4153 data_size = 1;
4154 SCVAL(pdata,0,delete_pending);
4155 break;
4157 case SMB_FILE_POSITION_INFORMATION:
4158 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4159 data_size = 8;
4160 SOFF_T(pdata,0,pos);
4161 break;
4163 case SMB_FILE_MODE_INFORMATION:
4164 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4165 SIVAL(pdata,0,mode);
4166 data_size = 4;
4167 break;
4169 case SMB_FILE_ALIGNMENT_INFORMATION:
4170 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4171 SIVAL(pdata,0,0); /* No alignment needed. */
4172 data_size = 4;
4173 break;
4175 #if 0
4177 * NT4 server just returns "invalid query" to this - if we try to answer
4178 * it then NTws gets a BSOD! (tridge).
4179 * W2K seems to want this. JRA.
4181 case SMB_QUERY_FILE_STREAM_INFO:
4182 #endif
4183 case SMB_FILE_STREAM_INFORMATION:
4184 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4185 if (mode & aDIR) {
4186 data_size = 0;
4187 } else {
4188 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4189 SIVAL(pdata,0,0); /* ??? */
4190 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4191 SOFF_T(pdata,8,file_size);
4192 SOFF_T(pdata,16,allocation_size);
4193 data_size = 24 + byte_len;
4195 break;
4197 case SMB_QUERY_COMPRESSION_INFO:
4198 case SMB_FILE_COMPRESSION_INFORMATION:
4199 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4200 SOFF_T(pdata,0,file_size);
4201 SIVAL(pdata,8,0); /* ??? */
4202 SIVAL(pdata,12,0); /* ??? */
4203 data_size = 16;
4204 break;
4206 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4207 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4208 put_long_date_timespec(pdata,create_time_ts);
4209 put_long_date_timespec(pdata+8,atime_ts);
4210 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4211 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4212 SOFF_T(pdata,32,allocation_size);
4213 SOFF_T(pdata,40,file_size);
4214 SIVAL(pdata,48,mode);
4215 SIVAL(pdata,52,0); /* ??? */
4216 data_size = 56;
4217 break;
4219 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4220 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4221 SIVAL(pdata,0,mode);
4222 SIVAL(pdata,4,0);
4223 data_size = 8;
4224 break;
4227 * CIFS UNIX Extensions.
4230 case SMB_QUERY_FILE_UNIX_BASIC:
4232 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4233 data_size = PTR_DIFF(pdata,(*ppdata));
4236 int i;
4237 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4239 for (i=0; i<100; i++)
4240 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4241 DEBUG(4,("\n"));
4244 break;
4246 case SMB_QUERY_FILE_UNIX_INFO2:
4248 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4249 data_size = PTR_DIFF(pdata,(*ppdata));
4252 int i;
4253 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4255 for (i=0; i<100; i++)
4256 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4257 DEBUG(4,("\n"));
4260 break;
4262 case SMB_QUERY_FILE_UNIX_LINK:
4264 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4266 if (!buffer) {
4267 reply_nterror(req, NT_STATUS_NO_MEMORY);
4268 return;
4271 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4272 #ifdef S_ISLNK
4273 if(!S_ISLNK(sbuf.st_mode)) {
4274 reply_unixerror(req, ERRSRV,
4275 ERRbadlink);
4276 return;
4278 #else
4279 reply_unixerror(req, ERRDOS, ERRbadlink);
4280 return;
4281 #endif
4282 len = SMB_VFS_READLINK(conn,fullpathname,
4283 buffer, PATH_MAX);
4284 if (len == -1) {
4285 reply_unixerror(req, ERRDOS,
4286 ERRnoaccess);
4287 return;
4289 buffer[len] = 0;
4290 len = srvstr_push(dstart, req->flags2,
4291 pdata, buffer,
4292 PTR_DIFF(dend, pdata),
4293 STR_TERMINATE);
4294 pdata += len;
4295 data_size = PTR_DIFF(pdata,(*ppdata));
4297 break;
4300 #if defined(HAVE_POSIX_ACLS)
4301 case SMB_QUERY_POSIX_ACL:
4303 SMB_ACL_T file_acl = NULL;
4304 SMB_ACL_T def_acl = NULL;
4305 uint16 num_file_acls = 0;
4306 uint16 num_def_acls = 0;
4308 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4309 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4310 } else {
4311 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4314 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4315 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4316 fname ));
4317 reply_nterror(
4318 req,
4319 NT_STATUS_NOT_IMPLEMENTED);
4320 return;
4323 if (S_ISDIR(sbuf.st_mode)) {
4324 if (fsp && fsp->is_directory) {
4325 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4326 } else {
4327 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4329 def_acl = free_empty_sys_acl(conn, def_acl);
4332 num_file_acls = count_acl_entries(conn, file_acl);
4333 num_def_acls = count_acl_entries(conn, def_acl);
4335 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4336 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4337 data_size,
4338 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4339 SMB_POSIX_ACL_HEADER_SIZE) ));
4340 if (file_acl) {
4341 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4343 if (def_acl) {
4344 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4346 reply_nterror(
4347 req,
4348 NT_STATUS_BUFFER_TOO_SMALL);
4349 return;
4352 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4353 SSVAL(pdata,2,num_file_acls);
4354 SSVAL(pdata,4,num_def_acls);
4355 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4356 if (file_acl) {
4357 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4359 if (def_acl) {
4360 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4362 reply_nterror(
4363 req, NT_STATUS_INTERNAL_ERROR);
4364 return;
4366 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4367 if (file_acl) {
4368 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4370 if (def_acl) {
4371 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4373 reply_nterror(
4374 req,
4375 NT_STATUS_INTERNAL_ERROR);
4376 return;
4379 if (file_acl) {
4380 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4382 if (def_acl) {
4383 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4385 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4386 break;
4388 #endif
4391 case SMB_QUERY_POSIX_LOCK:
4393 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4394 SMB_BIG_UINT count;
4395 SMB_BIG_UINT offset;
4396 uint32 lock_pid;
4397 enum brl_type lock_type;
4399 if (total_data != POSIX_LOCK_DATA_SIZE) {
4400 reply_nterror(
4401 req, NT_STATUS_INVALID_PARAMETER);
4402 return;
4405 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4406 case POSIX_LOCK_TYPE_READ:
4407 lock_type = READ_LOCK;
4408 break;
4409 case POSIX_LOCK_TYPE_WRITE:
4410 lock_type = WRITE_LOCK;
4411 break;
4412 case POSIX_LOCK_TYPE_UNLOCK:
4413 default:
4414 /* There's no point in asking for an unlock... */
4415 reply_nterror(
4416 req,
4417 NT_STATUS_INVALID_PARAMETER);
4418 return;
4421 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4422 #if defined(HAVE_LONGLONG)
4423 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4424 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4425 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4426 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4427 #else /* HAVE_LONGLONG */
4428 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4429 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4430 #endif /* HAVE_LONGLONG */
4432 status = query_lock(fsp,
4433 &lock_pid,
4434 &count,
4435 &offset,
4436 &lock_type,
4437 POSIX_LOCK);
4439 if (ERROR_WAS_LOCK_DENIED(status)) {
4440 /* Here we need to report who has it locked... */
4441 data_size = POSIX_LOCK_DATA_SIZE;
4443 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4444 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4445 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4446 #if defined(HAVE_LONGLONG)
4447 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4448 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4449 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4450 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4451 #else /* HAVE_LONGLONG */
4452 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4453 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4454 #endif /* HAVE_LONGLONG */
4456 } else if (NT_STATUS_IS_OK(status)) {
4457 /* For success we just return a copy of what we sent
4458 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4459 data_size = POSIX_LOCK_DATA_SIZE;
4460 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4461 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4462 } else {
4463 reply_nterror(req, status);
4464 return;
4466 break;
4469 default:
4470 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4471 return;
4474 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4475 max_data_bytes);
4477 return;
4480 /****************************************************************************
4481 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4482 code.
4483 ****************************************************************************/
4485 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4486 connection_struct *conn,
4487 const char *oldname_in,
4488 const char *newname_in)
4490 SMB_STRUCT_STAT sbuf1, sbuf2;
4491 char *last_component_oldname = NULL;
4492 char *last_component_newname = NULL;
4493 char *oldname = NULL;
4494 char *newname = NULL;
4495 NTSTATUS status = NT_STATUS_OK;
4497 ZERO_STRUCT(sbuf1);
4498 ZERO_STRUCT(sbuf2);
4500 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4501 &last_component_oldname, &sbuf1);
4502 if (!NT_STATUS_IS_OK(status)) {
4503 return status;
4506 status = check_name(conn, oldname);
4507 if (!NT_STATUS_IS_OK(status)) {
4508 return status;
4511 /* source must already exist. */
4512 if (!VALID_STAT(sbuf1)) {
4513 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4516 status = unix_convert(ctx, conn, newname_in, False, &newname,
4517 &last_component_newname, &sbuf2);
4518 if (!NT_STATUS_IS_OK(status)) {
4519 return status;
4522 status = check_name(conn, newname);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 return status;
4527 /* Disallow if newname already exists. */
4528 if (VALID_STAT(sbuf2)) {
4529 return NT_STATUS_OBJECT_NAME_COLLISION;
4532 /* No links from a directory. */
4533 if (S_ISDIR(sbuf1.st_mode)) {
4534 return NT_STATUS_FILE_IS_A_DIRECTORY;
4537 /* Ensure this is within the share. */
4538 status = check_reduced_name(conn, oldname);
4539 if (!NT_STATUS_IS_OK(status)) {
4540 return status;
4543 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4545 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4546 status = map_nt_error_from_unix(errno);
4547 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4548 nt_errstr(status), newname, oldname));
4551 return status;
4554 /****************************************************************************
4555 Deal with setting the time from any of the setfilepathinfo functions.
4556 ****************************************************************************/
4558 static NTSTATUS smb_set_file_time(connection_struct *conn,
4559 files_struct *fsp,
4560 const char *fname,
4561 const SMB_STRUCT_STAT *psbuf,
4562 struct timespec ts[2],
4563 bool setting_write_time)
4565 uint32 action =
4566 FILE_NOTIFY_CHANGE_LAST_ACCESS
4567 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4569 if (!VALID_STAT(*psbuf)) {
4570 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4573 /* get some defaults (no modifications) if any info is zero or -1. */
4574 if (null_timespec(ts[0])) {
4575 ts[0] = get_atimespec(psbuf);
4576 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4579 if (null_timespec(ts[1])) {
4580 ts[1] = get_mtimespec(psbuf);
4581 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4584 if (!setting_write_time) {
4585 /* ts[1] comes from change time, not write time. */
4586 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4589 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4590 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4593 * Try and set the times of this file if
4594 * they are different from the current values.
4598 struct timespec mts = get_mtimespec(psbuf);
4599 struct timespec ats = get_atimespec(psbuf);
4600 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4601 return NT_STATUS_OK;
4605 if(fsp != NULL) {
4607 * This was a setfileinfo on an open file.
4608 * NT does this a lot. We also need to
4609 * set the time here, as it can be read by
4610 * FindFirst/FindNext and with the patch for bug #2045
4611 * in smbd/fileio.c it ensures that this timestamp is
4612 * kept sticky even after a write. We save the request
4613 * away and will set it on file close and after a write. JRA.
4616 if (!null_timespec(ts[1])) {
4617 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4618 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4619 fsp_set_pending_modtime(fsp, ts[1]);
4623 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4625 if(file_ntimes(conn, fname, ts)!=0) {
4626 return map_nt_error_from_unix(errno);
4628 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4630 return NT_STATUS_OK;
4633 /****************************************************************************
4634 Deal with setting the dosmode from any of the setfilepathinfo functions.
4635 ****************************************************************************/
4637 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4638 const char *fname,
4639 SMB_STRUCT_STAT *psbuf,
4640 uint32 dosmode)
4642 if (!VALID_STAT(*psbuf)) {
4643 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4646 if (dosmode) {
4647 if (S_ISDIR(psbuf->st_mode)) {
4648 dosmode |= aDIR;
4649 } else {
4650 dosmode &= ~aDIR;
4654 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4656 /* check the mode isn't different, before changing it */
4657 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4659 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4660 fname, (unsigned int)dosmode ));
4662 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4663 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4664 fname, strerror(errno)));
4665 return map_nt_error_from_unix(errno);
4668 return NT_STATUS_OK;
4671 /****************************************************************************
4672 Deal with setting the size from any of the setfilepathinfo functions.
4673 ****************************************************************************/
4675 static NTSTATUS smb_set_file_size(connection_struct *conn,
4676 struct smb_request *req,
4677 files_struct *fsp,
4678 const char *fname,
4679 SMB_STRUCT_STAT *psbuf,
4680 SMB_OFF_T size)
4682 NTSTATUS status = NT_STATUS_OK;
4683 files_struct *new_fsp = NULL;
4685 if (!VALID_STAT(*psbuf)) {
4686 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4689 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4691 if (size == get_file_size(*psbuf)) {
4692 return NT_STATUS_OK;
4695 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4696 fname, (double)size ));
4698 if (fsp && fsp->fh->fd != -1) {
4699 /* Handle based call. */
4700 if (vfs_set_filelen(fsp, size) == -1) {
4701 return map_nt_error_from_unix(errno);
4703 return NT_STATUS_OK;
4706 status = open_file_ntcreate(conn, req, fname, psbuf,
4707 FILE_WRITE_DATA,
4708 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4709 FILE_OPEN,
4711 FILE_ATTRIBUTE_NORMAL,
4712 FORCE_OPLOCK_BREAK_TO_NONE,
4713 NULL, &new_fsp);
4715 if (!NT_STATUS_IS_OK(status)) {
4716 /* NB. We check for open_was_deferred in the caller. */
4717 return status;
4720 if (vfs_set_filelen(new_fsp, size) == -1) {
4721 status = map_nt_error_from_unix(errno);
4722 close_file(new_fsp,NORMAL_CLOSE);
4723 return status;
4726 close_file(new_fsp,NORMAL_CLOSE);
4727 return NT_STATUS_OK;
4730 /****************************************************************************
4731 Deal with SMB_INFO_SET_EA.
4732 ****************************************************************************/
4734 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4735 const char *pdata,
4736 int total_data,
4737 files_struct *fsp,
4738 const char *fname)
4740 struct ea_list *ea_list = NULL;
4741 TALLOC_CTX *ctx = NULL;
4742 NTSTATUS status = NT_STATUS_OK;
4744 if (total_data < 10) {
4746 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4747 length. They seem to have no effect. Bug #3212. JRA */
4749 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4750 /* We're done. We only get EA info in this call. */
4751 return NT_STATUS_OK;
4754 return NT_STATUS_INVALID_PARAMETER;
4757 if (IVAL(pdata,0) > total_data) {
4758 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4759 IVAL(pdata,0), (unsigned int)total_data));
4760 return NT_STATUS_INVALID_PARAMETER;
4763 ctx = talloc_tos();
4764 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4765 if (!ea_list) {
4766 return NT_STATUS_INVALID_PARAMETER;
4768 status = set_ea(conn, fsp, fname, ea_list);
4770 return status;
4773 /****************************************************************************
4774 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4775 ****************************************************************************/
4777 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4778 const char *pdata,
4779 int total_data,
4780 files_struct *fsp,
4781 const char *fname,
4782 SMB_STRUCT_STAT *psbuf)
4784 NTSTATUS status = NT_STATUS_OK;
4785 bool delete_on_close;
4786 uint32 dosmode = 0;
4788 if (total_data < 1) {
4789 return NT_STATUS_INVALID_PARAMETER;
4792 if (fsp == NULL) {
4793 return NT_STATUS_INVALID_HANDLE;
4796 delete_on_close = (CVAL(pdata,0) ? True : False);
4797 dosmode = dos_mode(conn, fname, psbuf);
4799 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4800 "delete_on_close = %u\n",
4801 fsp->fsp_name,
4802 (unsigned int)dosmode,
4803 (unsigned int)delete_on_close ));
4805 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4807 if (!NT_STATUS_IS_OK(status)) {
4808 return status;
4811 /* The set is across all open files on this dev/inode pair. */
4812 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4813 return NT_STATUS_ACCESS_DENIED;
4815 return NT_STATUS_OK;
4818 /****************************************************************************
4819 Deal with SMB_FILE_POSITION_INFORMATION.
4820 ****************************************************************************/
4822 static NTSTATUS smb_file_position_information(connection_struct *conn,
4823 const char *pdata,
4824 int total_data,
4825 files_struct *fsp)
4827 SMB_BIG_UINT position_information;
4829 if (total_data < 8) {
4830 return NT_STATUS_INVALID_PARAMETER;
4833 if (fsp == NULL) {
4834 /* Ignore on pathname based set. */
4835 return NT_STATUS_OK;
4838 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4839 #ifdef LARGE_SMB_OFF_T
4840 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4841 #else /* LARGE_SMB_OFF_T */
4842 if (IVAL(pdata,4) != 0) {
4843 /* more than 32 bits? */
4844 return NT_STATUS_INVALID_PARAMETER;
4846 #endif /* LARGE_SMB_OFF_T */
4848 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4849 fsp->fsp_name, (double)position_information ));
4850 fsp->fh->position_information = position_information;
4851 return NT_STATUS_OK;
4854 /****************************************************************************
4855 Deal with SMB_FILE_MODE_INFORMATION.
4856 ****************************************************************************/
4858 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4859 const char *pdata,
4860 int total_data)
4862 uint32 mode;
4864 if (total_data < 4) {
4865 return NT_STATUS_INVALID_PARAMETER;
4867 mode = IVAL(pdata,0);
4868 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4869 return NT_STATUS_INVALID_PARAMETER;
4871 return NT_STATUS_OK;
4874 /****************************************************************************
4875 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4876 ****************************************************************************/
4878 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4879 struct smb_request *req,
4880 const char *pdata,
4881 int total_data,
4882 const char *fname)
4884 char *link_target = NULL;
4885 const char *newname = fname;
4886 NTSTATUS status = NT_STATUS_OK;
4887 TALLOC_CTX *ctx = talloc_tos();
4889 /* Set a symbolic link. */
4890 /* Don't allow this if follow links is false. */
4892 if (total_data == 0) {
4893 return NT_STATUS_INVALID_PARAMETER;
4896 if (!lp_symlinks(SNUM(conn))) {
4897 return NT_STATUS_ACCESS_DENIED;
4900 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4901 total_data, STR_TERMINATE);
4903 if (!link_target) {
4904 return NT_STATUS_INVALID_PARAMETER;
4907 /* !widelinks forces the target path to be within the share. */
4908 /* This means we can interpret the target as a pathname. */
4909 if (!lp_widelinks(SNUM(conn))) {
4910 char *rel_name = NULL;
4911 char *last_dirp = NULL;
4913 if (*link_target == '/') {
4914 /* No absolute paths allowed. */
4915 return NT_STATUS_ACCESS_DENIED;
4917 rel_name = talloc_strdup(ctx,newname);
4918 if (!rel_name) {
4919 return NT_STATUS_NO_MEMORY;
4921 last_dirp = strrchr_m(rel_name, '/');
4922 if (last_dirp) {
4923 last_dirp[1] = '\0';
4924 } else {
4925 rel_name = talloc_strdup(ctx,"./");
4926 if (!rel_name) {
4927 return NT_STATUS_NO_MEMORY;
4930 rel_name = talloc_asprintf_append(rel_name,
4931 "%s",
4932 link_target);
4933 if (!rel_name) {
4934 return NT_STATUS_NO_MEMORY;
4937 status = check_name(conn, rel_name);
4938 if (!NT_STATUS_IS_OK(status)) {
4939 return status;
4943 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4944 newname, link_target ));
4946 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4947 return map_nt_error_from_unix(errno);
4950 return NT_STATUS_OK;
4953 /****************************************************************************
4954 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4955 ****************************************************************************/
4957 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4958 struct smb_request *req,
4959 const char *pdata, int total_data,
4960 const char *fname)
4962 char *oldname = NULL;
4963 TALLOC_CTX *ctx = talloc_tos();
4964 NTSTATUS status = NT_STATUS_OK;
4966 /* Set a hard link. */
4967 if (total_data == 0) {
4968 return NT_STATUS_INVALID_PARAMETER;
4971 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4972 total_data, STR_TERMINATE, &status);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 return status;
4977 status = resolve_dfspath(ctx, conn,
4978 req->flags2 & FLAGS2_DFS_PATHNAMES,
4979 oldname,
4980 &oldname);
4981 if (!NT_STATUS_IS_OK(status)) {
4982 return status;
4985 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4986 fname, oldname));
4988 return hardlink_internals(ctx, conn, oldname, fname);
4991 /****************************************************************************
4992 Deal with SMB_FILE_RENAME_INFORMATION.
4993 ****************************************************************************/
4995 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4996 struct smb_request *req,
4997 const char *pdata,
4998 int total_data,
4999 files_struct *fsp,
5000 const char *fname)
5002 bool overwrite;
5003 uint32 root_fid;
5004 uint32 len;
5005 char *newname = NULL;
5006 char *base_name = NULL;
5007 bool dest_has_wcard = False;
5008 NTSTATUS status = NT_STATUS_OK;
5009 char *p;
5010 TALLOC_CTX *ctx = talloc_tos();
5012 if (total_data < 13) {
5013 return NT_STATUS_INVALID_PARAMETER;
5016 overwrite = (CVAL(pdata,0) ? True : False);
5017 root_fid = IVAL(pdata,4);
5018 len = IVAL(pdata,8);
5020 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5021 return NT_STATUS_INVALID_PARAMETER;
5024 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5025 len, 0, &status,
5026 &dest_has_wcard);
5027 if (!NT_STATUS_IS_OK(status)) {
5028 return status;
5031 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5032 newname));
5034 status = resolve_dfspath_wcard(ctx, conn,
5035 req->flags2 & FLAGS2_DFS_PATHNAMES,
5036 newname,
5037 &newname,
5038 &dest_has_wcard);
5039 if (!NT_STATUS_IS_OK(status)) {
5040 return status;
5043 /* Check the new name has no '/' characters. */
5044 if (strchr_m(newname, '/')) {
5045 return NT_STATUS_NOT_SUPPORTED;
5048 /* Create the base directory. */
5049 base_name = talloc_strdup(ctx, fname);
5050 if (!base_name) {
5051 return NT_STATUS_NO_MEMORY;
5053 p = strrchr_m(base_name, '/');
5054 if (p) {
5055 p[1] = '\0';
5056 } else {
5057 base_name = talloc_strdup(ctx, "./");
5058 if (!base_name) {
5059 return NT_STATUS_NO_MEMORY;
5062 /* Append the new name. */
5063 base_name = talloc_asprintf_append(base_name,
5064 "%s",
5065 newname);
5066 if (!base_name) {
5067 return NT_STATUS_NO_MEMORY;
5070 if (fsp) {
5071 SMB_STRUCT_STAT sbuf;
5072 char *newname_last_component = NULL;
5074 ZERO_STRUCT(sbuf);
5076 status = unix_convert(ctx, conn, newname, False,
5077 &newname,
5078 &newname_last_component,
5079 &sbuf);
5081 /* If an error we expect this to be
5082 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5084 if (!NT_STATUS_IS_OK(status)
5085 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5086 status)) {
5087 return status;
5090 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5091 fsp->fnum, fsp->fsp_name, base_name ));
5092 status = rename_internals_fsp(conn, fsp, base_name,
5093 newname_last_component, 0,
5094 overwrite);
5095 } else {
5096 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5097 fname, base_name ));
5098 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5099 overwrite, False, dest_has_wcard);
5102 return status;
5105 /****************************************************************************
5106 Deal with SMB_SET_POSIX_ACL.
5107 ****************************************************************************/
5109 #if defined(HAVE_POSIX_ACLS)
5110 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5111 const char *pdata,
5112 int total_data,
5113 files_struct *fsp,
5114 const char *fname,
5115 SMB_STRUCT_STAT *psbuf)
5117 uint16 posix_acl_version;
5118 uint16 num_file_acls;
5119 uint16 num_def_acls;
5120 bool valid_file_acls = True;
5121 bool valid_def_acls = True;
5123 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5124 return NT_STATUS_INVALID_PARAMETER;
5126 posix_acl_version = SVAL(pdata,0);
5127 num_file_acls = SVAL(pdata,2);
5128 num_def_acls = SVAL(pdata,4);
5130 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5131 valid_file_acls = False;
5132 num_file_acls = 0;
5135 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5136 valid_def_acls = False;
5137 num_def_acls = 0;
5140 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5141 return NT_STATUS_INVALID_PARAMETER;
5144 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5145 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5146 return NT_STATUS_INVALID_PARAMETER;
5149 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5150 fname ? fname : fsp->fsp_name,
5151 (unsigned int)num_file_acls,
5152 (unsigned int)num_def_acls));
5154 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5155 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5156 return map_nt_error_from_unix(errno);
5159 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5160 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5161 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5162 return map_nt_error_from_unix(errno);
5164 return NT_STATUS_OK;
5166 #endif
5168 /****************************************************************************
5169 Deal with SMB_SET_POSIX_LOCK.
5170 ****************************************************************************/
5172 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5173 const struct smb_request *req,
5174 const char *pdata,
5175 int total_data,
5176 files_struct *fsp)
5178 SMB_BIG_UINT count;
5179 SMB_BIG_UINT offset;
5180 uint32 lock_pid;
5181 bool blocking_lock = False;
5182 enum brl_type lock_type;
5184 NTSTATUS status = NT_STATUS_OK;
5186 if (fsp == NULL || fsp->fh->fd == -1) {
5187 return NT_STATUS_INVALID_HANDLE;
5190 if (total_data != POSIX_LOCK_DATA_SIZE) {
5191 return NT_STATUS_INVALID_PARAMETER;
5194 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5195 case POSIX_LOCK_TYPE_READ:
5196 lock_type = READ_LOCK;
5197 break;
5198 case POSIX_LOCK_TYPE_WRITE:
5199 /* Return the right POSIX-mappable error code for files opened read-only. */
5200 if (!fsp->can_write) {
5201 return NT_STATUS_INVALID_HANDLE;
5203 lock_type = WRITE_LOCK;
5204 break;
5205 case POSIX_LOCK_TYPE_UNLOCK:
5206 lock_type = UNLOCK_LOCK;
5207 break;
5208 default:
5209 return NT_STATUS_INVALID_PARAMETER;
5212 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5213 blocking_lock = False;
5214 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5215 blocking_lock = True;
5216 } else {
5217 return NT_STATUS_INVALID_PARAMETER;
5220 if (!lp_blocking_locks(SNUM(conn))) {
5221 blocking_lock = False;
5224 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5225 #if defined(HAVE_LONGLONG)
5226 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5227 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5228 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5229 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5230 #else /* HAVE_LONGLONG */
5231 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5232 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5233 #endif /* HAVE_LONGLONG */
5235 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5236 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5237 fsp->fsp_name,
5238 (unsigned int)lock_type,
5239 (unsigned int)lock_pid,
5240 (double)count,
5241 (double)offset ));
5243 if (lock_type == UNLOCK_LOCK) {
5244 status = do_unlock(smbd_messaging_context(),
5245 fsp,
5246 lock_pid,
5247 count,
5248 offset,
5249 POSIX_LOCK);
5250 } else {
5251 uint32 block_smbpid;
5253 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5254 fsp,
5255 lock_pid,
5256 count,
5257 offset,
5258 lock_type,
5259 POSIX_LOCK,
5260 blocking_lock,
5261 &status,
5262 &block_smbpid);
5264 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5266 * A blocking lock was requested. Package up
5267 * this smb into a queued request and push it
5268 * onto the blocking lock queue.
5270 if(push_blocking_lock_request(br_lck,
5271 req,
5272 fsp,
5273 -1, /* infinite timeout. */
5275 lock_pid,
5276 lock_type,
5277 POSIX_LOCK,
5278 offset,
5279 count,
5280 block_smbpid)) {
5281 TALLOC_FREE(br_lck);
5282 return status;
5285 TALLOC_FREE(br_lck);
5288 return status;
5291 /****************************************************************************
5292 Deal with SMB_INFO_STANDARD.
5293 ****************************************************************************/
5295 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5296 const char *pdata,
5297 int total_data,
5298 files_struct *fsp,
5299 const char *fname,
5300 const SMB_STRUCT_STAT *psbuf)
5302 struct timespec ts[2];
5304 if (total_data < 12) {
5305 return NT_STATUS_INVALID_PARAMETER;
5308 /* access time */
5309 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5310 /* write time */
5311 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5313 DEBUG(10,("smb_set_info_standard: file %s\n",
5314 fname ? fname : fsp->fsp_name ));
5316 return smb_set_file_time(conn,
5317 fsp,
5318 fname,
5319 psbuf,
5321 true);
5324 /****************************************************************************
5325 Deal with SMB_SET_FILE_BASIC_INFO.
5326 ****************************************************************************/
5328 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5329 const char *pdata,
5330 int total_data,
5331 files_struct *fsp,
5332 const char *fname,
5333 SMB_STRUCT_STAT *psbuf)
5335 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5336 struct timespec write_time;
5337 struct timespec changed_time;
5338 uint32 dosmode = 0;
5339 struct timespec ts[2];
5340 NTSTATUS status = NT_STATUS_OK;
5341 bool setting_write_time = true;
5343 if (total_data < 36) {
5344 return NT_STATUS_INVALID_PARAMETER;
5347 /* Set the attributes */
5348 dosmode = IVAL(pdata,32);
5349 status = smb_set_file_dosmode(conn,
5350 fname,
5351 psbuf,
5352 dosmode);
5353 if (!NT_STATUS_IS_OK(status)) {
5354 return status;
5357 /* Ignore create time at offset pdata. */
5359 /* access time */
5360 ts[0] = interpret_long_date(pdata+8);
5362 write_time = interpret_long_date(pdata+16);
5363 changed_time = interpret_long_date(pdata+24);
5365 /* mtime */
5366 ts[1] = timespec_min(&write_time, &changed_time);
5368 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5369 ts[1] = write_time;
5372 /* Prefer a defined time to an undefined one. */
5373 if (null_timespec(ts[1])) {
5374 if (null_timespec(write_time)) {
5375 ts[1] = changed_time;
5376 setting_write_time = false;
5377 } else {
5378 ts[1] = write_time;
5382 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5383 fname ? fname : fsp->fsp_name ));
5385 return smb_set_file_time(conn,
5386 fsp,
5387 fname,
5388 psbuf,
5390 setting_write_time);
5393 /****************************************************************************
5394 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5395 ****************************************************************************/
5397 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5398 struct smb_request *req,
5399 const char *pdata,
5400 int total_data,
5401 files_struct *fsp,
5402 const char *fname,
5403 SMB_STRUCT_STAT *psbuf)
5405 SMB_BIG_UINT allocation_size = 0;
5406 NTSTATUS status = NT_STATUS_OK;
5407 files_struct *new_fsp = NULL;
5409 if (!VALID_STAT(*psbuf)) {
5410 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5413 if (total_data < 8) {
5414 return NT_STATUS_INVALID_PARAMETER;
5417 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5418 #ifdef LARGE_SMB_OFF_T
5419 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5420 #else /* LARGE_SMB_OFF_T */
5421 if (IVAL(pdata,4) != 0) {
5422 /* more than 32 bits? */
5423 return NT_STATUS_INVALID_PARAMETER;
5425 #endif /* LARGE_SMB_OFF_T */
5427 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5428 fname, (double)allocation_size ));
5430 if (allocation_size) {
5431 allocation_size = smb_roundup(conn, allocation_size);
5434 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5435 fname, (double)allocation_size ));
5437 if (fsp && fsp->fh->fd != -1) {
5438 /* Open file handle. */
5439 /* Only change if needed. */
5440 if (allocation_size != get_file_size(*psbuf)) {
5441 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5442 return map_nt_error_from_unix(errno);
5445 /* But always update the time. */
5446 if (null_timespec(fsp->pending_modtime)) {
5448 * This is equivalent to a write. Ensure it's seen immediately
5449 * if there are no pending writes.
5451 set_filetime(fsp->conn, fsp->fsp_name,
5452 timespec_current());
5454 return NT_STATUS_OK;
5457 /* Pathname or stat or directory file. */
5459 status = open_file_ntcreate(conn, req, fname, psbuf,
5460 FILE_WRITE_DATA,
5461 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5462 FILE_OPEN,
5464 FILE_ATTRIBUTE_NORMAL,
5465 FORCE_OPLOCK_BREAK_TO_NONE,
5466 NULL, &new_fsp);
5468 if (!NT_STATUS_IS_OK(status)) {
5469 /* NB. We check for open_was_deferred in the caller. */
5470 return status;
5473 /* Only change if needed. */
5474 if (allocation_size != get_file_size(*psbuf)) {
5475 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5476 status = map_nt_error_from_unix(errno);
5477 close_file(new_fsp,NORMAL_CLOSE);
5478 return status;
5482 /* Changing the allocation size should set the last mod time. */
5483 /* Don't need to call set_filetime as this will be flushed on
5484 * close. */
5486 fsp_set_pending_modtime(new_fsp, timespec_current());
5488 close_file(new_fsp,NORMAL_CLOSE);
5489 return NT_STATUS_OK;
5492 /****************************************************************************
5493 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5494 ****************************************************************************/
5496 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5497 struct smb_request *req,
5498 const char *pdata,
5499 int total_data,
5500 files_struct *fsp,
5501 const char *fname,
5502 SMB_STRUCT_STAT *psbuf)
5504 SMB_OFF_T size;
5506 if (total_data < 8) {
5507 return NT_STATUS_INVALID_PARAMETER;
5510 size = IVAL(pdata,0);
5511 #ifdef LARGE_SMB_OFF_T
5512 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5513 #else /* LARGE_SMB_OFF_T */
5514 if (IVAL(pdata,4) != 0) {
5515 /* more than 32 bits? */
5516 return NT_STATUS_INVALID_PARAMETER;
5518 #endif /* LARGE_SMB_OFF_T */
5519 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5520 "file %s to %.0f\n", fname, (double)size ));
5522 return smb_set_file_size(conn, req,
5523 fsp,
5524 fname,
5525 psbuf,
5526 size);
5529 /****************************************************************************
5530 Allow a UNIX info mknod.
5531 ****************************************************************************/
5533 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5534 const char *pdata,
5535 int total_data,
5536 const char *fname,
5537 SMB_STRUCT_STAT *psbuf)
5539 uint32 file_type = IVAL(pdata,56);
5540 #if defined(HAVE_MAKEDEV)
5541 uint32 dev_major = IVAL(pdata,60);
5542 uint32 dev_minor = IVAL(pdata,68);
5543 #endif
5544 SMB_DEV_T dev = (SMB_DEV_T)0;
5545 uint32 raw_unixmode = IVAL(pdata,84);
5546 NTSTATUS status;
5547 mode_t unixmode;
5549 if (total_data < 100) {
5550 return NT_STATUS_INVALID_PARAMETER;
5553 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 return status;
5558 #if defined(HAVE_MAKEDEV)
5559 dev = makedev(dev_major, dev_minor);
5560 #endif
5562 switch (file_type) {
5563 #if defined(S_IFIFO)
5564 case UNIX_TYPE_FIFO:
5565 unixmode |= S_IFIFO;
5566 break;
5567 #endif
5568 #if defined(S_IFSOCK)
5569 case UNIX_TYPE_SOCKET:
5570 unixmode |= S_IFSOCK;
5571 break;
5572 #endif
5573 #if defined(S_IFCHR)
5574 case UNIX_TYPE_CHARDEV:
5575 unixmode |= S_IFCHR;
5576 break;
5577 #endif
5578 #if defined(S_IFBLK)
5579 case UNIX_TYPE_BLKDEV:
5580 unixmode |= S_IFBLK;
5581 break;
5582 #endif
5583 default:
5584 return NT_STATUS_INVALID_PARAMETER;
5587 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5588 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5590 /* Ok - do the mknod. */
5591 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5592 return map_nt_error_from_unix(errno);
5595 /* If any of the other "set" calls fail we
5596 * don't want to end up with a half-constructed mknod.
5599 if (lp_inherit_perms(SNUM(conn))) {
5600 inherit_access_acl(
5601 conn, parent_dirname(fname),
5602 fname, unixmode);
5605 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5606 status = map_nt_error_from_unix(errno);
5607 SMB_VFS_UNLINK(conn,fname);
5608 return status;
5610 return NT_STATUS_OK;
5613 /****************************************************************************
5614 Deal with SMB_SET_FILE_UNIX_BASIC.
5615 ****************************************************************************/
5617 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5618 struct smb_request *req,
5619 const char *pdata,
5620 int total_data,
5621 files_struct *fsp,
5622 const char *fname,
5623 SMB_STRUCT_STAT *psbuf)
5625 struct timespec ts[2];
5626 uint32 raw_unixmode;
5627 mode_t unixmode;
5628 SMB_OFF_T size = 0;
5629 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5630 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5631 NTSTATUS status = NT_STATUS_OK;
5632 bool delete_on_fail = False;
5633 enum perm_type ptype;
5635 if (total_data < 100) {
5636 return NT_STATUS_INVALID_PARAMETER;
5639 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5640 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5641 size=IVAL(pdata,0); /* first 8 Bytes are size */
5642 #ifdef LARGE_SMB_OFF_T
5643 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5644 #else /* LARGE_SMB_OFF_T */
5645 if (IVAL(pdata,4) != 0) {
5646 /* more than 32 bits? */
5647 return NT_STATUS_INVALID_PARAMETER;
5649 #endif /* LARGE_SMB_OFF_T */
5652 ts[0] = interpret_long_date(pdata+24); /* access_time */
5653 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5654 set_owner = (uid_t)IVAL(pdata,40);
5655 set_grp = (gid_t)IVAL(pdata,48);
5656 raw_unixmode = IVAL(pdata,84);
5658 if (VALID_STAT(*psbuf)) {
5659 if (S_ISDIR(psbuf->st_mode)) {
5660 ptype = PERM_EXISTING_DIR;
5661 } else {
5662 ptype = PERM_EXISTING_FILE;
5664 } else {
5665 ptype = PERM_NEW_FILE;
5668 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5669 if (!NT_STATUS_IS_OK(status)) {
5670 return status;
5673 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5674 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5675 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5677 if (!VALID_STAT(*psbuf)) {
5679 * The only valid use of this is to create character and block
5680 * devices, and named pipes. This is deprecated (IMHO) and
5681 * a new info level should be used for mknod. JRA.
5684 status = smb_unix_mknod(conn,
5685 pdata,
5686 total_data,
5687 fname,
5688 psbuf);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 return status;
5693 /* Ensure we don't try and change anything else. */
5694 raw_unixmode = SMB_MODE_NO_CHANGE;
5695 size = get_file_size(*psbuf);
5696 ts[0] = get_atimespec(psbuf);
5697 ts[1] = get_mtimespec(psbuf);
5699 * We continue here as we might want to change the
5700 * owner uid/gid.
5702 delete_on_fail = True;
5705 #if 1
5706 /* Horrible backwards compatibility hack as an old server bug
5707 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5708 * */
5710 if (!size) {
5711 size = get_file_size(*psbuf);
5713 #endif
5716 * Deal with the UNIX specific mode set.
5719 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5720 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5721 (unsigned int)unixmode, fname ));
5722 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5723 return map_nt_error_from_unix(errno);
5728 * Deal with the UNIX specific uid set.
5731 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5732 int ret;
5734 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5735 (unsigned int)set_owner, fname ));
5737 if (S_ISLNK(psbuf->st_mode)) {
5738 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5739 } else {
5740 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5743 if (ret != 0) {
5744 status = map_nt_error_from_unix(errno);
5745 if (delete_on_fail) {
5746 SMB_VFS_UNLINK(conn,fname);
5748 return status;
5753 * Deal with the UNIX specific gid set.
5756 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5757 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5758 (unsigned int)set_owner, fname ));
5759 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5760 status = map_nt_error_from_unix(errno);
5761 if (delete_on_fail) {
5762 SMB_VFS_UNLINK(conn,fname);
5764 return status;
5768 /* Deal with any size changes. */
5770 status = smb_set_file_size(conn, req,
5771 fsp,
5772 fname,
5773 psbuf,
5774 size);
5775 if (!NT_STATUS_IS_OK(status)) {
5776 return status;
5779 /* Deal with any time changes. */
5781 return smb_set_file_time(conn,
5782 fsp,
5783 fname,
5784 psbuf,
5786 true);
5789 /****************************************************************************
5790 Deal with SMB_SET_FILE_UNIX_INFO2.
5791 ****************************************************************************/
5793 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5794 struct smb_request *req,
5795 const char *pdata,
5796 int total_data,
5797 files_struct *fsp,
5798 const char *fname,
5799 SMB_STRUCT_STAT *psbuf)
5801 NTSTATUS status;
5802 uint32 smb_fflags;
5803 uint32 smb_fmask;
5805 if (total_data < 116) {
5806 return NT_STATUS_INVALID_PARAMETER;
5809 /* Start by setting all the fields that are common between UNIX_BASIC
5810 * and UNIX_INFO2.
5812 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5813 fsp, fname, psbuf);
5814 if (!NT_STATUS_IS_OK(status)) {
5815 return status;
5818 smb_fflags = IVAL(pdata, 108);
5819 smb_fmask = IVAL(pdata, 112);
5821 /* NB: We should only attempt to alter the file flags if the client
5822 * sends a non-zero mask.
5824 if (smb_fmask != 0) {
5825 int stat_fflags = 0;
5827 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5828 &stat_fflags)) {
5829 /* Client asked to alter a flag we don't understand. */
5830 return NT_STATUS_INVALID_PARAMETER;
5833 if (fsp && fsp->fh->fd != -1) {
5834 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5835 return NT_STATUS_NOT_SUPPORTED;
5836 } else {
5837 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5838 return map_nt_error_from_unix(errno);
5843 /* XXX: need to add support for changing the create_time here. You
5844 * can do this for paths on Darwin with setattrlist(2). The right way
5845 * to hook this up is probably by extending the VFS utimes interface.
5848 return NT_STATUS_OK;
5851 /****************************************************************************
5852 Create a directory with POSIX semantics.
5853 ****************************************************************************/
5855 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5856 struct smb_request *req,
5857 char **ppdata,
5858 int total_data,
5859 const char *fname,
5860 SMB_STRUCT_STAT *psbuf,
5861 int *pdata_return_size)
5863 NTSTATUS status = NT_STATUS_OK;
5864 uint32 raw_unixmode = 0;
5865 uint32 mod_unixmode = 0;
5866 mode_t unixmode = (mode_t)0;
5867 files_struct *fsp = NULL;
5868 uint16 info_level_return = 0;
5869 int info;
5870 char *pdata = *ppdata;
5872 if (total_data < 18) {
5873 return NT_STATUS_INVALID_PARAMETER;
5876 raw_unixmode = IVAL(pdata,8);
5877 /* Next 4 bytes are not yet defined. */
5879 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 return status;
5884 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5886 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5887 fname, (unsigned int)unixmode ));
5889 status = open_directory(conn, req,
5890 fname,
5891 psbuf,
5892 FILE_READ_ATTRIBUTES, /* Just a stat open */
5893 FILE_SHARE_NONE, /* Ignored for stat opens */
5894 FILE_CREATE,
5896 mod_unixmode,
5897 &info,
5898 &fsp);
5900 if (NT_STATUS_IS_OK(status)) {
5901 close_file(fsp, NORMAL_CLOSE);
5904 info_level_return = SVAL(pdata,16);
5906 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5907 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5908 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5909 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5910 } else {
5911 *pdata_return_size = 12;
5914 /* Realloc the data size */
5915 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5916 if (*ppdata == NULL) {
5917 *pdata_return_size = 0;
5918 return NT_STATUS_NO_MEMORY;
5920 pdata = *ppdata;
5922 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5923 SSVAL(pdata,2,0); /* No fnum. */
5924 SIVAL(pdata,4,info); /* Was directory created. */
5926 switch (info_level_return) {
5927 case SMB_QUERY_FILE_UNIX_BASIC:
5928 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5929 SSVAL(pdata,10,0); /* Padding. */
5930 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5931 break;
5932 case SMB_QUERY_FILE_UNIX_INFO2:
5933 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5934 SSVAL(pdata,10,0); /* Padding. */
5935 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5936 break;
5937 default:
5938 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5939 SSVAL(pdata,10,0); /* Padding. */
5940 break;
5943 return status;
5946 /****************************************************************************
5947 Open/Create a file with POSIX semantics.
5948 ****************************************************************************/
5950 static NTSTATUS smb_posix_open(connection_struct *conn,
5951 struct smb_request *req,
5952 char **ppdata,
5953 int total_data,
5954 const char *fname,
5955 SMB_STRUCT_STAT *psbuf,
5956 int *pdata_return_size)
5958 bool extended_oplock_granted = False;
5959 char *pdata = *ppdata;
5960 uint32 flags = 0;
5961 uint32 wire_open_mode = 0;
5962 uint32 raw_unixmode = 0;
5963 uint32 mod_unixmode = 0;
5964 uint32 create_disp = 0;
5965 uint32 access_mask = 0;
5966 uint32 create_options = 0;
5967 NTSTATUS status = NT_STATUS_OK;
5968 mode_t unixmode = (mode_t)0;
5969 files_struct *fsp = NULL;
5970 int oplock_request = 0;
5971 int info = 0;
5972 uint16 info_level_return = 0;
5974 if (total_data < 18) {
5975 return NT_STATUS_INVALID_PARAMETER;
5978 flags = IVAL(pdata,0);
5979 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5980 if (oplock_request) {
5981 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5984 wire_open_mode = IVAL(pdata,4);
5986 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5987 return smb_posix_mkdir(conn, req,
5988 ppdata,
5989 total_data,
5990 fname,
5991 psbuf,
5992 pdata_return_size);
5995 switch (wire_open_mode & SMB_ACCMODE) {
5996 case SMB_O_RDONLY:
5997 access_mask = FILE_READ_DATA;
5998 break;
5999 case SMB_O_WRONLY:
6000 access_mask = FILE_WRITE_DATA;
6001 break;
6002 case SMB_O_RDWR:
6003 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6004 break;
6005 default:
6006 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6007 (unsigned int)wire_open_mode ));
6008 return NT_STATUS_INVALID_PARAMETER;
6011 wire_open_mode &= ~SMB_ACCMODE;
6013 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6014 create_disp = FILE_CREATE;
6015 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6016 create_disp = FILE_OVERWRITE_IF;
6017 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6018 create_disp = FILE_OPEN_IF;
6019 } else {
6020 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6021 (unsigned int)wire_open_mode ));
6022 return NT_STATUS_INVALID_PARAMETER;
6025 raw_unixmode = IVAL(pdata,8);
6026 /* Next 4 bytes are not yet defined. */
6028 status = unix_perms_from_wire(conn,
6029 psbuf,
6030 raw_unixmode,
6031 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6032 &unixmode);
6034 if (!NT_STATUS_IS_OK(status)) {
6035 return status;
6038 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6040 if (wire_open_mode & SMB_O_SYNC) {
6041 create_options |= FILE_WRITE_THROUGH;
6043 if (wire_open_mode & SMB_O_APPEND) {
6044 access_mask |= FILE_APPEND_DATA;
6046 if (wire_open_mode & SMB_O_DIRECT) {
6047 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6050 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6051 fname,
6052 (unsigned int)wire_open_mode,
6053 (unsigned int)unixmode ));
6055 status = open_file_ntcreate(conn, req,
6056 fname,
6057 psbuf,
6058 access_mask,
6059 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6060 create_disp,
6061 0, /* no create options yet. */
6062 mod_unixmode,
6063 oplock_request,
6064 &info,
6065 &fsp);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 return status;
6071 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6072 extended_oplock_granted = True;
6075 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6076 extended_oplock_granted = True;
6079 info_level_return = SVAL(pdata,16);
6081 /* Allocate the correct return size. */
6083 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6084 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6085 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6086 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6087 } else {
6088 *pdata_return_size = 12;
6091 /* Realloc the data size */
6092 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6093 if (*ppdata == NULL) {
6094 close_file(fsp,ERROR_CLOSE);
6095 *pdata_return_size = 0;
6096 return NT_STATUS_NO_MEMORY;
6098 pdata = *ppdata;
6100 if (extended_oplock_granted) {
6101 if (flags & REQUEST_BATCH_OPLOCK) {
6102 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6103 } else {
6104 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6106 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6107 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6108 } else {
6109 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6112 SSVAL(pdata,2,fsp->fnum);
6113 SIVAL(pdata,4,info); /* Was file created etc. */
6115 switch (info_level_return) {
6116 case SMB_QUERY_FILE_UNIX_BASIC:
6117 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6118 SSVAL(pdata,10,0); /* padding. */
6119 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6120 break;
6121 case SMB_QUERY_FILE_UNIX_INFO2:
6122 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6123 SSVAL(pdata,10,0); /* padding. */
6124 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6125 break;
6126 default:
6127 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6128 SSVAL(pdata,10,0); /* padding. */
6129 break;
6131 return NT_STATUS_OK;
6134 /****************************************************************************
6135 Delete a file with POSIX semantics.
6136 ****************************************************************************/
6138 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6139 struct smb_request *req,
6140 const char *pdata,
6141 int total_data,
6142 const char *fname,
6143 SMB_STRUCT_STAT *psbuf)
6145 NTSTATUS status = NT_STATUS_OK;
6146 files_struct *fsp = NULL;
6147 uint16 flags = 0;
6148 char del = 1;
6149 int info = 0;
6150 int i;
6151 struct share_mode_lock *lck = NULL;
6153 if (total_data < 2) {
6154 return NT_STATUS_INVALID_PARAMETER;
6157 flags = SVAL(pdata,0);
6159 if (!VALID_STAT(*psbuf)) {
6160 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6163 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6164 !VALID_STAT_OF_DIR(*psbuf)) {
6165 return NT_STATUS_NOT_A_DIRECTORY;
6168 DEBUG(10,("smb_posix_unlink: %s %s\n",
6169 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6170 fname));
6172 if (VALID_STAT_OF_DIR(*psbuf)) {
6173 status = open_directory(conn, req,
6174 fname,
6175 psbuf,
6176 DELETE_ACCESS,
6177 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6178 FILE_OPEN,
6180 FILE_FLAG_POSIX_SEMANTICS|0777,
6181 &info,
6182 &fsp);
6183 } else {
6185 status = open_file_ntcreate(conn, req,
6186 fname,
6187 psbuf,
6188 DELETE_ACCESS,
6189 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6190 FILE_OPEN,
6192 FILE_FLAG_POSIX_SEMANTICS|0777,
6193 0, /* No oplock, but break existing ones. */
6194 &info,
6195 &fsp);
6198 if (!NT_STATUS_IS_OK(status)) {
6199 return status;
6203 * Don't lie to client. If we can't really delete due to
6204 * non-POSIX opens return SHARING_VIOLATION.
6207 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
6208 if (lck == NULL) {
6209 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6210 "lock for file %s\n", fsp->fsp_name));
6211 close_file(fsp, NORMAL_CLOSE);
6212 return NT_STATUS_INVALID_PARAMETER;
6216 * See if others still have the file open. If this is the case, then
6217 * don't delete. If all opens are POSIX delete we can set the delete
6218 * on close disposition.
6220 for (i=0; i<lck->num_share_modes; i++) {
6221 struct share_mode_entry *e = &lck->share_modes[i];
6222 if (is_valid_share_mode_entry(e)) {
6223 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6224 continue;
6226 /* Fail with sharing violation. */
6227 close_file(fsp, NORMAL_CLOSE);
6228 TALLOC_FREE(lck);
6229 return NT_STATUS_SHARING_VIOLATION;
6234 * Set the delete on close.
6236 status = smb_set_file_disposition_info(conn,
6237 &del,
6239 fsp,
6240 fname,
6241 psbuf);
6243 if (!NT_STATUS_IS_OK(status)) {
6244 close_file(fsp, NORMAL_CLOSE);
6245 TALLOC_FREE(lck);
6246 return status;
6248 TALLOC_FREE(lck);
6249 return close_file(fsp, NORMAL_CLOSE);
6252 /****************************************************************************
6253 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6254 ****************************************************************************/
6256 static void call_trans2setfilepathinfo(connection_struct *conn,
6257 struct smb_request *req,
6258 unsigned int tran_call,
6259 char **pparams, int total_params,
6260 char **ppdata, int total_data,
6261 unsigned int max_data_bytes)
6263 char *params = *pparams;
6264 char *pdata = *ppdata;
6265 uint16 info_level;
6266 SMB_STRUCT_STAT sbuf;
6267 char *fname = NULL;
6268 files_struct *fsp = NULL;
6269 NTSTATUS status = NT_STATUS_OK;
6270 int data_return_size = 0;
6271 TALLOC_CTX *ctx = talloc_tos();
6273 if (!params) {
6274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6275 return;
6278 ZERO_STRUCT(sbuf);
6280 if (tran_call == TRANSACT2_SETFILEINFO) {
6281 if (total_params < 4) {
6282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6283 return;
6286 fsp = file_fsp(SVAL(params,0));
6287 /* Basic check for non-null fsp. */
6288 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6289 return;
6291 info_level = SVAL(params,2);
6293 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6294 if (!fname) {
6295 reply_nterror(req, NT_STATUS_NO_MEMORY);
6296 return;
6299 if(fsp->is_directory || fsp->fh->fd == -1) {
6301 * This is actually a SETFILEINFO on a directory
6302 * handle (returned from an NT SMB). NT5.0 seems
6303 * to do this call. JRA.
6305 if (INFO_LEVEL_IS_UNIX(info_level)) {
6306 /* Always do lstat for UNIX calls. */
6307 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6308 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6309 reply_unixerror(req,ERRDOS,ERRbadpath);
6310 return;
6312 } else {
6313 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6314 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6315 reply_unixerror(req,ERRDOS,ERRbadpath);
6316 return;
6319 } else if (fsp->print_file) {
6321 * Doing a DELETE_ON_CLOSE should cancel a print job.
6323 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6324 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6326 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6328 SSVAL(params,0,0);
6329 send_trans2_replies(conn, req, params, 2,
6330 *ppdata, 0,
6331 max_data_bytes);
6332 return;
6333 } else {
6334 reply_unixerror(req, ERRDOS, ERRbadpath);
6335 return;
6337 } else {
6339 * Original code - this is an open file.
6341 if (!check_fsp(conn, req, fsp, &current_user)) {
6342 return;
6345 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6346 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6347 reply_unixerror(req, ERRDOS, ERRbadfid);
6348 return;
6351 } else {
6352 /* set path info */
6353 if (total_params < 7) {
6354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6355 return;
6358 info_level = SVAL(params,0);
6359 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6360 total_params - 6, STR_TERMINATE,
6361 &status);
6362 if (!NT_STATUS_IS_OK(status)) {
6363 reply_nterror(req, status);
6364 return;
6367 status = resolve_dfspath(ctx, conn,
6368 req->flags2 & FLAGS2_DFS_PATHNAMES,
6369 fname,
6370 &fname);
6371 if (!NT_STATUS_IS_OK(status)) {
6372 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6373 reply_botherror(req,
6374 NT_STATUS_PATH_NOT_COVERED,
6375 ERRSRV, ERRbadpath);
6376 return;
6378 reply_nterror(req, status);
6379 return;
6382 status = unix_convert(ctx, conn, fname, False,
6383 &fname, NULL, &sbuf);
6384 if (!NT_STATUS_IS_OK(status)) {
6385 reply_nterror(req, status);
6386 return;
6389 status = check_name(conn, fname);
6390 if (!NT_STATUS_IS_OK(status)) {
6391 reply_nterror(req, status);
6392 return;
6395 if (INFO_LEVEL_IS_UNIX(info_level)) {
6397 * For CIFS UNIX extensions the target name may not exist.
6400 /* Always do lstat for UNIX calls. */
6401 SMB_VFS_LSTAT(conn,fname,&sbuf);
6403 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6404 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6405 reply_unixerror(req, ERRDOS, ERRbadpath);
6406 return;
6410 if (!CAN_WRITE(conn)) {
6411 reply_doserror(req, ERRSRV, ERRaccess);
6412 return;
6415 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6416 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6417 return;
6420 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6421 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6423 /* Realloc the parameter size */
6424 *pparams = (char *)SMB_REALLOC(*pparams,2);
6425 if (*pparams == NULL) {
6426 reply_nterror(req, NT_STATUS_NO_MEMORY);
6427 return;
6429 params = *pparams;
6431 SSVAL(params,0,0);
6433 if (fsp && !null_timespec(fsp->pending_modtime)) {
6434 /* the pending modtime overrides the current modtime */
6435 set_mtimespec(&sbuf, fsp->pending_modtime);
6438 switch (info_level) {
6440 case SMB_INFO_STANDARD:
6442 status = smb_set_info_standard(conn,
6443 pdata,
6444 total_data,
6445 fsp,
6446 fname,
6447 &sbuf);
6448 break;
6451 case SMB_INFO_SET_EA:
6453 status = smb_info_set_ea(conn,
6454 pdata,
6455 total_data,
6456 fsp,
6457 fname);
6458 break;
6461 case SMB_SET_FILE_BASIC_INFO:
6462 case SMB_FILE_BASIC_INFORMATION:
6464 status = smb_set_file_basic_info(conn,
6465 pdata,
6466 total_data,
6467 fsp,
6468 fname,
6469 &sbuf);
6470 break;
6473 case SMB_FILE_ALLOCATION_INFORMATION:
6474 case SMB_SET_FILE_ALLOCATION_INFO:
6476 status = smb_set_file_allocation_info(conn, req,
6477 pdata,
6478 total_data,
6479 fsp,
6480 fname,
6481 &sbuf);
6482 break;
6485 case SMB_FILE_END_OF_FILE_INFORMATION:
6486 case SMB_SET_FILE_END_OF_FILE_INFO:
6488 status = smb_set_file_end_of_file_info(conn, req,
6489 pdata,
6490 total_data,
6491 fsp,
6492 fname,
6493 &sbuf);
6494 break;
6497 case SMB_FILE_DISPOSITION_INFORMATION:
6498 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6500 #if 0
6501 /* JRA - We used to just ignore this on a path ?
6502 * Shouldn't this be invalid level on a pathname
6503 * based call ?
6505 if (tran_call != TRANSACT2_SETFILEINFO) {
6506 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6508 #endif
6509 status = smb_set_file_disposition_info(conn,
6510 pdata,
6511 total_data,
6512 fsp,
6513 fname,
6514 &sbuf);
6515 break;
6518 case SMB_FILE_POSITION_INFORMATION:
6520 status = smb_file_position_information(conn,
6521 pdata,
6522 total_data,
6523 fsp);
6524 break;
6527 /* From tridge Samba4 :
6528 * MODE_INFORMATION in setfileinfo (I have no
6529 * idea what "mode information" on a file is - it takes a value of 0,
6530 * 2, 4 or 6. What could it be?).
6533 case SMB_FILE_MODE_INFORMATION:
6535 status = smb_file_mode_information(conn,
6536 pdata,
6537 total_data);
6538 break;
6542 * CIFS UNIX extensions.
6545 case SMB_SET_FILE_UNIX_BASIC:
6547 status = smb_set_file_unix_basic(conn, req,
6548 pdata,
6549 total_data,
6550 fsp,
6551 fname,
6552 &sbuf);
6553 break;
6556 case SMB_SET_FILE_UNIX_INFO2:
6558 status = smb_set_file_unix_info2(conn, req,
6559 pdata,
6560 total_data,
6561 fsp,
6562 fname,
6563 &sbuf);
6564 break;
6567 case SMB_SET_FILE_UNIX_LINK:
6569 if (tran_call != TRANSACT2_SETPATHINFO) {
6570 /* We must have a pathname for this. */
6571 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6572 return;
6574 status = smb_set_file_unix_link(conn, req, pdata,
6575 total_data, fname);
6576 break;
6579 case SMB_SET_FILE_UNIX_HLINK:
6581 if (tran_call != TRANSACT2_SETPATHINFO) {
6582 /* We must have a pathname for this. */
6583 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6584 return;
6586 status = smb_set_file_unix_hlink(conn, req,
6587 pdata, total_data,
6588 fname);
6589 break;
6592 case SMB_FILE_RENAME_INFORMATION:
6594 status = smb_file_rename_information(conn, req,
6595 pdata, total_data,
6596 fsp, fname);
6597 break;
6600 #if defined(HAVE_POSIX_ACLS)
6601 case SMB_SET_POSIX_ACL:
6603 status = smb_set_posix_acl(conn,
6604 pdata,
6605 total_data,
6606 fsp,
6607 fname,
6608 &sbuf);
6609 break;
6611 #endif
6613 case SMB_SET_POSIX_LOCK:
6615 if (tran_call != TRANSACT2_SETFILEINFO) {
6616 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6617 return;
6619 status = smb_set_posix_lock(conn, req,
6620 pdata, total_data, fsp);
6621 break;
6624 case SMB_POSIX_PATH_OPEN:
6626 if (tran_call != TRANSACT2_SETPATHINFO) {
6627 /* We must have a pathname for this. */
6628 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6629 return;
6632 status = smb_posix_open(conn, req,
6633 ppdata,
6634 total_data,
6635 fname,
6636 &sbuf,
6637 &data_return_size);
6638 break;
6641 case SMB_POSIX_PATH_UNLINK:
6643 if (tran_call != TRANSACT2_SETPATHINFO) {
6644 /* We must have a pathname for this. */
6645 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6646 return;
6649 status = smb_posix_unlink(conn, req,
6650 pdata,
6651 total_data,
6652 fname,
6653 &sbuf);
6654 break;
6657 default:
6658 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6659 return;
6663 if (!NT_STATUS_IS_OK(status)) {
6664 if (open_was_deferred(req->mid)) {
6665 /* We have re-scheduled this call. */
6666 return;
6668 if (blocking_lock_was_deferred(req->mid)) {
6669 /* We have re-scheduled this call. */
6670 return;
6672 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6673 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6674 ERRSRV, ERRbadpath);
6675 return;
6677 if (info_level == SMB_POSIX_PATH_OPEN) {
6678 reply_openerror(req, status);
6679 return;
6682 reply_nterror(req, status);
6683 return;
6686 SSVAL(params,0,0);
6687 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6688 max_data_bytes);
6690 return;
6693 /****************************************************************************
6694 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6695 ****************************************************************************/
6697 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6698 char **pparams, int total_params,
6699 char **ppdata, int total_data,
6700 unsigned int max_data_bytes)
6702 char *params = *pparams;
6703 char *pdata = *ppdata;
6704 char *directory = NULL;
6705 SMB_STRUCT_STAT sbuf;
6706 NTSTATUS status = NT_STATUS_OK;
6707 struct ea_list *ea_list = NULL;
6708 TALLOC_CTX *ctx = talloc_tos();
6710 if (!CAN_WRITE(conn)) {
6711 reply_doserror(req, ERRSRV, ERRaccess);
6712 return;
6715 if (total_params < 5) {
6716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6717 return;
6720 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
6721 total_params - 4, STR_TERMINATE,
6722 &status);
6723 if (!NT_STATUS_IS_OK(status)) {
6724 reply_nterror(req, status);
6725 return;
6728 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6730 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 reply_nterror(req, status);
6733 return;
6736 status = check_name(conn, directory);
6737 if (!NT_STATUS_IS_OK(status)) {
6738 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6739 reply_nterror(req, status);
6740 return;
6743 /* Any data in this call is an EA list. */
6744 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6745 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6746 return;
6750 * OS/2 workplace shell seems to send SET_EA requests of "null"
6751 * length (4 bytes containing IVAL 4).
6752 * They seem to have no effect. Bug #3212. JRA.
6755 if (total_data != 4) {
6756 if (total_data < 10) {
6757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6758 return;
6761 if (IVAL(pdata,0) > total_data) {
6762 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6763 IVAL(pdata,0), (unsigned int)total_data));
6764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6765 return;
6768 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6769 total_data - 4);
6770 if (!ea_list) {
6771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6772 return;
6774 } else if (IVAL(pdata,0) != 4) {
6775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6776 return;
6779 status = create_directory(conn, req, directory);
6781 if (!NT_STATUS_IS_OK(status)) {
6782 reply_nterror(req, status);
6783 return;
6786 /* Try and set any given EA. */
6787 if (ea_list) {
6788 status = set_ea(conn, NULL, directory, ea_list);
6789 if (!NT_STATUS_IS_OK(status)) {
6790 reply_nterror(req, status);
6791 return;
6795 /* Realloc the parameter and data sizes */
6796 *pparams = (char *)SMB_REALLOC(*pparams,2);
6797 if(*pparams == NULL) {
6798 reply_nterror(req, NT_STATUS_NO_MEMORY);
6799 return;
6801 params = *pparams;
6803 SSVAL(params,0,0);
6805 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
6807 return;
6810 /****************************************************************************
6811 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6812 We don't actually do this - we just send a null response.
6813 ****************************************************************************/
6815 static void call_trans2findnotifyfirst(connection_struct *conn,
6816 struct smb_request *req,
6817 char **pparams, int total_params,
6818 char **ppdata, int total_data,
6819 unsigned int max_data_bytes)
6821 static uint16 fnf_handle = 257;
6822 char *params = *pparams;
6823 uint16 info_level;
6825 if (total_params < 6) {
6826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6827 return;
6830 info_level = SVAL(params,4);
6831 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6833 switch (info_level) {
6834 case 1:
6835 case 2:
6836 break;
6837 default:
6838 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6839 return;
6842 /* Realloc the parameter and data sizes */
6843 *pparams = (char *)SMB_REALLOC(*pparams,6);
6844 if (*pparams == NULL) {
6845 reply_nterror(req, NT_STATUS_NO_MEMORY);
6846 return;
6848 params = *pparams;
6850 SSVAL(params,0,fnf_handle);
6851 SSVAL(params,2,0); /* No changes */
6852 SSVAL(params,4,0); /* No EA errors */
6854 fnf_handle++;
6856 if(fnf_handle == 0)
6857 fnf_handle = 257;
6859 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
6861 return;
6864 /****************************************************************************
6865 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6866 changes). Currently this does nothing.
6867 ****************************************************************************/
6869 static void call_trans2findnotifynext(connection_struct *conn,
6870 struct smb_request *req,
6871 char **pparams, int total_params,
6872 char **ppdata, int total_data,
6873 unsigned int max_data_bytes)
6875 char *params = *pparams;
6877 DEBUG(3,("call_trans2findnotifynext\n"));
6879 /* Realloc the parameter and data sizes */
6880 *pparams = (char *)SMB_REALLOC(*pparams,4);
6881 if (*pparams == NULL) {
6882 reply_nterror(req, NT_STATUS_NO_MEMORY);
6883 return;
6885 params = *pparams;
6887 SSVAL(params,0,0); /* No changes */
6888 SSVAL(params,2,0); /* No EA errors */
6890 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
6892 return;
6895 /****************************************************************************
6896 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6897 ****************************************************************************/
6899 static void call_trans2getdfsreferral(connection_struct *conn,
6900 struct smb_request *req,
6901 char **pparams, int total_params,
6902 char **ppdata, int total_data,
6903 unsigned int max_data_bytes)
6905 char *params = *pparams;
6906 char *pathname = NULL;
6907 int reply_size = 0;
6908 int max_referral_level;
6909 NTSTATUS status = NT_STATUS_OK;
6910 TALLOC_CTX *ctx = talloc_tos();
6912 DEBUG(10,("call_trans2getdfsreferral\n"));
6914 if (total_params < 3) {
6915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6916 return;
6919 max_referral_level = SVAL(params,0);
6921 if(!lp_host_msdfs()) {
6922 reply_doserror(req, ERRDOS, ERRbadfunc);
6923 return;
6926 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
6927 total_params - 2, STR_TERMINATE);
6928 if (!pathname) {
6929 reply_nterror(req, NT_STATUS_NOT_FOUND);
6930 return;
6932 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6933 ppdata,&status)) < 0) {
6934 reply_nterror(req, status);
6935 return;
6938 SSVAL(req->inbuf, smb_flg2,
6939 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6940 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
6942 return;
6945 #define LMCAT_SPL 0x53
6946 #define LMFUNC_GETJOBID 0x60
6948 /****************************************************************************
6949 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6950 ****************************************************************************/
6952 static void call_trans2ioctl(connection_struct *conn,
6953 struct smb_request *req,
6954 char **pparams, int total_params,
6955 char **ppdata, int total_data,
6956 unsigned int max_data_bytes)
6958 char *pdata = *ppdata;
6959 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6961 /* check for an invalid fid before proceeding */
6963 if (!fsp) {
6964 reply_doserror(req, ERRDOS, ERRbadfid);
6965 return;
6968 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6969 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6970 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6971 if (*ppdata == NULL) {
6972 reply_nterror(req, NT_STATUS_NO_MEMORY);
6973 return;
6975 pdata = *ppdata;
6977 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6978 CAN ACCEPT THIS IN UNICODE. JRA. */
6980 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6981 srvstr_push(pdata, req->flags2, pdata + 2,
6982 global_myname(), 15,
6983 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6984 srvstr_push(pdata, req->flags2, pdata+18,
6985 lp_servicename(SNUM(conn)), 13,
6986 STR_ASCII|STR_TERMINATE); /* Service name */
6987 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
6988 max_data_bytes);
6989 return;
6992 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6993 reply_doserror(req, ERRSRV, ERRerror);
6996 /****************************************************************************
6997 Reply to a SMBfindclose (stop trans2 directory search).
6998 ****************************************************************************/
7000 void reply_findclose(struct smb_request *req)
7002 int dptr_num;
7004 START_PROFILE(SMBfindclose);
7006 if (req->wct < 1) {
7007 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7008 END_PROFILE(SMBfindclose);
7009 return;
7012 dptr_num = SVALS(req->inbuf,smb_vwv0);
7014 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7016 dptr_close(&dptr_num);
7018 reply_outbuf(req, 0, 0);
7020 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7022 END_PROFILE(SMBfindclose);
7023 return;
7026 /****************************************************************************
7027 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7028 ****************************************************************************/
7030 void reply_findnclose(struct smb_request *req)
7032 int dptr_num;
7034 START_PROFILE(SMBfindnclose);
7036 if (req->wct < 1) {
7037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7038 END_PROFILE(SMBfindnclose);
7039 return;
7042 dptr_num = SVAL(req->inbuf,smb_vwv0);
7044 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7046 /* We never give out valid handles for a
7047 findnotifyfirst - so any dptr_num is ok here.
7048 Just ignore it. */
7050 reply_outbuf(req, 0, 0);
7052 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7054 END_PROFILE(SMBfindnclose);
7055 return;
7058 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7059 struct trans_state *state)
7061 if (Protocol >= PROTOCOL_NT1) {
7062 req->flags2 |= 0x40; /* IS_LONG_NAME */
7063 SSVAL(req->inbuf,smb_flg2,req->flags2);
7066 if (conn->encrypt_level == Required && !req->encrypted) {
7067 if (state->call != TRANSACT2_QFSINFO &&
7068 state->call != TRANSACT2_SETFSINFO) {
7069 DEBUG(0,("handle_trans2: encryption required "
7070 "with call 0x%x\n",
7071 (unsigned int)state->call));
7072 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7073 return;
7077 /* Now we must call the relevant TRANS2 function */
7078 switch(state->call) {
7079 case TRANSACT2_OPEN:
7081 START_PROFILE(Trans2_open);
7082 call_trans2open(conn, req,
7083 &state->param, state->total_param,
7084 &state->data, state->total_data,
7085 state->max_data_return);
7086 END_PROFILE(Trans2_open);
7087 break;
7090 case TRANSACT2_FINDFIRST:
7092 START_PROFILE(Trans2_findfirst);
7093 call_trans2findfirst(conn, req,
7094 &state->param, state->total_param,
7095 &state->data, state->total_data,
7096 state->max_data_return);
7097 END_PROFILE(Trans2_findfirst);
7098 break;
7101 case TRANSACT2_FINDNEXT:
7103 START_PROFILE(Trans2_findnext);
7104 call_trans2findnext(conn, req,
7105 &state->param, state->total_param,
7106 &state->data, state->total_data,
7107 state->max_data_return);
7108 END_PROFILE(Trans2_findnext);
7109 break;
7112 case TRANSACT2_QFSINFO:
7114 START_PROFILE(Trans2_qfsinfo);
7115 call_trans2qfsinfo(conn, req,
7116 &state->param, state->total_param,
7117 &state->data, state->total_data,
7118 state->max_data_return);
7119 END_PROFILE(Trans2_qfsinfo);
7120 break;
7123 case TRANSACT2_SETFSINFO:
7125 START_PROFILE(Trans2_setfsinfo);
7126 call_trans2setfsinfo(conn, req,
7127 &state->param, state->total_param,
7128 &state->data, state->total_data,
7129 state->max_data_return);
7130 END_PROFILE(Trans2_setfsinfo);
7131 break;
7134 case TRANSACT2_QPATHINFO:
7135 case TRANSACT2_QFILEINFO:
7137 START_PROFILE(Trans2_qpathinfo);
7138 call_trans2qfilepathinfo(conn, req, state->call,
7139 &state->param, state->total_param,
7140 &state->data, state->total_data,
7141 state->max_data_return);
7142 END_PROFILE(Trans2_qpathinfo);
7143 break;
7146 case TRANSACT2_SETPATHINFO:
7147 case TRANSACT2_SETFILEINFO:
7149 START_PROFILE(Trans2_setpathinfo);
7150 call_trans2setfilepathinfo(conn, req, state->call,
7151 &state->param, state->total_param,
7152 &state->data, state->total_data,
7153 state->max_data_return);
7154 END_PROFILE(Trans2_setpathinfo);
7155 break;
7158 case TRANSACT2_FINDNOTIFYFIRST:
7160 START_PROFILE(Trans2_findnotifyfirst);
7161 call_trans2findnotifyfirst(conn, req,
7162 &state->param, state->total_param,
7163 &state->data, state->total_data,
7164 state->max_data_return);
7165 END_PROFILE(Trans2_findnotifyfirst);
7166 break;
7169 case TRANSACT2_FINDNOTIFYNEXT:
7171 START_PROFILE(Trans2_findnotifynext);
7172 call_trans2findnotifynext(conn, req,
7173 &state->param, state->total_param,
7174 &state->data, state->total_data,
7175 state->max_data_return);
7176 END_PROFILE(Trans2_findnotifynext);
7177 break;
7180 case TRANSACT2_MKDIR:
7182 START_PROFILE(Trans2_mkdir);
7183 call_trans2mkdir(conn, req,
7184 &state->param, state->total_param,
7185 &state->data, state->total_data,
7186 state->max_data_return);
7187 END_PROFILE(Trans2_mkdir);
7188 break;
7191 case TRANSACT2_GET_DFS_REFERRAL:
7193 START_PROFILE(Trans2_get_dfs_referral);
7194 call_trans2getdfsreferral(conn, req,
7195 &state->param, state->total_param,
7196 &state->data, state->total_data,
7197 state->max_data_return);
7198 END_PROFILE(Trans2_get_dfs_referral);
7199 break;
7202 case TRANSACT2_IOCTL:
7204 START_PROFILE(Trans2_ioctl);
7205 call_trans2ioctl(conn, req,
7206 &state->param, state->total_param,
7207 &state->data, state->total_data,
7208 state->max_data_return);
7209 END_PROFILE(Trans2_ioctl);
7210 break;
7213 default:
7214 /* Error in request */
7215 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7216 reply_doserror(req, ERRSRV,ERRerror);
7220 /****************************************************************************
7221 Reply to a SMBtrans2.
7222 ****************************************************************************/
7224 void reply_trans2(struct smb_request *req)
7226 connection_struct *conn = req->conn;
7227 unsigned int dsoff;
7228 unsigned int dscnt;
7229 unsigned int psoff;
7230 unsigned int pscnt;
7231 unsigned int tran_call;
7232 int size;
7233 struct trans_state *state;
7234 NTSTATUS result;
7236 START_PROFILE(SMBtrans2);
7238 if (req->wct < 14) {
7239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7240 END_PROFILE(SMBtrans2);
7241 return;
7244 dsoff = SVAL(req->inbuf, smb_dsoff);
7245 dscnt = SVAL(req->inbuf, smb_dscnt);
7246 psoff = SVAL(req->inbuf, smb_psoff);
7247 pscnt = SVAL(req->inbuf, smb_pscnt);
7248 tran_call = SVAL(req->inbuf, smb_setup0);
7249 size = smb_len(req->inbuf) + 4;
7251 result = allow_new_trans(conn->pending_trans, req->mid);
7252 if (!NT_STATUS_IS_OK(result)) {
7253 DEBUG(2, ("Got invalid trans2 request: %s\n",
7254 nt_errstr(result)));
7255 reply_nterror(req, result);
7256 END_PROFILE(SMBtrans2);
7257 return;
7260 if (IS_IPC(conn)) {
7261 switch (tran_call) {
7262 /* List the allowed trans2 calls on IPC$ */
7263 case TRANSACT2_OPEN:
7264 case TRANSACT2_GET_DFS_REFERRAL:
7265 case TRANSACT2_QFILEINFO:
7266 case TRANSACT2_QFSINFO:
7267 case TRANSACT2_SETFSINFO:
7268 break;
7269 default:
7270 reply_doserror(req, ERRSRV, ERRaccess);
7271 END_PROFILE(SMBtrans2);
7272 return;
7276 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7277 DEBUG(0, ("talloc failed\n"));
7278 reply_nterror(req, NT_STATUS_NO_MEMORY);
7279 END_PROFILE(SMBtrans2);
7280 return;
7283 state->cmd = SMBtrans2;
7285 state->mid = req->mid;
7286 state->vuid = req->vuid;
7287 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7288 state->setup = NULL;
7289 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7290 state->param = NULL;
7291 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7292 state->data = NULL;
7293 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7294 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7295 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7296 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7297 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7299 state->call = tran_call;
7301 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7302 is so as a sanity check */
7303 if (state->setup_count != 1) {
7305 * Need to have rc=0 for ioctl to get job id for OS/2.
7306 * Network printing will fail if function is not successful.
7307 * Similar function in reply.c will be used if protocol
7308 * is LANMAN1.0 instead of LM1.2X002.
7309 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7310 * outbuf doesn't have to be set(only job id is used).
7312 if ( (state->setup_count == 4)
7313 && (tran_call == TRANSACT2_IOCTL)
7314 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7315 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7316 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7317 } else {
7318 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7319 DEBUG(2,("Transaction is %d\n",tran_call));
7320 TALLOC_FREE(state);
7321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7322 END_PROFILE(SMBtrans2);
7323 return;
7327 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7328 goto bad_param;
7330 if (state->total_data) {
7331 /* Can't use talloc here, the core routines do realloc on the
7332 * params and data. */
7333 state->data = (char *)SMB_MALLOC(state->total_data);
7334 if (state->data == NULL) {
7335 DEBUG(0,("reply_trans2: data malloc fail for %u "
7336 "bytes !\n", (unsigned int)state->total_data));
7337 TALLOC_FREE(state);
7338 reply_nterror(req, NT_STATUS_NO_MEMORY);
7339 END_PROFILE(SMBtrans2);
7340 return;
7342 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7343 goto bad_param;
7344 if ((smb_base(req->inbuf)+dsoff+dscnt
7345 > (char *)req->inbuf + size) ||
7346 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7347 goto bad_param;
7349 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7352 if (state->total_param) {
7353 /* Can't use talloc here, the core routines do realloc on the
7354 * params and data. */
7355 state->param = (char *)SMB_MALLOC(state->total_param);
7356 if (state->param == NULL) {
7357 DEBUG(0,("reply_trans: param malloc fail for %u "
7358 "bytes !\n", (unsigned int)state->total_param));
7359 SAFE_FREE(state->data);
7360 TALLOC_FREE(state);
7361 reply_nterror(req, NT_STATUS_NO_MEMORY);
7362 END_PROFILE(SMBtrans2);
7363 return;
7365 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7366 goto bad_param;
7367 if ((smb_base(req->inbuf)+psoff+pscnt
7368 > (char *)req->inbuf + size) ||
7369 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7370 goto bad_param;
7372 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7375 state->received_data = dscnt;
7376 state->received_param = pscnt;
7378 if ((state->received_param == state->total_param) &&
7379 (state->received_data == state->total_data)) {
7381 handle_trans2(conn, req, state);
7383 SAFE_FREE(state->data);
7384 SAFE_FREE(state->param);
7385 TALLOC_FREE(state);
7386 END_PROFILE(SMBtrans2);
7387 return;
7390 DLIST_ADD(conn->pending_trans, state);
7392 /* We need to send an interim response then receive the rest
7393 of the parameter/data bytes */
7394 reply_outbuf(req, 0, 0);
7395 show_msg((char *)req->outbuf);
7396 END_PROFILE(SMBtrans2);
7397 return;
7399 bad_param:
7401 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7402 SAFE_FREE(state->data);
7403 SAFE_FREE(state->param);
7404 TALLOC_FREE(state);
7405 END_PROFILE(SMBtrans2);
7406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7410 /****************************************************************************
7411 Reply to a SMBtranss2
7412 ****************************************************************************/
7414 void reply_transs2(struct smb_request *req)
7416 connection_struct *conn = req->conn;
7417 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7418 struct trans_state *state;
7419 int size;
7421 START_PROFILE(SMBtranss2);
7423 show_msg((char *)req->inbuf);
7425 if (req->wct < 8) {
7426 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7427 END_PROFILE(SMBtranss2);
7428 return;
7431 size = smb_len(req->inbuf)+4;
7433 for (state = conn->pending_trans; state != NULL;
7434 state = state->next) {
7435 if (state->mid == req->mid) {
7436 break;
7440 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7442 END_PROFILE(SMBtranss2);
7443 return;
7446 /* Revise state->total_param and state->total_data in case they have
7447 changed downwards */
7449 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7450 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7451 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7452 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7454 pcnt = SVAL(req->inbuf, smb_spscnt);
7455 poff = SVAL(req->inbuf, smb_spsoff);
7456 pdisp = SVAL(req->inbuf, smb_spsdisp);
7458 dcnt = SVAL(req->inbuf, smb_sdscnt);
7459 doff = SVAL(req->inbuf, smb_sdsoff);
7460 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7462 state->received_param += pcnt;
7463 state->received_data += dcnt;
7465 if ((state->received_data > state->total_data) ||
7466 (state->received_param > state->total_param))
7467 goto bad_param;
7469 if (pcnt) {
7470 if (pdisp+pcnt > state->total_param)
7471 goto bad_param;
7472 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7473 goto bad_param;
7474 if (pdisp > state->total_param)
7475 goto bad_param;
7476 if ((smb_base(req->inbuf) + poff + pcnt
7477 > (char *)req->inbuf + size) ||
7478 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7479 goto bad_param;
7480 if (state->param + pdisp < state->param)
7481 goto bad_param;
7483 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7484 pcnt);
7487 if (dcnt) {
7488 if (ddisp+dcnt > state->total_data)
7489 goto bad_param;
7490 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7491 goto bad_param;
7492 if (ddisp > state->total_data)
7493 goto bad_param;
7494 if ((smb_base(req->inbuf) + doff + dcnt
7495 > (char *)req->inbuf + size) ||
7496 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7497 goto bad_param;
7498 if (state->data + ddisp < state->data)
7499 goto bad_param;
7501 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7502 dcnt);
7505 if ((state->received_param < state->total_param) ||
7506 (state->received_data < state->total_data)) {
7507 END_PROFILE(SMBtranss2);
7508 return;
7512 * construct_reply_common will copy smb_com from inbuf to
7513 * outbuf. SMBtranss2 is wrong here.
7515 SCVAL(req->inbuf,smb_com,SMBtrans2);
7517 handle_trans2(conn, req, state);
7519 DLIST_REMOVE(conn->pending_trans, state);
7520 SAFE_FREE(state->data);
7521 SAFE_FREE(state->param);
7522 TALLOC_FREE(state);
7524 END_PROFILE(SMBtranss2);
7525 return;
7527 bad_param:
7529 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7530 DLIST_REMOVE(conn->pending_trans, state);
7531 SAFE_FREE(state->data);
7532 SAFE_FREE(state->param);
7533 TALLOC_FREE(state);
7534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7535 END_PROFILE(SMBtranss2);
7536 return;