r24102: Pass the fid instead of inbuf and an offset to file_fsp.
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blobd455a12fa112f8f12585bd1850c9b6fc57113b38
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
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 static char *store_file_unix_basic(connection_struct *conn,
38 char *pdata,
39 files_struct *fsp,
40 const SMB_STRUCT_STAT *psbuf);
42 static char *store_file_unix_basic_info2(connection_struct *conn,
43 char *pdata,
44 files_struct *fsp,
45 const SMB_STRUCT_STAT *psbuf);
47 /********************************************************************
48 Roundup a value to the nearest allocation roundup size boundary.
49 Only do this for Windows clients.
50 ********************************************************************/
52 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
54 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
56 /* Only roundup for Windows clients. */
57 enum remote_arch_types ra_type = get_remote_arch();
58 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
59 val = SMB_ROUNDUP(val,rval);
61 return val;
64 /********************************************************************
65 Given a stat buffer return the allocated size on disk, taking into
66 account sparse files.
67 ********************************************************************/
69 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
71 SMB_BIG_UINT ret;
73 if(S_ISDIR(sbuf->st_mode)) {
74 return 0;
77 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
78 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
79 #else
80 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
81 #endif
83 if (fsp && fsp->initial_allocation_size)
84 ret = MAX(ret,fsp->initial_allocation_size);
86 return smb_roundup(conn, ret);
89 /****************************************************************************
90 Utility functions for dealing with extended attributes.
91 ****************************************************************************/
93 /****************************************************************************
94 Refuse to allow clients to overwrite our private xattrs.
95 ****************************************************************************/
97 static BOOL samba_private_attr_name(const char *unix_ea_name)
99 static const char *prohibited_ea_names[] = {
100 SAMBA_POSIX_INHERITANCE_EA_NAME,
101 SAMBA_XATTR_DOS_ATTRIB,
102 NULL
105 int i;
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
109 return True;
111 return False;
114 /****************************************************************************
115 Get one EA value. Fill in a struct ea_struct.
116 ****************************************************************************/
118 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
119 const char *fname, char *ea_name, struct ea_struct *pea)
121 /* Get the value of this xattr. Max size is 64k. */
122 size_t attr_size = 256;
123 char *val = NULL;
124 ssize_t sizeret;
126 again:
128 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
129 if (!val) {
130 return False;
133 if (fsp && fsp->fh->fd != -1) {
134 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
135 } else {
136 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
139 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
140 attr_size = 65536;
141 goto again;
144 if (sizeret == -1) {
145 return False;
148 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
149 dump_data(10, (uint8 *)val, sizeret);
151 pea->flags = 0;
152 if (strnequal(ea_name, "user.", 5)) {
153 pea->name = &ea_name[5];
154 } else {
155 pea->name = ea_name;
157 pea->value.data = (unsigned char *)val;
158 pea->value.length = (size_t)sizeret;
159 return True;
162 /****************************************************************************
163 Return a linked list of the total EA's. Plus the total size
164 ****************************************************************************/
166 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
167 const char *fname, size_t *pea_total_len)
169 /* Get a list of all xattrs. Max namesize is 64k. */
170 size_t ea_namelist_size = 1024;
171 char *ea_namelist;
172 char *p;
173 ssize_t sizeret;
174 int i;
175 struct ea_list *ea_list_head = NULL;
177 *pea_total_len = 0;
179 if (!lp_ea_support(SNUM(conn))) {
180 return NULL;
183 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
184 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
186 if (!ea_namelist) {
187 return NULL;
190 if (fsp && fsp->fh->fd != -1) {
191 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
192 } else {
193 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
196 if (sizeret == -1 && errno == ERANGE) {
197 ea_namelist_size *= 2;
198 } else {
199 break;
203 if (sizeret == -1)
204 return NULL;
206 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
208 if (sizeret) {
209 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
210 struct ea_list *listp;
212 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
213 continue;
215 listp = TALLOC_P(mem_ctx, struct ea_list);
216 if (!listp)
217 return NULL;
219 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
220 return NULL;
224 fstring dos_ea_name;
225 push_ascii_fstring(dos_ea_name, listp->ea.name);
226 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
227 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
228 (unsigned int)*pea_total_len, dos_ea_name,
229 (unsigned int)listp->ea.value.length ));
231 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
233 /* Add on 4 for total length. */
234 if (*pea_total_len) {
235 *pea_total_len += 4;
239 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
240 return ea_list_head;
243 /****************************************************************************
244 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
245 that was filled.
246 ****************************************************************************/
248 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
249 connection_struct *conn, struct ea_list *ea_list)
251 unsigned int ret_data_size = 4;
252 char *p = pdata;
254 SMB_ASSERT(total_data_size >= 4);
256 if (!lp_ea_support(SNUM(conn))) {
257 SIVAL(pdata,4,0);
258 return 4;
261 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
262 size_t dos_namelen;
263 fstring dos_ea_name;
264 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
265 dos_namelen = strlen(dos_ea_name);
266 if (dos_namelen > 255 || dos_namelen == 0) {
267 break;
269 if (ea_list->ea.value.length > 65535) {
270 break;
272 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
273 break;
276 /* We know we have room. */
277 SCVAL(p,0,ea_list->ea.flags);
278 SCVAL(p,1,dos_namelen);
279 SSVAL(p,2,ea_list->ea.value.length);
280 fstrcpy(p+4, dos_ea_name);
281 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
283 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
284 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
287 ret_data_size = PTR_DIFF(p, pdata);
288 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
289 SIVAL(pdata,0,ret_data_size);
290 return ret_data_size;
293 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
295 size_t total_ea_len = 0;
296 TALLOC_CTX *mem_ctx = NULL;
298 if (!lp_ea_support(SNUM(conn))) {
299 return 0;
301 mem_ctx = talloc_init("estimate_ea_size");
302 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
303 talloc_destroy(mem_ctx);
304 return total_ea_len;
307 /****************************************************************************
308 Ensure the EA name is case insensitive by matching any existing EA name.
309 ****************************************************************************/
311 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
313 size_t total_ea_len;
314 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
315 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
317 for (; ea_list; ea_list = ea_list->next) {
318 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
319 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
320 &unix_ea_name[5], ea_list->ea.name));
321 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
322 break;
325 talloc_destroy(mem_ctx);
328 /****************************************************************************
329 Set or delete an extended attribute.
330 ****************************************************************************/
332 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
334 if (!lp_ea_support(SNUM(conn))) {
335 return NT_STATUS_EAS_NOT_SUPPORTED;
338 for (;ea_list; ea_list = ea_list->next) {
339 int ret;
340 fstring unix_ea_name;
342 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
343 fstrcat(unix_ea_name, ea_list->ea.name);
345 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
347 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
349 if (samba_private_attr_name(unix_ea_name)) {
350 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
351 return NT_STATUS_ACCESS_DENIED;
354 if (ea_list->ea.value.length == 0) {
355 /* Remove the attribute. */
356 if (fsp && (fsp->fh->fd != -1)) {
357 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
358 unix_ea_name, fsp->fsp_name));
359 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
360 } else {
361 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
362 unix_ea_name, fname));
363 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
365 #ifdef ENOATTR
366 /* Removing a non existent attribute always succeeds. */
367 if (ret == -1 && errno == ENOATTR) {
368 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
369 unix_ea_name));
370 ret = 0;
372 #endif
373 } else {
374 if (fsp && (fsp->fh->fd != -1)) {
375 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
376 unix_ea_name, fsp->fsp_name));
377 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
378 ea_list->ea.value.data, ea_list->ea.value.length, 0);
379 } else {
380 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
381 unix_ea_name, fname));
382 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
383 ea_list->ea.value.data, ea_list->ea.value.length, 0);
387 if (ret == -1) {
388 #ifdef ENOTSUP
389 if (errno == ENOTSUP) {
390 return NT_STATUS_EAS_NOT_SUPPORTED;
392 #endif
393 return map_nt_error_from_unix(errno);
397 return NT_STATUS_OK;
399 /****************************************************************************
400 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
401 ****************************************************************************/
403 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
405 struct ea_list *ea_list_head = NULL;
406 size_t offset = 0;
408 while (offset + 2 < data_size) {
409 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
410 unsigned int namelen = CVAL(pdata,offset);
412 offset++; /* Go past the namelen byte. */
414 /* integer wrap paranioa. */
415 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
416 (offset > data_size) || (namelen > data_size) ||
417 (offset + namelen >= data_size)) {
418 break;
420 /* Ensure the name is null terminated. */
421 if (pdata[offset + namelen] != '\0') {
422 return NULL;
424 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
425 if (!eal->ea.name) {
426 return NULL;
429 offset += (namelen + 1); /* Go past the name + terminating zero. */
430 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
431 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
434 return ea_list_head;
437 /****************************************************************************
438 Read one EA list entry from the buffer.
439 ****************************************************************************/
441 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
443 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
444 uint16 val_len;
445 unsigned int namelen;
447 if (!eal) {
448 return NULL;
451 if (data_size < 6) {
452 return NULL;
455 eal->ea.flags = CVAL(pdata,0);
456 namelen = CVAL(pdata,1);
457 val_len = SVAL(pdata,2);
459 if (4 + namelen + 1 + val_len > data_size) {
460 return NULL;
463 /* Ensure the name is null terminated. */
464 if (pdata[namelen + 4] != '\0') {
465 return NULL;
467 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
468 if (!eal->ea.name) {
469 return NULL;
472 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
473 if (!eal->ea.value.data) {
474 return NULL;
477 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
479 /* Ensure we're null terminated just in case we print the value. */
480 eal->ea.value.data[val_len] = '\0';
481 /* But don't count the null. */
482 eal->ea.value.length--;
484 if (pbytes_used) {
485 *pbytes_used = 4 + namelen + 1 + val_len;
488 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
489 dump_data(10, eal->ea.value.data, eal->ea.value.length);
491 return eal;
494 /****************************************************************************
495 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
496 ****************************************************************************/
498 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
500 struct ea_list *ea_list_head = NULL;
501 size_t offset = 0;
502 size_t bytes_used = 0;
504 while (offset < data_size) {
505 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
507 if (!eal) {
508 return NULL;
511 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
512 offset += bytes_used;
515 return ea_list_head;
518 /****************************************************************************
519 Count the total EA size needed.
520 ****************************************************************************/
522 static size_t ea_list_size(struct ea_list *ealist)
524 fstring dos_ea_name;
525 struct ea_list *listp;
526 size_t ret = 0;
528 for (listp = ealist; listp; listp = listp->next) {
529 push_ascii_fstring(dos_ea_name, listp->ea.name);
530 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
532 /* Add on 4 for total length. */
533 if (ret) {
534 ret += 4;
537 return ret;
540 /****************************************************************************
541 Return a union of EA's from a file list and a list of names.
542 The TALLOC context for the two lists *MUST* be identical as we steal
543 memory from one list to add to another. JRA.
544 ****************************************************************************/
546 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
548 struct ea_list *nlistp, *flistp;
550 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
551 for (flistp = file_list; flistp; flistp = flistp->next) {
552 if (strequal(nlistp->ea.name, flistp->ea.name)) {
553 break;
557 if (flistp) {
558 /* Copy the data from this entry. */
559 nlistp->ea.flags = flistp->ea.flags;
560 nlistp->ea.value = flistp->ea.value;
561 } else {
562 /* Null entry. */
563 nlistp->ea.flags = 0;
564 ZERO_STRUCT(nlistp->ea.value);
568 *total_ea_len = ea_list_size(name_list);
569 return name_list;
572 /****************************************************************************
573 Send the required number of replies back.
574 We assume all fields other than the data fields are
575 set correctly for the type of call.
576 HACK ! Always assumes smb_setup field is zero.
577 ****************************************************************************/
579 int send_trans2_replies(const char *inbuf,
580 char *outbuf,
581 int bufsize,
582 const char *params,
583 int paramsize,
584 const char *pdata,
585 int datasize,
586 int max_data_bytes)
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
596 int useable_space;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(inbuf,outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
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 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
622 show_msg(outbuf);
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
625 return 0;
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(inbuf, outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
685 else
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
693 } else {
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
717 show_msg(outbuf);
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
727 /* Sanity check */
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
731 return -1;
735 return 0;
738 /****************************************************************************
739 Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
742 static int call_trans2open(connection_struct *conn,
743 struct smb_request *req,
744 char *inbuf, char *outbuf, int bufsize,
745 char **pparams, int total_params,
746 char **ppdata, int total_data,
747 unsigned int max_data_bytes)
749 char *params = *pparams;
750 char *pdata = *ppdata;
751 int deny_mode;
752 int32 open_attr;
753 BOOL oplock_request;
754 #if 0
755 BOOL return_additional_info;
756 int16 open_sattr;
757 time_t open_time;
758 #endif
759 int open_ofun;
760 uint32 open_size;
761 char *pname;
762 pstring fname;
763 SMB_OFF_T size=0;
764 int fattr=0,mtime=0;
765 SMB_INO_T inode = 0;
766 SMB_STRUCT_STAT sbuf;
767 int smb_action = 0;
768 files_struct *fsp;
769 struct ea_list *ea_list = NULL;
770 uint16 flags = 0;
771 NTSTATUS status;
772 uint32 access_mask;
773 uint32 share_mode;
774 uint32 create_disposition;
775 uint32 create_options = 0;
778 * Ensure we have enough parameters to perform the operation.
781 if (total_params < 29) {
782 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
785 flags = SVAL(params, 0);
786 deny_mode = SVAL(params, 2);
787 open_attr = SVAL(params,6);
788 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
789 if (oplock_request) {
790 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
793 #if 0
794 return_additional_info = BITSETW(params,0);
795 open_sattr = SVAL(params, 4);
796 open_time = make_unix_date3(params+8);
797 #endif
798 open_ofun = SVAL(params,12);
799 open_size = IVAL(params,14);
800 pname = &params[28];
802 if (IS_IPC(conn)) {
803 return(ERROR_DOS(ERRSRV,ERRaccess));
806 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, pname,
807 sizeof(fname), total_params - 28, STR_TERMINATE,
808 &status);
809 if (!NT_STATUS_IS_OK(status)) {
810 return ERROR_NT(status);
813 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
814 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
815 (unsigned int)open_ofun, open_size));
817 /* XXXX we need to handle passed times, sattr and flags */
819 status = unix_convert(conn, fname, False, NULL, &sbuf);
820 if (!NT_STATUS_IS_OK(status)) {
821 return ERROR_NT(status);
824 status = check_name(conn, fname);
825 if (!NT_STATUS_IS_OK(status)) {
826 return ERROR_NT(status);
829 if (open_ofun == 0) {
830 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
833 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
834 &access_mask,
835 &share_mode,
836 &create_disposition,
837 &create_options)) {
838 return ERROR_DOS(ERRDOS, ERRbadaccess);
841 /* Any data in this call is an EA list. */
842 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
843 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
846 if (total_data != 4) {
847 if (total_data < 10) {
848 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
851 if (IVAL(pdata,0) > total_data) {
852 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
853 IVAL(pdata,0), (unsigned int)total_data));
854 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
857 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
858 total_data - 4);
859 if (!ea_list) {
860 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
862 } else if (IVAL(pdata,0) != 4) {
863 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
866 status = open_file_ntcreate(conn, req, fname, &sbuf,
867 access_mask,
868 share_mode,
869 create_disposition,
870 create_options,
871 open_attr,
872 oplock_request,
873 &smb_action, &fsp);
875 if (!NT_STATUS_IS_OK(status)) {
876 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
877 /* We have re-scheduled this call. */
878 return -1;
880 return ERROR_NT(status);
883 size = get_file_size(sbuf);
884 fattr = dos_mode(conn,fname,&sbuf);
885 mtime = sbuf.st_mtime;
886 inode = sbuf.st_ino;
887 if (fattr & aDIR) {
888 close_file(fsp,ERROR_CLOSE);
889 return(ERROR_DOS(ERRDOS,ERRnoaccess));
892 /* Save the requested allocation size. */
893 /* Allocate space for the file if a size hint is supplied */
894 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
895 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
896 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
897 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
898 if (fsp->is_directory) {
899 close_file(fsp,ERROR_CLOSE);
900 /* Can't set allocation size on a directory. */
901 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
903 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
904 close_file(fsp,ERROR_CLOSE);
905 return ERROR_NT(NT_STATUS_DISK_FULL);
908 /* Adjust size here to return the right size in the reply.
909 Windows does it this way. */
910 size = fsp->initial_allocation_size;
911 } else {
912 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
916 if (ea_list && smb_action == FILE_WAS_CREATED) {
917 status = set_ea(conn, fsp, fname, ea_list);
918 if (!NT_STATUS_IS_OK(status)) {
919 close_file(fsp,ERROR_CLOSE);
920 return ERROR_NT(status);
924 /* Realloc the size of parameters and data we will return */
925 *pparams = (char *)SMB_REALLOC(*pparams, 30);
926 if(*pparams == NULL ) {
927 return ERROR_NT(NT_STATUS_NO_MEMORY);
929 params = *pparams;
931 SSVAL(params,0,fsp->fnum);
932 SSVAL(params,2,fattr);
933 srv_put_dos_date2(params,4, mtime);
934 SIVAL(params,8, (uint32)size);
935 SSVAL(params,12,deny_mode);
936 SSVAL(params,14,0); /* open_type - file or directory. */
937 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
939 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
940 smb_action |= EXTENDED_OPLOCK_GRANTED;
943 SSVAL(params,18,smb_action);
946 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
948 SIVAL(params,20,inode);
949 SSVAL(params,24,0); /* Padding. */
950 if (flags & 8) {
951 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
952 SIVAL(params, 26, ea_size);
953 } else {
954 SIVAL(params, 26, 0);
957 /* Send the required number of replies */
958 send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
960 return -1;
963 /*********************************************************
964 Routine to check if a given string matches exactly.
965 as a special case a mask of "." does NOT match. That
966 is required for correct wildcard semantics
967 Case can be significant or not.
968 **********************************************************/
970 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
972 if (mask[0] == '.' && mask[1] == 0)
973 return False;
974 if (conn->case_sensitive)
975 return strcmp(str,mask)==0;
976 if (StrCaseCmp(str,mask) != 0) {
977 return False;
979 if (dptr_has_wild(conn->dirptr)) {
980 return False;
982 return True;
985 /****************************************************************************
986 Return the filetype for UNIX extensions.
987 ****************************************************************************/
989 static uint32 unix_filetype(mode_t mode)
991 if(S_ISREG(mode))
992 return UNIX_TYPE_FILE;
993 else if(S_ISDIR(mode))
994 return UNIX_TYPE_DIR;
995 #ifdef S_ISLNK
996 else if(S_ISLNK(mode))
997 return UNIX_TYPE_SYMLINK;
998 #endif
999 #ifdef S_ISCHR
1000 else if(S_ISCHR(mode))
1001 return UNIX_TYPE_CHARDEV;
1002 #endif
1003 #ifdef S_ISBLK
1004 else if(S_ISBLK(mode))
1005 return UNIX_TYPE_BLKDEV;
1006 #endif
1007 #ifdef S_ISFIFO
1008 else if(S_ISFIFO(mode))
1009 return UNIX_TYPE_FIFO;
1010 #endif
1011 #ifdef S_ISSOCK
1012 else if(S_ISSOCK(mode))
1013 return UNIX_TYPE_SOCKET;
1014 #endif
1016 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1017 return UNIX_TYPE_UNKNOWN;
1020 /****************************************************************************
1021 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1022 ****************************************************************************/
1024 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1026 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1027 SMB_STRUCT_STAT *psbuf,
1028 uint32 perms,
1029 enum perm_type ptype,
1030 mode_t *ret_perms)
1032 mode_t ret = 0;
1034 if (perms == SMB_MODE_NO_CHANGE) {
1035 if (!VALID_STAT(*psbuf)) {
1036 return NT_STATUS_INVALID_PARAMETER;
1037 } else {
1038 *ret_perms = psbuf->st_mode;
1039 return NT_STATUS_OK;
1043 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1044 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1045 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1046 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1047 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1048 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1049 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1050 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1051 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1052 #ifdef S_ISVTX
1053 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1054 #endif
1055 #ifdef S_ISGID
1056 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1057 #endif
1058 #ifdef S_ISUID
1059 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1060 #endif
1062 switch (ptype) {
1063 case PERM_NEW_FILE:
1064 /* Apply mode mask */
1065 ret &= lp_create_mask(SNUM(conn));
1066 /* Add in force bits */
1067 ret |= lp_force_create_mode(SNUM(conn));
1068 break;
1069 case PERM_NEW_DIR:
1070 ret &= lp_dir_mask(SNUM(conn));
1071 /* Add in force bits */
1072 ret |= lp_force_dir_mode(SNUM(conn));
1073 break;
1074 case PERM_EXISTING_FILE:
1075 /* Apply mode mask */
1076 ret &= lp_security_mask(SNUM(conn));
1077 /* Add in force bits */
1078 ret |= lp_force_security_mode(SNUM(conn));
1079 break;
1080 case PERM_EXISTING_DIR:
1081 /* Apply mode mask */
1082 ret &= lp_dir_security_mask(SNUM(conn));
1083 /* Add in force bits */
1084 ret |= lp_force_dir_security_mode(SNUM(conn));
1085 break;
1088 *ret_perms = ret;
1089 return NT_STATUS_OK;
1092 /****************************************************************************
1093 Get a level dependent lanman2 dir entry.
1094 ****************************************************************************/
1096 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1097 void *inbuf, char *outbuf,
1098 char *path_mask,uint32 dirtype,int info_level,
1099 int requires_resume_key,
1100 BOOL dont_descend,char **ppdata,
1101 char *base_data, int space_remaining,
1102 BOOL *out_of_space, BOOL *got_exact_match,
1103 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1105 const char *dname;
1106 BOOL found = False;
1107 SMB_STRUCT_STAT sbuf;
1108 pstring mask;
1109 pstring pathreal;
1110 pstring fname;
1111 char *p, *q, *pdata = *ppdata;
1112 uint32 reskey=0;
1113 long prev_dirpos=0;
1114 uint32 mode=0;
1115 SMB_OFF_T file_size = 0;
1116 SMB_BIG_UINT allocation_size = 0;
1117 uint32 len;
1118 struct timespec mdate_ts, adate_ts, create_date_ts;
1119 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1120 char *nameptr;
1121 char *last_entry_ptr;
1122 BOOL was_8_3;
1123 uint32 nt_extmode; /* Used for NT connections instead of mode */
1124 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1125 BOOL check_mangled_names = lp_manglednames(conn->params);
1127 *fname = 0;
1128 *out_of_space = False;
1129 *got_exact_match = False;
1131 ZERO_STRUCT(mdate_ts);
1132 ZERO_STRUCT(adate_ts);
1133 ZERO_STRUCT(create_date_ts);
1135 if (!conn->dirptr)
1136 return(False);
1138 p = strrchr_m(path_mask,'/');
1139 if(p != NULL) {
1140 if(p[1] == '\0')
1141 pstrcpy(mask,"*.*");
1142 else
1143 pstrcpy(mask, p+1);
1144 } else
1145 pstrcpy(mask, path_mask);
1148 while (!found) {
1149 BOOL got_match;
1150 BOOL ms_dfs_link = False;
1152 /* Needed if we run out of space */
1153 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1154 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1157 * Due to bugs in NT client redirectors we are not using
1158 * resume keys any more - set them to zero.
1159 * Check out the related comments in findfirst/findnext.
1160 * JRA.
1163 reskey = 0;
1165 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1166 (long)conn->dirptr,curr_dirpos));
1168 if (!dname) {
1169 return(False);
1173 * fname may get mangled, dname is never mangled.
1174 * Whenever we're accessing the filesystem we use
1175 * pathreal which is composed from dname.
1178 pstrcpy(fname,dname);
1180 /* This will mangle fname if it's an illegal name. */
1181 mangle_map(fname,False,True,conn->params);
1183 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1184 got_match = mask_match(fname, mask, conn->case_sensitive);
1187 if(!got_match && check_mangled_names &&
1188 !mangle_is_8_3(fname, False, conn->params)) {
1189 pstring mangled_name;
1192 * It turns out that NT matches wildcards against
1193 * both long *and* short names. This may explain some
1194 * of the wildcard wierdness from old DOS clients
1195 * that some people have been seeing.... JRA.
1198 pstrcpy(mangled_name, fname);
1200 /* Force the mangling into 8.3. */
1201 mangle_map( mangled_name, True, False, conn->params);
1202 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1203 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1207 if (got_match) {
1208 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1209 if (dont_descend && !isdots) {
1210 continue;
1213 pstrcpy(pathreal,conn->dirpath);
1214 if(needslash) {
1215 pstrcat(pathreal,"/");
1217 pstrcat(pathreal,dname);
1219 if (INFO_LEVEL_IS_UNIX(info_level)) {
1220 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1221 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1222 pathreal,strerror(errno)));
1223 continue;
1225 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1226 pstring link_target;
1228 /* Needed to show the msdfs symlinks as
1229 * directories */
1231 if(lp_host_msdfs() &&
1232 lp_msdfs_root(SNUM(conn)) &&
1233 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1234 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1235 "as a directory\n",
1236 pathreal));
1237 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1239 } else {
1241 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1242 pathreal,strerror(errno)));
1243 continue;
1247 if (ms_dfs_link) {
1248 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1249 } else {
1250 mode = dos_mode(conn,pathreal,&sbuf);
1253 if (!dir_check_ftype(conn,mode,dirtype)) {
1254 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1255 continue;
1258 if (!(mode & aDIR)) {
1259 file_size = get_file_size(sbuf);
1261 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1263 mdate_ts = get_mtimespec(&sbuf);
1264 adate_ts = get_atimespec(&sbuf);
1265 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1267 if (lp_dos_filetime_resolution(SNUM(conn))) {
1268 dos_filetime_timespec(&create_date_ts);
1269 dos_filetime_timespec(&mdate_ts);
1270 dos_filetime_timespec(&adate_ts);
1273 create_date = convert_timespec_to_time_t(create_date_ts);
1274 mdate = convert_timespec_to_time_t(mdate_ts);
1275 adate = convert_timespec_to_time_t(adate_ts);
1277 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1279 found = True;
1281 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1285 p = pdata;
1286 last_entry_ptr = p;
1288 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1290 switch (info_level) {
1291 case SMB_FIND_INFO_STANDARD:
1292 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1293 if(requires_resume_key) {
1294 SIVAL(p,0,reskey);
1295 p += 4;
1297 srv_put_dos_date2(p,0,create_date);
1298 srv_put_dos_date2(p,4,adate);
1299 srv_put_dos_date2(p,8,mdate);
1300 SIVAL(p,12,(uint32)file_size);
1301 SIVAL(p,16,(uint32)allocation_size);
1302 SSVAL(p,20,mode);
1303 p += 23;
1304 nameptr = p;
1305 p += align_string(outbuf, p, 0);
1306 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1307 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1308 if (len > 2) {
1309 SCVAL(nameptr, -1, len - 2);
1310 } else {
1311 SCVAL(nameptr, -1, 0);
1313 } else {
1314 if (len > 1) {
1315 SCVAL(nameptr, -1, len - 1);
1316 } else {
1317 SCVAL(nameptr, -1, 0);
1320 p += len;
1321 break;
1323 case SMB_FIND_EA_SIZE:
1324 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1325 if(requires_resume_key) {
1326 SIVAL(p,0,reskey);
1327 p += 4;
1329 srv_put_dos_date2(p,0,create_date);
1330 srv_put_dos_date2(p,4,adate);
1331 srv_put_dos_date2(p,8,mdate);
1332 SIVAL(p,12,(uint32)file_size);
1333 SIVAL(p,16,(uint32)allocation_size);
1334 SSVAL(p,20,mode);
1336 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1337 SIVAL(p,22,ea_size); /* Extended attributes */
1339 p += 27;
1340 nameptr = p - 1;
1341 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1342 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1343 if (len > 2) {
1344 len -= 2;
1345 } else {
1346 len = 0;
1348 } else {
1349 if (len > 1) {
1350 len -= 1;
1351 } else {
1352 len = 0;
1355 SCVAL(nameptr,0,len);
1356 p += len;
1357 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1358 break;
1360 case SMB_FIND_EA_LIST:
1362 struct ea_list *file_list = NULL;
1363 size_t ea_len = 0;
1365 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1366 if (!name_list) {
1367 return False;
1369 if(requires_resume_key) {
1370 SIVAL(p,0,reskey);
1371 p += 4;
1373 srv_put_dos_date2(p,0,create_date);
1374 srv_put_dos_date2(p,4,adate);
1375 srv_put_dos_date2(p,8,mdate);
1376 SIVAL(p,12,(uint32)file_size);
1377 SIVAL(p,16,(uint32)allocation_size);
1378 SSVAL(p,20,mode);
1379 p += 22; /* p now points to the EA area. */
1381 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1382 name_list = ea_list_union(name_list, file_list, &ea_len);
1384 /* We need to determine if this entry will fit in the space available. */
1385 /* Max string size is 255 bytes. */
1386 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1387 /* Move the dirptr back to prev_dirpos */
1388 dptr_SeekDir(conn->dirptr, prev_dirpos);
1389 *out_of_space = True;
1390 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1391 return False; /* Not finished - just out of space */
1394 /* Push the ea_data followed by the name. */
1395 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1396 nameptr = p;
1397 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1398 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1399 if (len > 2) {
1400 len -= 2;
1401 } else {
1402 len = 0;
1404 } else {
1405 if (len > 1) {
1406 len -= 1;
1407 } else {
1408 len = 0;
1411 SCVAL(nameptr,0,len);
1412 p += len + 1;
1413 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1414 break;
1417 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1418 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1419 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1420 p += 4;
1421 SIVAL(p,0,reskey); p += 4;
1422 put_long_date_timespec(p,create_date_ts); p += 8;
1423 put_long_date_timespec(p,adate_ts); p += 8;
1424 put_long_date_timespec(p,mdate_ts); p += 8;
1425 put_long_date_timespec(p,mdate_ts); p += 8;
1426 SOFF_T(p,0,file_size); p += 8;
1427 SOFF_T(p,0,allocation_size); p += 8;
1428 SIVAL(p,0,nt_extmode); p += 4;
1429 q = p; p += 4; /* q is placeholder for name length. */
1431 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1432 SIVAL(p,0,ea_size); /* Extended attributes */
1433 p += 4;
1435 /* Clear the short name buffer. This is
1436 * IMPORTANT as not doing so will trigger
1437 * a Win2k client bug. JRA.
1439 if (!was_8_3 && check_mangled_names) {
1440 pstring mangled_name;
1441 pstrcpy(mangled_name, fname);
1442 mangle_map(mangled_name,True,True,
1443 conn->params);
1444 mangled_name[12] = 0;
1445 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1446 if (len < 24) {
1447 memset(p + 2 + len,'\0',24 - len);
1449 SSVAL(p, 0, len);
1450 } else {
1451 memset(p,'\0',26);
1453 p += 2 + 24;
1454 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1455 SIVAL(q,0,len);
1456 p += len;
1457 SIVAL(p,0,0); /* Ensure any padding is null. */
1458 len = PTR_DIFF(p, pdata);
1459 len = (len + 3) & ~3;
1460 SIVAL(pdata,0,len);
1461 p = pdata + len;
1462 break;
1464 case SMB_FIND_FILE_DIRECTORY_INFO:
1465 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1466 p += 4;
1467 SIVAL(p,0,reskey); p += 4;
1468 put_long_date_timespec(p,create_date_ts); p += 8;
1469 put_long_date_timespec(p,adate_ts); p += 8;
1470 put_long_date_timespec(p,mdate_ts); p += 8;
1471 put_long_date_timespec(p,mdate_ts); p += 8;
1472 SOFF_T(p,0,file_size); p += 8;
1473 SOFF_T(p,0,allocation_size); p += 8;
1474 SIVAL(p,0,nt_extmode); p += 4;
1475 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1476 SIVAL(p,0,len);
1477 p += 4 + len;
1478 SIVAL(p,0,0); /* Ensure any padding is null. */
1479 len = PTR_DIFF(p, pdata);
1480 len = (len + 3) & ~3;
1481 SIVAL(pdata,0,len);
1482 p = pdata + len;
1483 break;
1485 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1486 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1487 p += 4;
1488 SIVAL(p,0,reskey); p += 4;
1489 put_long_date_timespec(p,create_date_ts); p += 8;
1490 put_long_date_timespec(p,adate_ts); p += 8;
1491 put_long_date_timespec(p,mdate_ts); p += 8;
1492 put_long_date_timespec(p,mdate_ts); p += 8;
1493 SOFF_T(p,0,file_size); p += 8;
1494 SOFF_T(p,0,allocation_size); p += 8;
1495 SIVAL(p,0,nt_extmode); p += 4;
1496 q = p; p += 4; /* q is placeholder for name length. */
1498 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1499 SIVAL(p,0,ea_size); /* Extended attributes */
1500 p +=4;
1502 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1503 SIVAL(q, 0, len);
1504 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_NAMES_INFO:
1514 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1515 p += 4;
1516 SIVAL(p,0,reskey); p += 4;
1517 p += 4;
1518 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1519 acl on a dir (tridge) */
1520 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1521 SIVAL(p, -4, len);
1522 p += len;
1523 SIVAL(p,0,0); /* Ensure any padding is null. */
1524 len = PTR_DIFF(p, pdata);
1525 len = (len + 3) & ~3;
1526 SIVAL(pdata,0,len);
1527 p = pdata + len;
1528 break;
1530 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1531 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1532 p += 4;
1533 SIVAL(p,0,reskey); p += 4;
1534 put_long_date_timespec(p,create_date_ts); p += 8;
1535 put_long_date_timespec(p,adate_ts); p += 8;
1536 put_long_date_timespec(p,mdate_ts); p += 8;
1537 put_long_date_timespec(p,mdate_ts); p += 8;
1538 SOFF_T(p,0,file_size); p += 8;
1539 SOFF_T(p,0,allocation_size); p += 8;
1540 SIVAL(p,0,nt_extmode); p += 4;
1541 q = p; p += 4; /* q is placeholder for name length. */
1543 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1544 SIVAL(p,0,ea_size); /* Extended attributes */
1545 p +=4;
1547 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1548 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1549 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1550 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1551 SIVAL(q, 0, len);
1552 p += len;
1553 SIVAL(p,0,0); /* Ensure any padding is null. */
1554 len = PTR_DIFF(p, pdata);
1555 len = (len + 3) & ~3;
1556 SIVAL(pdata,0,len);
1557 p = pdata + len;
1558 break;
1560 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1561 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1562 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1563 p += 4;
1564 SIVAL(p,0,reskey); p += 4;
1565 put_long_date_timespec(p,create_date_ts); p += 8;
1566 put_long_date_timespec(p,adate_ts); p += 8;
1567 put_long_date_timespec(p,mdate_ts); p += 8;
1568 put_long_date_timespec(p,mdate_ts); p += 8;
1569 SOFF_T(p,0,file_size); p += 8;
1570 SOFF_T(p,0,allocation_size); p += 8;
1571 SIVAL(p,0,nt_extmode); p += 4;
1572 q = p; p += 4; /* q is placeholder for name length */
1574 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1575 SIVAL(p,0,ea_size); /* Extended attributes */
1576 p +=4;
1578 /* Clear the short name buffer. This is
1579 * IMPORTANT as not doing so will trigger
1580 * a Win2k client bug. JRA.
1582 if (!was_8_3 && check_mangled_names) {
1583 pstring mangled_name;
1584 pstrcpy(mangled_name, fname);
1585 mangle_map(mangled_name,True,True,
1586 conn->params);
1587 mangled_name[12] = 0;
1588 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1589 SSVAL(p, 0, len);
1590 if (len < 24) {
1591 memset(p + 2 + len,'\0',24 - len);
1593 SSVAL(p, 0, len);
1594 } else {
1595 memset(p,'\0',26);
1597 p += 26;
1598 SSVAL(p,0,0); p += 2; /* Reserved ? */
1599 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1600 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1601 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1602 SIVAL(q,0,len);
1603 p += len;
1604 SIVAL(p,0,0); /* Ensure any padding is null. */
1605 len = PTR_DIFF(p, pdata);
1606 len = (len + 3) & ~3;
1607 SIVAL(pdata,0,len);
1608 p = pdata + len;
1609 break;
1611 /* CIFS UNIX Extension. */
1613 case SMB_FIND_FILE_UNIX:
1614 case SMB_FIND_FILE_UNIX_INFO2:
1615 p+= 4;
1616 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1618 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1620 if (info_level == SMB_FIND_FILE_UNIX) {
1621 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1622 p = store_file_unix_basic(conn, p,
1623 NULL, &sbuf);
1624 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1625 } else {
1626 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1627 p = store_file_unix_basic_info2(conn, p,
1628 NULL, &sbuf);
1629 nameptr = p;
1630 p += 4;
1631 len = srvstr_push(outbuf, p, fname, -1, 0);
1632 SIVAL(nameptr, 0, len);
1635 p += len;
1636 SIVAL(p,0,0); /* Ensure any padding is null. */
1638 len = PTR_DIFF(p, pdata);
1639 len = (len + 3) & ~3;
1640 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1641 p = pdata + len;
1642 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1644 break;
1646 default:
1647 return(False);
1651 if (PTR_DIFF(p,pdata) > space_remaining) {
1652 /* Move the dirptr back to prev_dirpos */
1653 dptr_SeekDir(conn->dirptr, prev_dirpos);
1654 *out_of_space = True;
1655 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1656 return False; /* Not finished - just out of space */
1659 /* Setup the last entry pointer, as an offset from base_data */
1660 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1661 /* Advance the data pointer to the next slot */
1662 *ppdata = p;
1664 return(found);
1667 /****************************************************************************
1668 Reply to a TRANS2_FINDFIRST.
1669 ****************************************************************************/
1671 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1672 char **pparams, int total_params, char **ppdata, int total_data,
1673 unsigned int max_data_bytes)
1675 /* We must be careful here that we don't return more than the
1676 allowed number of data bytes. If this means returning fewer than
1677 maxentries then so be it. We assume that the redirector has
1678 enough room for the fixed number of parameter bytes it has
1679 requested. */
1680 char *params = *pparams;
1681 char *pdata = *ppdata;
1682 uint32 dirtype;
1683 int maxentries;
1684 uint16 findfirst_flags;
1685 BOOL close_after_first;
1686 BOOL close_if_end;
1687 BOOL requires_resume_key;
1688 int info_level;
1689 pstring directory;
1690 pstring mask;
1691 char *p;
1692 int last_entry_off=0;
1693 int dptr_num = -1;
1694 int numentries = 0;
1695 int i;
1696 BOOL finished = False;
1697 BOOL dont_descend = False;
1698 BOOL out_of_space = False;
1699 int space_remaining;
1700 BOOL mask_contains_wcard = False;
1701 SMB_STRUCT_STAT sbuf;
1702 TALLOC_CTX *ea_ctx = NULL;
1703 struct ea_list *ea_list = NULL;
1704 NTSTATUS ntstatus = NT_STATUS_OK;
1706 if (total_params < 13) {
1707 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1710 dirtype = SVAL(params,0);
1711 maxentries = SVAL(params,2);
1712 findfirst_flags = SVAL(params,4);
1713 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1714 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1715 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1716 info_level = SVAL(params,6);
1718 *directory = *mask = 0;
1720 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1721 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1722 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1723 info_level, max_data_bytes));
1725 if (!maxentries) {
1726 /* W2K3 seems to treat zero as 1. */
1727 maxentries = 1;
1730 switch (info_level) {
1731 case SMB_FIND_INFO_STANDARD:
1732 case SMB_FIND_EA_SIZE:
1733 case SMB_FIND_EA_LIST:
1734 case SMB_FIND_FILE_DIRECTORY_INFO:
1735 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1736 case SMB_FIND_FILE_NAMES_INFO:
1737 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1738 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1739 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1740 break;
1741 case SMB_FIND_FILE_UNIX:
1742 case SMB_FIND_FILE_UNIX_INFO2:
1743 if (!lp_unix_extensions()) {
1744 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1746 break;
1747 default:
1748 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1751 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), directory,
1752 params+12, sizeof(directory), total_params - 12,
1753 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1754 if (!NT_STATUS_IS_OK(ntstatus)) {
1755 return ERROR_NT(ntstatus);
1758 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1759 if (!NT_STATUS_IS_OK(ntstatus)) {
1760 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1761 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1763 return ERROR_NT(ntstatus);
1766 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1767 if (!NT_STATUS_IS_OK(ntstatus)) {
1768 return ERROR_NT(ntstatus);
1770 ntstatus = check_name(conn, directory);
1771 if (!NT_STATUS_IS_OK(ntstatus)) {
1772 return ERROR_NT(ntstatus);
1775 p = strrchr_m(directory,'/');
1776 if(p == NULL) {
1777 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1778 if((directory[0] == '.') && (directory[1] == '\0')) {
1779 pstrcpy(mask,"*");
1780 mask_contains_wcard = True;
1781 } else {
1782 pstrcpy(mask,directory);
1784 pstrcpy(directory,"./");
1785 } else {
1786 pstrcpy(mask,p+1);
1787 *p = 0;
1790 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1792 if (info_level == SMB_FIND_EA_LIST) {
1793 uint32 ea_size;
1795 if (total_data < 4) {
1796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1799 ea_size = IVAL(pdata,0);
1800 if (ea_size != total_data) {
1801 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1802 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1803 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1806 if (!lp_ea_support(SNUM(conn))) {
1807 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1810 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1811 return ERROR_NT(NT_STATUS_NO_MEMORY);
1814 /* Pull out the list of names. */
1815 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1816 if (!ea_list) {
1817 talloc_destroy(ea_ctx);
1818 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1822 *ppdata = (char *)SMB_REALLOC(
1823 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1824 if(*ppdata == NULL ) {
1825 talloc_destroy(ea_ctx);
1826 return ERROR_NT(NT_STATUS_NO_MEMORY);
1828 pdata = *ppdata;
1830 /* Realloc the params space */
1831 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1832 if (*pparams == NULL) {
1833 talloc_destroy(ea_ctx);
1834 return ERROR_NT(NT_STATUS_NO_MEMORY);
1836 params = *pparams;
1838 /* Save the wildcard match and attribs we are using on this directory -
1839 needed as lanman2 assumes these are being saved between calls */
1841 ntstatus = dptr_create(conn,
1842 directory,
1843 False,
1844 True,
1845 SVAL(inbuf,smb_pid),
1846 mask,
1847 mask_contains_wcard,
1848 dirtype,
1849 &conn->dirptr);
1851 if (!NT_STATUS_IS_OK(ntstatus)) {
1852 talloc_destroy(ea_ctx);
1853 return ERROR_NT(ntstatus);
1856 dptr_num = dptr_dnum(conn->dirptr);
1857 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1859 /* We don't need to check for VOL here as this is returned by
1860 a different TRANS2 call. */
1862 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1863 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1864 dont_descend = True;
1866 p = pdata;
1867 space_remaining = max_data_bytes;
1868 out_of_space = False;
1870 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1871 BOOL got_exact_match = False;
1873 /* this is a heuristic to avoid seeking the dirptr except when
1874 absolutely necessary. It allows for a filename of about 40 chars */
1875 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1876 out_of_space = True;
1877 finished = False;
1878 } else {
1879 finished = !get_lanman2_dir_entry(conn,
1880 inbuf, outbuf,
1881 mask,dirtype,info_level,
1882 requires_resume_key,dont_descend,
1883 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1884 &last_entry_off, ea_list, ea_ctx);
1887 if (finished && out_of_space)
1888 finished = False;
1890 if (!finished && !out_of_space)
1891 numentries++;
1894 * As an optimisation if we know we aren't looking
1895 * for a wildcard name (ie. the name matches the wildcard exactly)
1896 * then we can finish on any (first) match.
1897 * This speeds up large directory searches. JRA.
1900 if(got_exact_match)
1901 finished = True;
1903 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1906 talloc_destroy(ea_ctx);
1908 /* Check if we can close the dirptr */
1909 if(close_after_first || (finished && close_if_end)) {
1910 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1911 dptr_close(&dptr_num);
1915 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1916 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1917 * the protocol level is less than NT1. Tested with smbclient. JRA.
1918 * This should fix the OS/2 client bug #2335.
1921 if(numentries == 0) {
1922 dptr_close(&dptr_num);
1923 if (Protocol < PROTOCOL_NT1) {
1924 return ERROR_DOS(ERRDOS,ERRnofiles);
1925 } else {
1926 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1930 /* At this point pdata points to numentries directory entries. */
1932 /* Set up the return parameter block */
1933 SSVAL(params,0,dptr_num);
1934 SSVAL(params,2,numentries);
1935 SSVAL(params,4,finished);
1936 SSVAL(params,6,0); /* Never an EA error */
1937 SSVAL(params,8,last_entry_off);
1939 send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1941 if ((! *directory) && dptr_path(dptr_num))
1942 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1944 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1945 smb_fn_name(CVAL(inbuf,smb_com)),
1946 mask, directory, dirtype, numentries ) );
1949 * Force a name mangle here to ensure that the
1950 * mask as an 8.3 name is top of the mangled cache.
1951 * The reasons for this are subtle. Don't remove
1952 * this code unless you know what you are doing
1953 * (see PR#13758). JRA.
1956 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1957 mangle_map(mask, True, True, conn->params);
1959 return(-1);
1962 /****************************************************************************
1963 Reply to a TRANS2_FINDNEXT.
1964 ****************************************************************************/
1966 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1967 char **pparams, int total_params, char **ppdata, int total_data,
1968 unsigned int max_data_bytes)
1970 /* We must be careful here that we don't return more than the
1971 allowed number of data bytes. If this means returning fewer than
1972 maxentries then so be it. We assume that the redirector has
1973 enough room for the fixed number of parameter bytes it has
1974 requested. */
1975 char *params = *pparams;
1976 char *pdata = *ppdata;
1977 int dptr_num;
1978 int maxentries;
1979 uint16 info_level;
1980 uint32 resume_key;
1981 uint16 findnext_flags;
1982 BOOL close_after_request;
1983 BOOL close_if_end;
1984 BOOL requires_resume_key;
1985 BOOL continue_bit;
1986 BOOL mask_contains_wcard = False;
1987 pstring resume_name;
1988 pstring mask;
1989 pstring directory;
1990 char *p;
1991 uint16 dirtype;
1992 int numentries = 0;
1993 int i, last_entry_off=0;
1994 BOOL finished = False;
1995 BOOL dont_descend = False;
1996 BOOL out_of_space = False;
1997 int space_remaining;
1998 TALLOC_CTX *ea_ctx = NULL;
1999 struct ea_list *ea_list = NULL;
2000 NTSTATUS ntstatus = NT_STATUS_OK;
2002 if (total_params < 13) {
2003 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2006 dptr_num = SVAL(params,0);
2007 maxentries = SVAL(params,2);
2008 info_level = SVAL(params,4);
2009 resume_key = IVAL(params,6);
2010 findnext_flags = SVAL(params,10);
2011 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2012 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2013 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2014 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2016 *mask = *directory = *resume_name = 0;
2018 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), resume_name,
2019 params+12, sizeof(resume_name),
2020 total_params - 12, STR_TERMINATE, &ntstatus,
2021 &mask_contains_wcard);
2022 if (!NT_STATUS_IS_OK(ntstatus)) {
2023 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2024 complain (it thinks we're asking for the directory above the shared
2025 path or an invalid name). Catch this as the resume name is only compared, never used in
2026 a file access. JRA. */
2027 srvstr_pull(inbuf, SVAL(inbuf,smb_flg2),
2028 resume_name, params+12,
2029 sizeof(resume_name), total_params - 12,
2030 STR_TERMINATE);
2032 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2033 return ERROR_NT(ntstatus);
2037 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2038 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2039 resume_key = %d resume name = %s continue=%d level = %d\n",
2040 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2041 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2043 if (!maxentries) {
2044 /* W2K3 seems to treat zero as 1. */
2045 maxentries = 1;
2048 switch (info_level) {
2049 case SMB_FIND_INFO_STANDARD:
2050 case SMB_FIND_EA_SIZE:
2051 case SMB_FIND_EA_LIST:
2052 case SMB_FIND_FILE_DIRECTORY_INFO:
2053 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2054 case SMB_FIND_FILE_NAMES_INFO:
2055 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2056 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2057 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2058 break;
2059 case SMB_FIND_FILE_UNIX:
2060 case SMB_FIND_FILE_UNIX_INFO2:
2061 if (!lp_unix_extensions()) {
2062 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2064 break;
2065 default:
2066 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2069 if (info_level == SMB_FIND_EA_LIST) {
2070 uint32 ea_size;
2072 if (total_data < 4) {
2073 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2076 ea_size = IVAL(pdata,0);
2077 if (ea_size != total_data) {
2078 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2079 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2080 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2083 if (!lp_ea_support(SNUM(conn))) {
2084 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2087 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2088 return ERROR_NT(NT_STATUS_NO_MEMORY);
2091 /* Pull out the list of names. */
2092 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2093 if (!ea_list) {
2094 talloc_destroy(ea_ctx);
2095 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2099 *ppdata = (char *)SMB_REALLOC(
2100 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2101 if(*ppdata == NULL) {
2102 talloc_destroy(ea_ctx);
2103 return ERROR_NT(NT_STATUS_NO_MEMORY);
2106 pdata = *ppdata;
2108 /* Realloc the params space */
2109 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2110 if(*pparams == NULL ) {
2111 talloc_destroy(ea_ctx);
2112 return ERROR_NT(NT_STATUS_NO_MEMORY);
2115 params = *pparams;
2117 /* Check that the dptr is valid */
2118 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2119 talloc_destroy(ea_ctx);
2120 return ERROR_DOS(ERRDOS,ERRnofiles);
2123 string_set(&conn->dirpath,dptr_path(dptr_num));
2125 /* Get the wildcard mask from the dptr */
2126 if((p = dptr_wcard(dptr_num))== NULL) {
2127 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2128 talloc_destroy(ea_ctx);
2129 return ERROR_DOS(ERRDOS,ERRnofiles);
2132 pstrcpy(mask, p);
2133 pstrcpy(directory,conn->dirpath);
2135 /* Get the attr mask from the dptr */
2136 dirtype = dptr_attr(dptr_num);
2138 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2139 dptr_num, mask, dirtype,
2140 (long)conn->dirptr,
2141 dptr_TellDir(conn->dirptr)));
2143 /* We don't need to check for VOL here as this is returned by
2144 a different TRANS2 call. */
2146 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2147 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2148 dont_descend = True;
2150 p = pdata;
2151 space_remaining = max_data_bytes;
2152 out_of_space = False;
2155 * Seek to the correct position. We no longer use the resume key but
2156 * depend on the last file name instead.
2159 if(*resume_name && !continue_bit) {
2160 SMB_STRUCT_STAT st;
2162 long current_pos = 0;
2164 * Remember, mangle_map is called by
2165 * get_lanman2_dir_entry(), so the resume name
2166 * could be mangled. Ensure we check the unmangled name.
2169 if (mangle_is_mangled(resume_name, conn->params)) {
2170 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2171 conn->params);
2175 * Fix for NT redirector problem triggered by resume key indexes
2176 * changing between directory scans. We now return a resume key of 0
2177 * and instead look for the filename to continue from (also given
2178 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2179 * findfirst/findnext (as is usual) then the directory pointer
2180 * should already be at the correct place.
2183 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2184 } /* end if resume_name && !continue_bit */
2186 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2187 BOOL got_exact_match = False;
2189 /* this is a heuristic to avoid seeking the dirptr except when
2190 absolutely necessary. It allows for a filename of about 40 chars */
2191 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2192 out_of_space = True;
2193 finished = False;
2194 } else {
2195 finished = !get_lanman2_dir_entry(conn,
2196 inbuf, outbuf,
2197 mask,dirtype,info_level,
2198 requires_resume_key,dont_descend,
2199 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2200 &last_entry_off, ea_list, ea_ctx);
2203 if (finished && out_of_space)
2204 finished = False;
2206 if (!finished && !out_of_space)
2207 numentries++;
2210 * As an optimisation if we know we aren't looking
2211 * for a wildcard name (ie. the name matches the wildcard exactly)
2212 * then we can finish on any (first) match.
2213 * This speeds up large directory searches. JRA.
2216 if(got_exact_match)
2217 finished = True;
2219 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2222 talloc_destroy(ea_ctx);
2224 /* Check if we can close the dirptr */
2225 if(close_after_request || (finished && close_if_end)) {
2226 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2227 dptr_close(&dptr_num); /* This frees up the saved mask */
2230 /* Set up the return parameter block */
2231 SSVAL(params,0,numentries);
2232 SSVAL(params,2,finished);
2233 SSVAL(params,4,0); /* Never an EA error */
2234 SSVAL(params,6,last_entry_off);
2236 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2238 if ((! *directory) && dptr_path(dptr_num))
2239 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2241 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2242 smb_fn_name(CVAL(inbuf,smb_com)),
2243 mask, directory, dirtype, numentries ) );
2245 return(-1);
2248 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2250 E_md4hash(lp_servicename(SNUM(conn)),objid);
2251 return objid;
2254 /****************************************************************************
2255 Reply to a TRANS2_QFSINFO (query filesystem info).
2256 ****************************************************************************/
2258 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2259 char **pparams, int total_params, char **ppdata, int total_data,
2260 unsigned int max_data_bytes)
2262 char *pdata;
2263 char *params = *pparams;
2264 uint16 info_level;
2265 int data_len, len;
2266 SMB_STRUCT_STAT st;
2267 const char *vname = volume_label(SNUM(conn));
2268 int snum = SNUM(conn);
2269 char *fstype = lp_fstype(SNUM(conn));
2270 int quota_flag = 0;
2272 if (total_params < 2) {
2273 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2276 info_level = SVAL(params,0);
2278 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2280 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2281 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2282 return ERROR_DOS(ERRSRV,ERRinvdevice);
2285 *ppdata = (char *)SMB_REALLOC(
2286 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2287 if (*ppdata == NULL ) {
2288 return ERROR_NT(NT_STATUS_NO_MEMORY);
2291 pdata = *ppdata;
2292 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2294 switch (info_level) {
2295 case SMB_INFO_ALLOCATION:
2297 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2298 data_len = 18;
2299 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2300 return(UNIXERROR(ERRHRD,ERRgeneral));
2303 block_size = lp_block_size(snum);
2304 if (bsize < block_size) {
2305 SMB_BIG_UINT factor = block_size/bsize;
2306 bsize = block_size;
2307 dsize /= factor;
2308 dfree /= factor;
2310 if (bsize > block_size) {
2311 SMB_BIG_UINT factor = bsize/block_size;
2312 bsize = block_size;
2313 dsize *= factor;
2314 dfree *= factor;
2316 bytes_per_sector = 512;
2317 sectors_per_unit = bsize/bytes_per_sector;
2319 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2320 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2321 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2323 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2324 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2325 SIVAL(pdata,l1_cUnit,dsize);
2326 SIVAL(pdata,l1_cUnitAvail,dfree);
2327 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2328 break;
2331 case SMB_INFO_VOLUME:
2332 /* Return volume name */
2334 * Add volume serial number - hash of a combination of
2335 * the called hostname and the service name.
2337 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2339 * Win2k3 and previous mess this up by sending a name length
2340 * one byte short. I believe only older clients (OS/2 Win9x) use
2341 * this call so try fixing this by adding a terminating null to
2342 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2344 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2345 SCVAL(pdata,l2_vol_cch,len);
2346 data_len = l2_vol_szVolLabel + len;
2347 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2348 (unsigned)st.st_ctime, len, vname));
2349 break;
2351 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2352 case SMB_FS_ATTRIBUTE_INFORMATION:
2355 #if defined(HAVE_SYS_QUOTAS)
2356 quota_flag = FILE_VOLUME_QUOTAS;
2357 #endif
2359 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2360 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2361 FILE_SUPPORTS_OBJECT_IDS|
2362 FILE_UNICODE_ON_DISK|
2363 quota_flag); /* FS ATTRIBUTES */
2365 SIVAL(pdata,4,255); /* Max filename component length */
2366 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2367 and will think we can't do long filenames */
2368 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2369 SIVAL(pdata,8,len);
2370 data_len = 12 + len;
2371 break;
2373 case SMB_QUERY_FS_LABEL_INFO:
2374 case SMB_FS_LABEL_INFORMATION:
2375 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2376 data_len = 4 + len;
2377 SIVAL(pdata,0,len);
2378 break;
2380 case SMB_QUERY_FS_VOLUME_INFO:
2381 case SMB_FS_VOLUME_INFORMATION:
2384 * Add volume serial number - hash of a combination of
2385 * the called hostname and the service name.
2387 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2388 (str_checksum(get_local_machine_name())<<16));
2390 /* Max label len is 32 characters. */
2391 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2392 SIVAL(pdata,12,len);
2393 data_len = 18+len;
2395 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2396 (int)strlen(vname),vname, lp_servicename(snum)));
2397 break;
2399 case SMB_QUERY_FS_SIZE_INFO:
2400 case SMB_FS_SIZE_INFORMATION:
2402 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2403 data_len = 24;
2404 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2405 return(UNIXERROR(ERRHRD,ERRgeneral));
2407 block_size = lp_block_size(snum);
2408 if (bsize < block_size) {
2409 SMB_BIG_UINT factor = block_size/bsize;
2410 bsize = block_size;
2411 dsize /= factor;
2412 dfree /= factor;
2414 if (bsize > block_size) {
2415 SMB_BIG_UINT factor = bsize/block_size;
2416 bsize = block_size;
2417 dsize *= factor;
2418 dfree *= factor;
2420 bytes_per_sector = 512;
2421 sectors_per_unit = bsize/bytes_per_sector;
2422 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2423 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2424 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2425 SBIG_UINT(pdata,0,dsize);
2426 SBIG_UINT(pdata,8,dfree);
2427 SIVAL(pdata,16,sectors_per_unit);
2428 SIVAL(pdata,20,bytes_per_sector);
2429 break;
2432 case SMB_FS_FULL_SIZE_INFORMATION:
2434 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2435 data_len = 32;
2436 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2437 return(UNIXERROR(ERRHRD,ERRgeneral));
2439 block_size = lp_block_size(snum);
2440 if (bsize < block_size) {
2441 SMB_BIG_UINT factor = block_size/bsize;
2442 bsize = block_size;
2443 dsize /= factor;
2444 dfree /= factor;
2446 if (bsize > block_size) {
2447 SMB_BIG_UINT factor = bsize/block_size;
2448 bsize = block_size;
2449 dsize *= factor;
2450 dfree *= factor;
2452 bytes_per_sector = 512;
2453 sectors_per_unit = bsize/bytes_per_sector;
2454 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2455 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2456 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2457 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2458 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2459 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2460 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2461 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2462 break;
2465 case SMB_QUERY_FS_DEVICE_INFO:
2466 case SMB_FS_DEVICE_INFORMATION:
2467 data_len = 8;
2468 SIVAL(pdata,0,0); /* dev type */
2469 SIVAL(pdata,4,0); /* characteristics */
2470 break;
2472 #ifdef HAVE_SYS_QUOTAS
2473 case SMB_FS_QUOTA_INFORMATION:
2475 * what we have to send --metze:
2477 * Unknown1: 24 NULL bytes
2478 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2479 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2480 * Quota Flags: 2 byte :
2481 * Unknown3: 6 NULL bytes
2483 * 48 bytes total
2485 * details for Quota Flags:
2487 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2488 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2489 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2490 * 0x0001 Enable Quotas: enable quota for this fs
2494 /* we need to fake up a fsp here,
2495 * because its not send in this call
2497 files_struct fsp;
2498 SMB_NTQUOTA_STRUCT quotas;
2500 ZERO_STRUCT(fsp);
2501 ZERO_STRUCT(quotas);
2503 fsp.conn = conn;
2504 fsp.fnum = -1;
2506 /* access check */
2507 if (current_user.ut.uid != 0) {
2508 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2509 lp_servicename(SNUM(conn)),conn->user));
2510 return ERROR_DOS(ERRDOS,ERRnoaccess);
2513 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2514 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2515 return ERROR_DOS(ERRSRV,ERRerror);
2518 data_len = 48;
2520 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2522 /* Unknown1 24 NULL bytes*/
2523 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2524 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2525 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2527 /* Default Soft Quota 8 bytes */
2528 SBIG_UINT(pdata,24,quotas.softlim);
2530 /* Default Hard Quota 8 bytes */
2531 SBIG_UINT(pdata,32,quotas.hardlim);
2533 /* Quota flag 2 bytes */
2534 SSVAL(pdata,40,quotas.qflags);
2536 /* Unknown3 6 NULL bytes */
2537 SSVAL(pdata,42,0);
2538 SIVAL(pdata,44,0);
2540 break;
2542 #endif /* HAVE_SYS_QUOTAS */
2543 case SMB_FS_OBJECTID_INFORMATION:
2545 unsigned char objid[16];
2546 memcpy(pdata,create_volume_objectid(conn, objid),16);
2547 data_len = 64;
2548 break;
2552 * Query the version and capabilities of the CIFS UNIX extensions
2553 * in use.
2556 case SMB_QUERY_CIFS_UNIX_INFO:
2557 if (!lp_unix_extensions()) {
2558 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2560 data_len = 12;
2561 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2562 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2563 /* We have POSIX ACLs, pathname and locking capability. */
2564 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2565 CIFS_UNIX_POSIX_ACLS_CAP|
2566 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2567 CIFS_UNIX_FCNTL_LOCKS_CAP|
2568 CIFS_UNIX_EXTATTR_CAP|
2569 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2570 /* Ensure we don't do this on signed or sealed data. */
2571 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2572 )));
2573 break;
2575 case SMB_QUERY_POSIX_FS_INFO:
2577 int rc;
2578 vfs_statvfs_struct svfs;
2580 if (!lp_unix_extensions()) {
2581 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2584 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2586 if (!rc) {
2587 data_len = 56;
2588 SIVAL(pdata,0,svfs.OptimalTransferSize);
2589 SIVAL(pdata,4,svfs.BlockSize);
2590 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2591 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2592 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2593 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2594 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2595 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2596 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2597 #ifdef EOPNOTSUPP
2598 } else if (rc == EOPNOTSUPP) {
2599 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2600 #endif /* EOPNOTSUPP */
2601 } else {
2602 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2603 return ERROR_DOS(ERRSRV,ERRerror);
2605 break;
2608 case SMB_QUERY_POSIX_WHOAMI:
2610 uint32_t flags = 0;
2611 uint32_t sid_bytes;
2612 int i;
2614 if (!lp_unix_extensions()) {
2615 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2618 if (max_data_bytes < 40) {
2619 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2622 /* We ARE guest if global_sid_Builtin_Guests is
2623 * in our list of SIDs.
2625 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2626 current_user.nt_user_token)) {
2627 flags |= SMB_WHOAMI_GUEST;
2630 /* We are NOT guest if global_sid_Authenticated_Users
2631 * is in our list of SIDs.
2633 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2634 current_user.nt_user_token)) {
2635 flags &= ~SMB_WHOAMI_GUEST;
2638 /* NOTE: 8 bytes for UID/GID, irrespective of native
2639 * platform size. This matches
2640 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2642 data_len = 4 /* flags */
2643 + 4 /* flag mask */
2644 + 8 /* uid */
2645 + 8 /* gid */
2646 + 4 /* ngroups */
2647 + 4 /* num_sids */
2648 + 4 /* SID bytes */
2649 + 4 /* pad/reserved */
2650 + (current_user.ut.ngroups * 8)
2651 /* groups list */
2652 + (current_user.nt_user_token->num_sids *
2653 SID_MAX_SIZE)
2654 /* SID list */;
2656 SIVAL(pdata, 0, flags);
2657 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2658 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2659 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2662 if (data_len >= max_data_bytes) {
2663 /* Potential overflow, skip the GIDs and SIDs. */
2665 SIVAL(pdata, 24, 0); /* num_groups */
2666 SIVAL(pdata, 28, 0); /* num_sids */
2667 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2668 SIVAL(pdata, 36, 0); /* reserved */
2670 data_len = 40;
2671 break;
2674 SIVAL(pdata, 24, current_user.ut.ngroups);
2675 SIVAL(pdata, 28,
2676 current_user.nt_user_token->num_sids);
2678 /* We walk the SID list twice, but this call is fairly
2679 * infrequent, and I don't expect that it's performance
2680 * sensitive -- jpeach
2682 for (i = 0, sid_bytes = 0;
2683 i < current_user.nt_user_token->num_sids; ++i) {
2684 sid_bytes +=
2685 sid_size(&current_user.nt_user_token->user_sids[i]);
2688 /* SID list byte count */
2689 SIVAL(pdata, 32, sid_bytes);
2691 /* 4 bytes pad/reserved - must be zero */
2692 SIVAL(pdata, 36, 0);
2693 data_len = 40;
2695 /* GID list */
2696 for (i = 0; i < current_user.ut.ngroups; ++i) {
2697 SBIG_UINT(pdata, data_len,
2698 (SMB_BIG_UINT)current_user.ut.groups[i]);
2699 data_len += 8;
2702 /* SID list */
2703 for (i = 0;
2704 i < current_user.nt_user_token->num_sids; ++i) {
2705 int sid_len =
2706 sid_size(&current_user.nt_user_token->user_sids[i]);
2708 sid_linearize(pdata + data_len, sid_len,
2709 &current_user.nt_user_token->user_sids[i]);
2710 data_len += sid_len;
2713 break;
2716 case SMB_MAC_QUERY_FS_INFO:
2718 * Thursby MAC extension... ONLY on NTFS filesystems
2719 * once we do streams then we don't need this
2721 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2722 data_len = 88;
2723 SIVAL(pdata,84,0x100); /* Don't support mac... */
2724 break;
2726 /* drop through */
2727 default:
2728 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2732 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2734 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2736 return -1;
2739 /****************************************************************************
2740 Reply to a TRANS2_SETFSINFO (set filesystem info).
2741 ****************************************************************************/
2743 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2744 char **pparams, int total_params, char **ppdata, int total_data,
2745 unsigned int max_data_bytes)
2747 char *pdata = *ppdata;
2748 char *params = *pparams;
2749 uint16 info_level;
2750 int outsize;
2752 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2754 /* */
2755 if (total_params < 4) {
2756 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2757 total_params));
2758 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2761 info_level = SVAL(params,2);
2763 switch(info_level) {
2764 case SMB_SET_CIFS_UNIX_INFO:
2766 uint16 client_unix_major;
2767 uint16 client_unix_minor;
2768 uint32 client_unix_cap_low;
2769 uint32 client_unix_cap_high;
2771 if (!lp_unix_extensions()) {
2772 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2775 /* There should be 12 bytes of capabilities set. */
2776 if (total_data < 8) {
2777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2779 client_unix_major = SVAL(pdata,0);
2780 client_unix_minor = SVAL(pdata,2);
2781 client_unix_cap_low = IVAL(pdata,4);
2782 client_unix_cap_high = IVAL(pdata,8);
2783 /* Just print these values for now. */
2784 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2785 cap_low = 0x%x, cap_high = 0x%x\n",
2786 (unsigned int)client_unix_major,
2787 (unsigned int)client_unix_minor,
2788 (unsigned int)client_unix_cap_low,
2789 (unsigned int)client_unix_cap_high ));
2791 /* Here is where we must switch to posix pathname processing... */
2792 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2793 lp_set_posix_pathnames();
2794 mangle_change_to_posix();
2797 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2798 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2799 /* Client that knows how to do posix locks,
2800 * but not posix open/mkdir operations. Set a
2801 * default type for read/write checks. */
2803 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2806 break;
2808 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2810 NTSTATUS status;
2811 size_t param_len = 0;
2812 size_t data_len = total_data;
2814 if (!lp_unix_extensions()) {
2815 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2818 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2820 status = srv_request_encryption_setup(conn,
2821 (unsigned char **)ppdata,
2822 &data_len,
2823 (unsigned char **)pparams,
2824 &param_len
2827 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2828 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2829 } else if (!NT_STATUS_IS_OK(status)) {
2830 return ERROR_NT(status);
2833 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2835 if (NT_STATUS_IS_OK(status)) {
2836 /* Server-side transport encryption is now *on*. */
2837 status = srv_encryption_start(conn);
2838 if (!NT_STATUS_IS_OK(status)) {
2839 exit_server_cleanly("Failure in setting up encrypted transport");
2842 return -1;
2844 case SMB_FS_QUOTA_INFORMATION:
2846 files_struct *fsp = NULL;
2847 SMB_NTQUOTA_STRUCT quotas;
2849 ZERO_STRUCT(quotas);
2851 /* access check */
2852 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2853 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2854 lp_servicename(SNUM(conn)),conn->user));
2855 return ERROR_DOS(ERRSRV,ERRaccess);
2858 /* note: normaly there're 48 bytes,
2859 * but we didn't use the last 6 bytes for now
2860 * --metze
2862 fsp = file_fsp(SVAL(params,0));
2863 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2864 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2865 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2868 if (total_data < 42) {
2869 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2870 total_data));
2871 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2874 /* unknown_1 24 NULL bytes in pdata*/
2876 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2877 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2878 #ifdef LARGE_SMB_OFF_T
2879 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2880 #else /* LARGE_SMB_OFF_T */
2881 if ((IVAL(pdata,28) != 0)&&
2882 ((quotas.softlim != 0xFFFFFFFF)||
2883 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2884 /* more than 32 bits? */
2885 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2887 #endif /* LARGE_SMB_OFF_T */
2889 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2890 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2891 #ifdef LARGE_SMB_OFF_T
2892 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2893 #else /* LARGE_SMB_OFF_T */
2894 if ((IVAL(pdata,36) != 0)&&
2895 ((quotas.hardlim != 0xFFFFFFFF)||
2896 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2897 /* more than 32 bits? */
2898 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2900 #endif /* LARGE_SMB_OFF_T */
2902 /* quota_flags 2 bytes **/
2903 quotas.qflags = SVAL(pdata,40);
2905 /* unknown_2 6 NULL bytes follow*/
2907 /* now set the quotas */
2908 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2909 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2910 return ERROR_DOS(ERRSRV,ERRerror);
2913 break;
2915 default:
2916 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2917 info_level));
2918 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2919 break;
2923 * sending this reply works fine,
2924 * but I'm not sure it's the same
2925 * like windows do...
2926 * --metze
2928 outsize = set_message(inbuf, outbuf,10,0,True);
2930 return outsize;
2933 #if defined(HAVE_POSIX_ACLS)
2934 /****************************************************************************
2935 Utility function to count the number of entries in a POSIX acl.
2936 ****************************************************************************/
2938 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2940 unsigned int ace_count = 0;
2941 int entry_id = SMB_ACL_FIRST_ENTRY;
2942 SMB_ACL_ENTRY_T entry;
2944 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2945 /* get_next... */
2946 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2947 entry_id = SMB_ACL_NEXT_ENTRY;
2949 ace_count++;
2951 return ace_count;
2954 /****************************************************************************
2955 Utility function to marshall a POSIX acl into wire format.
2956 ****************************************************************************/
2958 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2960 int entry_id = SMB_ACL_FIRST_ENTRY;
2961 SMB_ACL_ENTRY_T entry;
2963 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2964 SMB_ACL_TAG_T tagtype;
2965 SMB_ACL_PERMSET_T permset;
2966 unsigned char perms = 0;
2967 unsigned int own_grp;
2969 /* get_next... */
2970 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2971 entry_id = SMB_ACL_NEXT_ENTRY;
2974 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2975 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2976 return False;
2979 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2980 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2981 return False;
2984 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2985 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2986 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2988 SCVAL(pdata,1,perms);
2990 switch (tagtype) {
2991 case SMB_ACL_USER_OBJ:
2992 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2993 own_grp = (unsigned int)pst->st_uid;
2994 SIVAL(pdata,2,own_grp);
2995 SIVAL(pdata,6,0);
2996 break;
2997 case SMB_ACL_USER:
2999 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3000 if (!puid) {
3001 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3002 return False;
3004 own_grp = (unsigned int)*puid;
3005 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3006 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3007 SIVAL(pdata,2,own_grp);
3008 SIVAL(pdata,6,0);
3009 break;
3011 case SMB_ACL_GROUP_OBJ:
3012 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3013 own_grp = (unsigned int)pst->st_gid;
3014 SIVAL(pdata,2,own_grp);
3015 SIVAL(pdata,6,0);
3016 break;
3017 case SMB_ACL_GROUP:
3019 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3020 if (!pgid) {
3021 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3022 return False;
3024 own_grp = (unsigned int)*pgid;
3025 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3026 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3027 SIVAL(pdata,2,own_grp);
3028 SIVAL(pdata,6,0);
3029 break;
3031 case SMB_ACL_MASK:
3032 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3033 SIVAL(pdata,2,0xFFFFFFFF);
3034 SIVAL(pdata,6,0xFFFFFFFF);
3035 break;
3036 case SMB_ACL_OTHER:
3037 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3038 SIVAL(pdata,2,0xFFFFFFFF);
3039 SIVAL(pdata,6,0xFFFFFFFF);
3040 break;
3041 default:
3042 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3043 return False;
3045 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3048 return True;
3050 #endif
3052 /****************************************************************************
3053 Store the FILE_UNIX_BASIC info.
3054 ****************************************************************************/
3056 static char *store_file_unix_basic(connection_struct *conn,
3057 char *pdata,
3058 files_struct *fsp,
3059 const SMB_STRUCT_STAT *psbuf)
3061 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3062 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3064 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3065 pdata += 8;
3067 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3068 pdata += 8;
3070 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3071 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3072 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3073 pdata += 24;
3075 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3076 SIVAL(pdata,4,0);
3077 pdata += 8;
3079 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3080 SIVAL(pdata,4,0);
3081 pdata += 8;
3083 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3084 pdata += 4;
3086 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3087 SIVAL(pdata,4,0);
3088 pdata += 8;
3090 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3091 SIVAL(pdata,4,0);
3092 pdata += 8;
3094 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3095 pdata += 8;
3097 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3098 SIVAL(pdata,4,0);
3099 pdata += 8;
3101 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3102 SIVAL(pdata,4,0);
3103 pdata += 8;
3105 return pdata;
3108 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3109 * the chflags(2) (or equivalent) flags.
3111 * XXX: this really should be behind the VFS interface. To do this, we would
3112 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3113 * Each VFS module could then implement it's own mapping as appropriate for the
3114 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3116 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3117 info2_flags_map[] =
3119 #ifdef UF_NODUMP
3120 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3121 #endif
3123 #ifdef UF_IMMUTABLE
3124 { UF_IMMUTABLE, EXT_IMMUTABLE },
3125 #endif
3127 #ifdef UF_APPEND
3128 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3129 #endif
3131 #ifdef UF_HIDDEN
3132 { UF_HIDDEN, EXT_HIDDEN },
3133 #endif
3135 /* Do not remove. We need to guarantee that this array has at least one
3136 * entry to build on HP-UX.
3138 { 0, 0 }
3142 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3143 uint32 *smb_fflags, uint32 *smb_fmask)
3145 #ifdef HAVE_STAT_ST_FLAGS
3146 int i;
3148 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3149 *smb_fmask |= info2_flags_map[i].smb_fflag;
3150 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3151 *smb_fflags |= info2_flags_map[i].smb_fflag;
3154 #endif /* HAVE_STAT_ST_FLAGS */
3157 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3158 const uint32 smb_fflags,
3159 const uint32 smb_fmask,
3160 int *stat_fflags)
3162 #ifdef HAVE_STAT_ST_FLAGS
3163 uint32 max_fmask = 0;
3164 int i;
3166 *stat_fflags = psbuf->st_flags;
3168 /* For each flags requested in smb_fmask, check the state of the
3169 * corresponding flag in smb_fflags and set or clear the matching
3170 * stat flag.
3173 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3174 max_fmask |= info2_flags_map[i].smb_fflag;
3175 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3176 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3177 *stat_fflags |= info2_flags_map[i].stat_fflag;
3178 } else {
3179 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3184 /* If smb_fmask is asking to set any bits that are not supported by
3185 * our flag mappings, we should fail.
3187 if ((smb_fmask & max_fmask) != smb_fmask) {
3188 return False;
3191 return True;
3192 #else
3193 return False;
3194 #endif /* HAVE_STAT_ST_FLAGS */
3198 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3199 * of file flags and birth (create) time.
3201 static char *store_file_unix_basic_info2(connection_struct *conn,
3202 char *pdata,
3203 files_struct *fsp,
3204 const SMB_STRUCT_STAT *psbuf)
3206 uint32 file_flags = 0;
3207 uint32 flags_mask = 0;
3209 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3211 /* Create (birth) time 64 bit */
3212 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3213 pdata += 8;
3215 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3216 SIVAL(pdata, 0, file_flags); /* flags */
3217 SIVAL(pdata, 4, flags_mask); /* mask */
3218 pdata += 8;
3220 return pdata;
3223 /****************************************************************************
3224 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3225 ****************************************************************************/
3227 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3228 unsigned int tran_call,
3229 char **pparams, int total_params, char **ppdata, int total_data,
3230 unsigned int max_data_bytes)
3232 char *params = *pparams;
3233 char *pdata = *ppdata;
3234 unsigned int data_size = 0;
3235 unsigned int param_size = 2;
3236 uint16 info_level;
3237 smb_np_struct *p_pipe = NULL;
3239 if (!params) {
3240 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3243 if (total_params < 4) {
3244 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3247 p_pipe = get_rpc_pipe_p(params,0);
3248 if (p_pipe == NULL) {
3249 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3252 info_level = SVAL(params,2);
3254 *pparams = (char *)SMB_REALLOC(*pparams,2);
3255 if (*pparams == NULL) {
3256 return ERROR_NT(NT_STATUS_NO_MEMORY);
3258 params = *pparams;
3259 SSVAL(params,0,0);
3260 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3261 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3262 if (*ppdata == NULL ) {
3263 return ERROR_NT(NT_STATUS_NO_MEMORY);
3265 pdata = *ppdata;
3267 switch (info_level) {
3268 case SMB_FILE_STANDARD_INFORMATION:
3269 memset(pdata,24,0);
3270 SOFF_T(pdata,0,4096LL);
3271 SIVAL(pdata,16,1);
3272 SIVAL(pdata,20,1);
3273 data_size = 24;
3274 break;
3276 default:
3277 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3280 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3282 return(-1);
3285 /****************************************************************************
3286 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3287 file name or file id).
3288 ****************************************************************************/
3290 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3291 unsigned int tran_call,
3292 char **pparams, int total_params, char **ppdata, int total_data,
3293 unsigned int max_data_bytes)
3295 char *params = *pparams;
3296 char *pdata = *ppdata;
3297 uint16 info_level;
3298 int mode=0;
3299 int nlink;
3300 SMB_OFF_T file_size=0;
3301 SMB_BIG_UINT allocation_size=0;
3302 unsigned int data_size = 0;
3303 unsigned int param_size = 2;
3304 SMB_STRUCT_STAT sbuf;
3305 pstring fname, dos_fname;
3306 char *fullpathname;
3307 char *base_name;
3308 char *p;
3309 SMB_OFF_T pos = 0;
3310 BOOL delete_pending = False;
3311 int len;
3312 time_t create_time, mtime, atime;
3313 struct timespec create_time_ts, mtime_ts, atime_ts;
3314 files_struct *fsp = NULL;
3315 TALLOC_CTX *data_ctx = NULL;
3316 struct ea_list *ea_list = NULL;
3317 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3318 char *lock_data = NULL;
3320 if (!params)
3321 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3323 ZERO_STRUCT(sbuf);
3325 if (tran_call == TRANSACT2_QFILEINFO) {
3326 if (total_params < 4) {
3327 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3330 if (IS_IPC(conn)) {
3331 return call_trans2qpipeinfo(conn,
3332 inbuf,
3333 outbuf,
3334 length,
3335 bufsize,
3336 tran_call,
3337 pparams,
3338 total_params,
3339 ppdata,
3340 total_data,
3341 max_data_bytes);
3344 fsp = file_fsp(SVAL(params,0));
3345 info_level = SVAL(params,2);
3347 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3349 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3350 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3353 if(fsp && (fsp->fake_file_handle)) {
3355 * This is actually for the QUOTA_FAKE_FILE --metze
3358 pstrcpy(fname, fsp->fsp_name);
3359 /* We know this name is ok, it's already passed the checks. */
3361 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3363 * This is actually a QFILEINFO on a directory
3364 * handle (returned from an NT SMB). NT5.0 seems
3365 * to do this call. JRA.
3367 /* We know this name is ok, it's already passed the checks. */
3368 pstrcpy(fname, fsp->fsp_name);
3370 if (INFO_LEVEL_IS_UNIX(info_level)) {
3371 /* Always do lstat for UNIX calls. */
3372 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3373 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3374 return UNIXERROR(ERRDOS,ERRbadpath);
3376 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3377 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3378 return UNIXERROR(ERRDOS,ERRbadpath);
3381 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3382 } else {
3384 * Original code - this is an open file.
3386 CHECK_FSP(fsp,conn);
3388 pstrcpy(fname, fsp->fsp_name);
3389 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3390 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3391 return(UNIXERROR(ERRDOS,ERRbadfid));
3393 pos = fsp->fh->position_information;
3394 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3395 access_mask = fsp->access_mask;
3397 } else {
3398 NTSTATUS status = NT_STATUS_OK;
3400 /* qpathinfo */
3401 if (total_params < 7) {
3402 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3405 info_level = SVAL(params,0);
3407 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3409 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3410 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3413 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, &params[6],
3414 sizeof(fname), total_params - 6,
3415 STR_TERMINATE, &status);
3416 if (!NT_STATUS_IS_OK(status)) {
3417 return ERROR_NT(status);
3420 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3421 if (!NT_STATUS_IS_OK(status)) {
3422 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3423 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3425 return ERROR_NT(status);
3428 status = unix_convert(conn, fname, False, NULL, &sbuf);
3429 if (!NT_STATUS_IS_OK(status)) {
3430 return ERROR_NT(status);
3432 status = check_name(conn, fname);
3433 if (!NT_STATUS_IS_OK(status)) {
3434 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3435 return ERROR_NT(status);
3438 if (INFO_LEVEL_IS_UNIX(info_level)) {
3439 /* Always do lstat for UNIX calls. */
3440 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3441 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3442 return UNIXERROR(ERRDOS,ERRbadpath);
3444 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3445 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3446 return UNIXERROR(ERRDOS,ERRbadpath);
3449 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3450 if (delete_pending) {
3451 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3455 nlink = sbuf.st_nlink;
3457 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3458 /* NTFS does not seem to count ".." */
3459 nlink -= 1;
3462 if ((nlink > 0) && delete_pending) {
3463 nlink -= 1;
3466 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3467 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3470 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3471 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3473 p = strrchr_m(fname,'/');
3474 if (!p)
3475 base_name = fname;
3476 else
3477 base_name = p+1;
3479 mode = dos_mode(conn,fname,&sbuf);
3480 if (!mode)
3481 mode = FILE_ATTRIBUTE_NORMAL;
3483 fullpathname = fname;
3484 if (!(mode & aDIR))
3485 file_size = get_file_size(sbuf);
3487 /* Pull out any data sent here before we realloc. */
3488 switch (info_level) {
3489 case SMB_INFO_QUERY_EAS_FROM_LIST:
3491 /* Pull any EA list from the data portion. */
3492 uint32 ea_size;
3494 if (total_data < 4) {
3495 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3497 ea_size = IVAL(pdata,0);
3499 if (total_data > 0 && ea_size != total_data) {
3500 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3501 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3502 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3505 if (!lp_ea_support(SNUM(conn))) {
3506 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3509 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3510 return ERROR_NT(NT_STATUS_NO_MEMORY);
3513 /* Pull out the list of names. */
3514 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3515 if (!ea_list) {
3516 talloc_destroy(data_ctx);
3517 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3519 break;
3522 case SMB_QUERY_POSIX_LOCK:
3524 if (fsp == NULL || fsp->fh->fd == -1) {
3525 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3528 if (total_data != POSIX_LOCK_DATA_SIZE) {
3529 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3532 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3533 return ERROR_NT(NT_STATUS_NO_MEMORY);
3536 /* Copy the lock range data. */
3537 lock_data = (char *)TALLOC_MEMDUP(
3538 data_ctx, pdata, total_data);
3539 if (!lock_data) {
3540 talloc_destroy(data_ctx);
3541 return ERROR_NT(NT_STATUS_NO_MEMORY);
3544 default:
3545 break;
3548 *pparams = (char *)SMB_REALLOC(*pparams,2);
3549 if (*pparams == NULL) {
3550 talloc_destroy(data_ctx);
3551 return ERROR_NT(NT_STATUS_NO_MEMORY);
3553 params = *pparams;
3554 SSVAL(params,0,0);
3555 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3556 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3557 if (*ppdata == NULL ) {
3558 talloc_destroy(data_ctx);
3559 return ERROR_NT(NT_STATUS_NO_MEMORY);
3561 pdata = *ppdata;
3563 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3564 mtime_ts = get_mtimespec(&sbuf);
3565 atime_ts = get_atimespec(&sbuf);
3567 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3569 if (fsp) {
3570 if (!null_timespec(fsp->pending_modtime)) {
3571 /* the pending modtime overrides the current modtime */
3572 mtime_ts = fsp->pending_modtime;
3574 } else {
3575 /* Do we have this path open ? */
3576 files_struct *fsp1 = file_find_di_first(file_id_sbuf(&sbuf));
3577 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3578 /* the pending modtime overrides the current modtime */
3579 mtime_ts = fsp1->pending_modtime;
3581 if (fsp1 && fsp1->initial_allocation_size) {
3582 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3586 if (lp_dos_filetime_resolution(SNUM(conn))) {
3587 dos_filetime_timespec(&create_time_ts);
3588 dos_filetime_timespec(&mtime_ts);
3589 dos_filetime_timespec(&atime_ts);
3592 create_time = convert_timespec_to_time_t(create_time_ts);
3593 mtime = convert_timespec_to_time_t(mtime_ts);
3594 atime = convert_timespec_to_time_t(atime_ts);
3596 /* NT expects the name to be in an exact form of the *full*
3597 filename. See the trans2 torture test */
3598 if (strequal(base_name,".")) {
3599 pstrcpy(dos_fname, "\\");
3600 } else {
3601 pstr_sprintf(dos_fname, "\\%s", fname);
3602 string_replace(dos_fname, '/', '\\');
3605 switch (info_level) {
3606 case SMB_INFO_STANDARD:
3607 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3608 data_size = 22;
3609 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3610 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3611 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3612 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3613 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3614 SSVAL(pdata,l1_attrFile,mode);
3615 break;
3617 case SMB_INFO_QUERY_EA_SIZE:
3619 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3620 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3621 data_size = 26;
3622 srv_put_dos_date2(pdata,0,create_time);
3623 srv_put_dos_date2(pdata,4,atime);
3624 srv_put_dos_date2(pdata,8,mtime); /* write time */
3625 SIVAL(pdata,12,(uint32)file_size);
3626 SIVAL(pdata,16,(uint32)allocation_size);
3627 SSVAL(pdata,20,mode);
3628 SIVAL(pdata,22,ea_size);
3629 break;
3632 case SMB_INFO_IS_NAME_VALID:
3633 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3634 if (tran_call == TRANSACT2_QFILEINFO) {
3635 /* os/2 needs this ? really ?*/
3636 return ERROR_DOS(ERRDOS,ERRbadfunc);
3638 data_size = 0;
3639 param_size = 0;
3640 break;
3642 case SMB_INFO_QUERY_EAS_FROM_LIST:
3644 size_t total_ea_len = 0;
3645 struct ea_list *ea_file_list = NULL;
3647 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3649 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3650 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3652 if (!ea_list || (total_ea_len > data_size)) {
3653 talloc_destroy(data_ctx);
3654 data_size = 4;
3655 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3656 break;
3659 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3660 talloc_destroy(data_ctx);
3661 break;
3664 case SMB_INFO_QUERY_ALL_EAS:
3666 /* We have data_size bytes to put EA's into. */
3667 size_t total_ea_len = 0;
3669 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3671 data_ctx = talloc_init("ea_ctx");
3672 if (!data_ctx) {
3673 return ERROR_NT(NT_STATUS_NO_MEMORY);
3676 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3677 if (!ea_list || (total_ea_len > data_size)) {
3678 talloc_destroy(data_ctx);
3679 data_size = 4;
3680 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3681 break;
3684 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3685 talloc_destroy(data_ctx);
3686 break;
3689 case SMB_FILE_BASIC_INFORMATION:
3690 case SMB_QUERY_FILE_BASIC_INFO:
3692 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3693 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3694 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3695 } else {
3696 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3697 data_size = 40;
3698 SIVAL(pdata,36,0);
3700 put_long_date_timespec(pdata,create_time_ts);
3701 put_long_date_timespec(pdata+8,atime_ts);
3702 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3703 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3704 SIVAL(pdata,32,mode);
3706 DEBUG(5,("SMB_QFBI - "));
3707 DEBUG(5,("create: %s ", ctime(&create_time)));
3708 DEBUG(5,("access: %s ", ctime(&atime)));
3709 DEBUG(5,("write: %s ", ctime(&mtime)));
3710 DEBUG(5,("change: %s ", ctime(&mtime)));
3711 DEBUG(5,("mode: %x\n", mode));
3712 break;
3714 case SMB_FILE_STANDARD_INFORMATION:
3715 case SMB_QUERY_FILE_STANDARD_INFO:
3717 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3718 data_size = 24;
3719 SOFF_T(pdata,0,allocation_size);
3720 SOFF_T(pdata,8,file_size);
3721 SIVAL(pdata,16,nlink);
3722 SCVAL(pdata,20,delete_pending?1:0);
3723 SCVAL(pdata,21,(mode&aDIR)?1:0);
3724 SSVAL(pdata,22,0); /* Padding. */
3725 break;
3727 case SMB_FILE_EA_INFORMATION:
3728 case SMB_QUERY_FILE_EA_INFO:
3730 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3731 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3732 data_size = 4;
3733 SIVAL(pdata,0,ea_size);
3734 break;
3737 /* Get the 8.3 name - used if NT SMB was negotiated. */
3738 case SMB_QUERY_FILE_ALT_NAME_INFO:
3739 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3741 pstring short_name;
3743 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3744 pstrcpy(short_name,base_name);
3745 /* Mangle if not already 8.3 */
3746 if(!mangle_is_8_3(short_name, True, conn->params)) {
3747 mangle_map(short_name,True,True,conn->params);
3749 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3750 data_size = 4 + len;
3751 SIVAL(pdata,0,len);
3752 break;
3755 case SMB_QUERY_FILE_NAME_INFO:
3757 this must be *exactly* right for ACLs on mapped drives to work
3759 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3760 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3761 data_size = 4 + len;
3762 SIVAL(pdata,0,len);
3763 break;
3765 case SMB_FILE_ALLOCATION_INFORMATION:
3766 case SMB_QUERY_FILE_ALLOCATION_INFO:
3767 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3768 data_size = 8;
3769 SOFF_T(pdata,0,allocation_size);
3770 break;
3772 case SMB_FILE_END_OF_FILE_INFORMATION:
3773 case SMB_QUERY_FILE_END_OF_FILEINFO:
3774 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3775 data_size = 8;
3776 SOFF_T(pdata,0,file_size);
3777 break;
3779 case SMB_QUERY_FILE_ALL_INFO:
3780 case SMB_FILE_ALL_INFORMATION:
3782 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3783 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3784 put_long_date_timespec(pdata,create_time_ts);
3785 put_long_date_timespec(pdata+8,atime_ts);
3786 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3787 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3788 SIVAL(pdata,32,mode);
3789 SIVAL(pdata,36,0); /* padding. */
3790 pdata += 40;
3791 SOFF_T(pdata,0,allocation_size);
3792 SOFF_T(pdata,8,file_size);
3793 SIVAL(pdata,16,nlink);
3794 SCVAL(pdata,20,delete_pending);
3795 SCVAL(pdata,21,(mode&aDIR)?1:0);
3796 SSVAL(pdata,22,0);
3797 pdata += 24;
3798 SIVAL(pdata,0,ea_size);
3799 pdata += 4; /* EA info */
3800 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3801 SIVAL(pdata,0,len);
3802 pdata += 4 + len;
3803 data_size = PTR_DIFF(pdata,(*ppdata));
3804 break;
3806 case SMB_FILE_INTERNAL_INFORMATION:
3807 /* This should be an index number - looks like
3808 dev/ino to me :-)
3810 I think this causes us to fail the IFSKIT
3811 BasicFileInformationTest. -tpot */
3813 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3814 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3815 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3816 data_size = 8;
3817 break;
3819 case SMB_FILE_ACCESS_INFORMATION:
3820 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3821 SIVAL(pdata,0,access_mask);
3822 data_size = 4;
3823 break;
3825 case SMB_FILE_NAME_INFORMATION:
3826 /* Pathname with leading '\'. */
3828 size_t byte_len;
3829 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3830 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3831 SIVAL(pdata,0,byte_len);
3832 data_size = 4 + byte_len;
3833 break;
3836 case SMB_FILE_DISPOSITION_INFORMATION:
3837 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3838 data_size = 1;
3839 SCVAL(pdata,0,delete_pending);
3840 break;
3842 case SMB_FILE_POSITION_INFORMATION:
3843 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3844 data_size = 8;
3845 SOFF_T(pdata,0,pos);
3846 break;
3848 case SMB_FILE_MODE_INFORMATION:
3849 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3850 SIVAL(pdata,0,mode);
3851 data_size = 4;
3852 break;
3854 case SMB_FILE_ALIGNMENT_INFORMATION:
3855 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3856 SIVAL(pdata,0,0); /* No alignment needed. */
3857 data_size = 4;
3858 break;
3860 #if 0
3862 * NT4 server just returns "invalid query" to this - if we try to answer
3863 * it then NTws gets a BSOD! (tridge).
3864 * W2K seems to want this. JRA.
3866 case SMB_QUERY_FILE_STREAM_INFO:
3867 #endif
3868 case SMB_FILE_STREAM_INFORMATION:
3869 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3870 if (mode & aDIR) {
3871 data_size = 0;
3872 } else {
3873 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3874 SIVAL(pdata,0,0); /* ??? */
3875 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3876 SOFF_T(pdata,8,file_size);
3877 SOFF_T(pdata,16,allocation_size);
3878 data_size = 24 + byte_len;
3880 break;
3882 case SMB_QUERY_COMPRESSION_INFO:
3883 case SMB_FILE_COMPRESSION_INFORMATION:
3884 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3885 SOFF_T(pdata,0,file_size);
3886 SIVAL(pdata,8,0); /* ??? */
3887 SIVAL(pdata,12,0); /* ??? */
3888 data_size = 16;
3889 break;
3891 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3892 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3893 put_long_date_timespec(pdata,create_time_ts);
3894 put_long_date_timespec(pdata+8,atime_ts);
3895 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3896 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3897 SOFF_T(pdata,32,allocation_size);
3898 SOFF_T(pdata,40,file_size);
3899 SIVAL(pdata,48,mode);
3900 SIVAL(pdata,52,0); /* ??? */
3901 data_size = 56;
3902 break;
3904 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3905 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3906 SIVAL(pdata,0,mode);
3907 SIVAL(pdata,4,0);
3908 data_size = 8;
3909 break;
3912 * CIFS UNIX Extensions.
3915 case SMB_QUERY_FILE_UNIX_BASIC:
3917 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3918 data_size = PTR_DIFF(pdata,(*ppdata));
3921 int i;
3922 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3924 for (i=0; i<100; i++)
3925 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3926 DEBUG(4,("\n"));
3929 break;
3931 case SMB_QUERY_FILE_UNIX_INFO2:
3933 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3934 data_size = PTR_DIFF(pdata,(*ppdata));
3937 int i;
3938 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3940 for (i=0; i<100; i++)
3941 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3942 DEBUG(4,("\n"));
3945 break;
3947 case SMB_QUERY_FILE_UNIX_LINK:
3949 pstring buffer;
3951 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3952 #ifdef S_ISLNK
3953 if(!S_ISLNK(sbuf.st_mode))
3954 return(UNIXERROR(ERRSRV,ERRbadlink));
3955 #else
3956 return(UNIXERROR(ERRDOS,ERRbadlink));
3957 #endif
3958 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3959 if (len == -1)
3960 return(UNIXERROR(ERRDOS,ERRnoaccess));
3961 buffer[len] = 0;
3962 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3963 pdata += len;
3964 data_size = PTR_DIFF(pdata,(*ppdata));
3966 break;
3969 #if defined(HAVE_POSIX_ACLS)
3970 case SMB_QUERY_POSIX_ACL:
3972 SMB_ACL_T file_acl = NULL;
3973 SMB_ACL_T def_acl = NULL;
3974 uint16 num_file_acls = 0;
3975 uint16 num_def_acls = 0;
3977 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3978 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3979 } else {
3980 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3983 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3984 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3985 fname ));
3986 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3989 if (S_ISDIR(sbuf.st_mode)) {
3990 if (fsp && fsp->is_directory) {
3991 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3992 } else {
3993 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3995 def_acl = free_empty_sys_acl(conn, def_acl);
3998 num_file_acls = count_acl_entries(conn, file_acl);
3999 num_def_acls = count_acl_entries(conn, def_acl);
4001 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4002 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4003 data_size,
4004 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4005 SMB_POSIX_ACL_HEADER_SIZE) ));
4006 if (file_acl) {
4007 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4009 if (def_acl) {
4010 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4012 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4015 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4016 SSVAL(pdata,2,num_file_acls);
4017 SSVAL(pdata,4,num_def_acls);
4018 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4019 if (file_acl) {
4020 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4022 if (def_acl) {
4023 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4025 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4027 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4028 if (file_acl) {
4029 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4031 if (def_acl) {
4032 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4034 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4037 if (file_acl) {
4038 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4040 if (def_acl) {
4041 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4043 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4044 break;
4046 #endif
4049 case SMB_QUERY_POSIX_LOCK:
4051 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4052 SMB_BIG_UINT count;
4053 SMB_BIG_UINT offset;
4054 uint32 lock_pid;
4055 enum brl_type lock_type;
4057 if (total_data != POSIX_LOCK_DATA_SIZE) {
4058 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4061 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4062 case POSIX_LOCK_TYPE_READ:
4063 lock_type = READ_LOCK;
4064 break;
4065 case POSIX_LOCK_TYPE_WRITE:
4066 lock_type = WRITE_LOCK;
4067 break;
4068 case POSIX_LOCK_TYPE_UNLOCK:
4069 default:
4070 /* There's no point in asking for an unlock... */
4071 talloc_destroy(data_ctx);
4072 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4075 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4076 #if defined(HAVE_LONGLONG)
4077 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4078 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4079 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4080 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4081 #else /* HAVE_LONGLONG */
4082 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4083 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4084 #endif /* HAVE_LONGLONG */
4086 status = query_lock(fsp,
4087 &lock_pid,
4088 &count,
4089 &offset,
4090 &lock_type,
4091 POSIX_LOCK);
4093 if (ERROR_WAS_LOCK_DENIED(status)) {
4094 /* Here we need to report who has it locked... */
4095 data_size = POSIX_LOCK_DATA_SIZE;
4097 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4098 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4099 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4100 #if defined(HAVE_LONGLONG)
4101 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4102 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4103 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4104 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4105 #else /* HAVE_LONGLONG */
4106 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4107 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4108 #endif /* HAVE_LONGLONG */
4110 } else if (NT_STATUS_IS_OK(status)) {
4111 /* For success we just return a copy of what we sent
4112 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4113 data_size = POSIX_LOCK_DATA_SIZE;
4114 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4115 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4116 } else {
4117 return ERROR_NT(status);
4119 break;
4122 default:
4123 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4126 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4128 return(-1);
4131 /****************************************************************************
4132 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4133 code.
4134 ****************************************************************************/
4136 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4138 SMB_STRUCT_STAT sbuf1, sbuf2;
4139 pstring last_component_oldname;
4140 pstring last_component_newname;
4141 NTSTATUS status = NT_STATUS_OK;
4143 ZERO_STRUCT(sbuf1);
4144 ZERO_STRUCT(sbuf2);
4146 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4147 if (!NT_STATUS_IS_OK(status)) {
4148 return status;
4151 status = check_name(conn, oldname);
4152 if (!NT_STATUS_IS_OK(status)) {
4153 return status;
4156 /* source must already exist. */
4157 if (!VALID_STAT(sbuf1)) {
4158 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4161 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4162 if (!NT_STATUS_IS_OK(status)) {
4163 return status;
4166 status = check_name(conn, newname);
4167 if (!NT_STATUS_IS_OK(status)) {
4168 return status;
4171 /* Disallow if newname already exists. */
4172 if (VALID_STAT(sbuf2)) {
4173 return NT_STATUS_OBJECT_NAME_COLLISION;
4176 /* No links from a directory. */
4177 if (S_ISDIR(sbuf1.st_mode)) {
4178 return NT_STATUS_FILE_IS_A_DIRECTORY;
4181 /* Ensure this is within the share. */
4182 status = check_reduced_name(conn, oldname);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 return status;
4187 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4189 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4190 status = map_nt_error_from_unix(errno);
4191 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4192 nt_errstr(status), newname, oldname));
4195 return status;
4198 /****************************************************************************
4199 Deal with setting the time from any of the setfilepathinfo functions.
4200 ****************************************************************************/
4202 static NTSTATUS smb_set_file_time(connection_struct *conn,
4203 files_struct *fsp,
4204 const char *fname,
4205 const SMB_STRUCT_STAT *psbuf,
4206 struct timespec ts[2])
4208 uint32 action =
4209 FILE_NOTIFY_CHANGE_LAST_ACCESS
4210 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4213 if (!VALID_STAT(*psbuf)) {
4214 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4217 /* get some defaults (no modifications) if any info is zero or -1. */
4218 if (null_timespec(ts[0])) {
4219 ts[0] = get_atimespec(psbuf);
4220 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4223 if (null_timespec(ts[1])) {
4224 ts[1] = get_mtimespec(psbuf);
4225 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4228 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4229 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4232 * Try and set the times of this file if
4233 * they are different from the current values.
4237 struct timespec mts = get_mtimespec(psbuf);
4238 struct timespec ats = get_atimespec(psbuf);
4239 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4240 return NT_STATUS_OK;
4244 if(fsp != NULL) {
4246 * This was a setfileinfo on an open file.
4247 * NT does this a lot. We also need to
4248 * set the time here, as it can be read by
4249 * FindFirst/FindNext and with the patch for bug #2045
4250 * in smbd/fileio.c it ensures that this timestamp is
4251 * kept sticky even after a write. We save the request
4252 * away and will set it on file close and after a write. JRA.
4255 if (!null_timespec(ts[1])) {
4256 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4257 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4258 fsp_set_pending_modtime(fsp, ts[1]);
4262 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4264 if(file_ntimes(conn, fname, ts)!=0) {
4265 return map_nt_error_from_unix(errno);
4267 if (action != 0) {
4268 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4270 return NT_STATUS_OK;
4273 /****************************************************************************
4274 Deal with setting the dosmode from any of the setfilepathinfo functions.
4275 ****************************************************************************/
4277 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4278 const char *fname,
4279 SMB_STRUCT_STAT *psbuf,
4280 uint32 dosmode)
4282 if (!VALID_STAT(*psbuf)) {
4283 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4286 if (dosmode) {
4287 if (S_ISDIR(psbuf->st_mode)) {
4288 dosmode |= aDIR;
4289 } else {
4290 dosmode &= ~aDIR;
4294 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4296 /* check the mode isn't different, before changing it */
4297 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4299 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4300 fname, (unsigned int)dosmode ));
4302 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4303 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4304 fname, strerror(errno)));
4305 return map_nt_error_from_unix(errno);
4308 return NT_STATUS_OK;
4311 /****************************************************************************
4312 Deal with setting the size from any of the setfilepathinfo functions.
4313 ****************************************************************************/
4315 static NTSTATUS smb_set_file_size(connection_struct *conn,
4316 struct smb_request *req,
4317 files_struct *fsp,
4318 const char *fname,
4319 SMB_STRUCT_STAT *psbuf,
4320 SMB_OFF_T size)
4322 NTSTATUS status = NT_STATUS_OK;
4323 files_struct *new_fsp = NULL;
4325 if (!VALID_STAT(*psbuf)) {
4326 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4329 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4331 if (size == get_file_size(*psbuf)) {
4332 return NT_STATUS_OK;
4335 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4336 fname, (double)size ));
4338 if (fsp && fsp->fh->fd != -1) {
4339 /* Handle based call. */
4340 if (vfs_set_filelen(fsp, size) == -1) {
4341 return map_nt_error_from_unix(errno);
4343 return NT_STATUS_OK;
4346 status = open_file_ntcreate(conn, req, fname, psbuf,
4347 FILE_WRITE_DATA,
4348 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4349 FILE_OPEN,
4351 FILE_ATTRIBUTE_NORMAL,
4352 FORCE_OPLOCK_BREAK_TO_NONE,
4353 NULL, &new_fsp);
4355 if (!NT_STATUS_IS_OK(status)) {
4356 /* NB. We check for open_was_deferred in the caller. */
4357 return status;
4360 if (vfs_set_filelen(new_fsp, size) == -1) {
4361 status = map_nt_error_from_unix(errno);
4362 close_file(new_fsp,NORMAL_CLOSE);
4363 return status;
4366 close_file(new_fsp,NORMAL_CLOSE);
4367 return NT_STATUS_OK;
4370 /****************************************************************************
4371 Deal with SMB_INFO_SET_EA.
4372 ****************************************************************************/
4374 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4375 const char *pdata,
4376 int total_data,
4377 files_struct *fsp,
4378 const char *fname)
4380 struct ea_list *ea_list = NULL;
4381 TALLOC_CTX *ctx = NULL;
4382 NTSTATUS status = NT_STATUS_OK;
4384 if (total_data < 10) {
4386 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4387 length. They seem to have no effect. Bug #3212. JRA */
4389 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4390 /* We're done. We only get EA info in this call. */
4391 return NT_STATUS_OK;
4394 return NT_STATUS_INVALID_PARAMETER;
4397 if (IVAL(pdata,0) > total_data) {
4398 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4399 IVAL(pdata,0), (unsigned int)total_data));
4400 return NT_STATUS_INVALID_PARAMETER;
4403 ctx = talloc_init("SMB_INFO_SET_EA");
4404 if (!ctx) {
4405 return NT_STATUS_NO_MEMORY;
4407 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4408 if (!ea_list) {
4409 talloc_destroy(ctx);
4410 return NT_STATUS_INVALID_PARAMETER;
4412 status = set_ea(conn, fsp, fname, ea_list);
4413 talloc_destroy(ctx);
4415 return status;
4418 /****************************************************************************
4419 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4420 ****************************************************************************/
4422 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4423 const char *pdata,
4424 int total_data,
4425 files_struct *fsp,
4426 const char *fname,
4427 SMB_STRUCT_STAT *psbuf)
4429 NTSTATUS status = NT_STATUS_OK;
4430 BOOL delete_on_close;
4431 uint32 dosmode = 0;
4433 if (total_data < 1) {
4434 return NT_STATUS_INVALID_PARAMETER;
4437 if (fsp == NULL) {
4438 return NT_STATUS_INVALID_HANDLE;
4441 delete_on_close = (CVAL(pdata,0) ? True : False);
4442 dosmode = dos_mode(conn, fname, psbuf);
4444 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4445 "delete_on_close = %u\n",
4446 fsp->fsp_name,
4447 (unsigned int)dosmode,
4448 (unsigned int)delete_on_close ));
4450 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4452 if (!NT_STATUS_IS_OK(status)) {
4453 return status;
4456 /* The set is across all open files on this dev/inode pair. */
4457 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4458 return NT_STATUS_ACCESS_DENIED;
4460 return NT_STATUS_OK;
4463 /****************************************************************************
4464 Deal with SMB_FILE_POSITION_INFORMATION.
4465 ****************************************************************************/
4467 static NTSTATUS smb_file_position_information(connection_struct *conn,
4468 const char *pdata,
4469 int total_data,
4470 files_struct *fsp)
4472 SMB_BIG_UINT position_information;
4474 if (total_data < 8) {
4475 return NT_STATUS_INVALID_PARAMETER;
4478 if (fsp == NULL) {
4479 /* Ignore on pathname based set. */
4480 return NT_STATUS_OK;
4483 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4484 #ifdef LARGE_SMB_OFF_T
4485 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4486 #else /* LARGE_SMB_OFF_T */
4487 if (IVAL(pdata,4) != 0) {
4488 /* more than 32 bits? */
4489 return NT_STATUS_INVALID_PARAMETER;
4491 #endif /* LARGE_SMB_OFF_T */
4493 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4494 fsp->fsp_name, (double)position_information ));
4495 fsp->fh->position_information = position_information;
4496 return NT_STATUS_OK;
4499 /****************************************************************************
4500 Deal with SMB_FILE_MODE_INFORMATION.
4501 ****************************************************************************/
4503 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4504 const char *pdata,
4505 int total_data)
4507 uint32 mode;
4509 if (total_data < 4) {
4510 return NT_STATUS_INVALID_PARAMETER;
4512 mode = IVAL(pdata,0);
4513 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4514 return NT_STATUS_INVALID_PARAMETER;
4516 return NT_STATUS_OK;
4519 /****************************************************************************
4520 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4521 ****************************************************************************/
4523 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4524 char *inbuf,
4525 const char *pdata,
4526 int total_data,
4527 const char *fname)
4529 pstring link_target;
4530 const char *newname = fname;
4531 NTSTATUS status = NT_STATUS_OK;
4533 /* Set a symbolic link. */
4534 /* Don't allow this if follow links is false. */
4536 if (total_data == 0) {
4537 return NT_STATUS_INVALID_PARAMETER;
4540 if (!lp_symlinks(SNUM(conn))) {
4541 return NT_STATUS_ACCESS_DENIED;
4544 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
4545 sizeof(link_target), total_data, STR_TERMINATE);
4547 /* !widelinks forces the target path to be within the share. */
4548 /* This means we can interpret the target as a pathname. */
4549 if (!lp_widelinks(SNUM(conn))) {
4550 pstring rel_name;
4551 char *last_dirp = NULL;
4553 if (*link_target == '/') {
4554 /* No absolute paths allowed. */
4555 return NT_STATUS_ACCESS_DENIED;
4557 pstrcpy(rel_name, newname);
4558 last_dirp = strrchr_m(rel_name, '/');
4559 if (last_dirp) {
4560 last_dirp[1] = '\0';
4561 } else {
4562 pstrcpy(rel_name, "./");
4564 pstrcat(rel_name, link_target);
4566 status = check_name(conn, rel_name);
4567 if (!NT_STATUS_IS_OK(status)) {
4568 return status;
4572 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4573 newname, link_target ));
4575 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4576 return map_nt_error_from_unix(errno);
4579 return NT_STATUS_OK;
4582 /****************************************************************************
4583 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4584 ****************************************************************************/
4586 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4587 char *inbuf,
4588 char *outbuf,
4589 const char *pdata,
4590 int total_data,
4591 pstring fname)
4593 pstring oldname;
4594 NTSTATUS status = NT_STATUS_OK;
4596 /* Set a hard link. */
4597 if (total_data == 0) {
4598 return NT_STATUS_INVALID_PARAMETER;
4601 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
4602 sizeof(oldname), total_data, STR_TERMINATE, &status);
4603 if (!NT_STATUS_IS_OK(status)) {
4604 return status;
4607 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4608 if (!NT_STATUS_IS_OK(status)) {
4609 return status;
4612 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4613 fname, oldname));
4615 return hardlink_internals(conn, oldname, fname);
4618 /****************************************************************************
4619 Deal with SMB_FILE_RENAME_INFORMATION.
4620 ****************************************************************************/
4622 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4623 struct smb_request *req,
4624 char *inbuf,
4625 char *outbuf,
4626 const char *pdata,
4627 int total_data,
4628 files_struct *fsp,
4629 pstring fname)
4631 BOOL overwrite;
4632 uint32 root_fid;
4633 uint32 len;
4634 pstring newname;
4635 pstring base_name;
4636 BOOL dest_has_wcard = False;
4637 NTSTATUS status = NT_STATUS_OK;
4638 char *p;
4640 if (total_data < 13) {
4641 return NT_STATUS_INVALID_PARAMETER;
4644 overwrite = (CVAL(pdata,0) ? True : False);
4645 root_fid = IVAL(pdata,4);
4646 len = IVAL(pdata,8);
4648 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4649 return NT_STATUS_INVALID_PARAMETER;
4652 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
4653 sizeof(newname), len, 0, &status,
4654 &dest_has_wcard);
4655 if (!NT_STATUS_IS_OK(status)) {
4656 return status;
4659 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4660 if (!NT_STATUS_IS_OK(status)) {
4661 return status;
4664 /* Check the new name has no '/' characters. */
4665 if (strchr_m(newname, '/')) {
4666 return NT_STATUS_NOT_SUPPORTED;
4669 /* Create the base directory. */
4670 pstrcpy(base_name, fname);
4671 p = strrchr_m(base_name, '/');
4672 if (p) {
4673 p[1] = '\0';
4674 } else {
4675 pstrcpy(base_name, "./");
4677 /* Append the new name. */
4678 pstrcat(base_name, newname);
4680 if (fsp) {
4681 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4682 fsp->fnum, fsp->fsp_name, base_name ));
4683 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4684 } else {
4685 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4686 fname, newname ));
4687 status = rename_internals(conn, req, fname, base_name, 0,
4688 overwrite, False, dest_has_wcard);
4691 return status;
4694 /****************************************************************************
4695 Deal with SMB_SET_POSIX_ACL.
4696 ****************************************************************************/
4698 #if defined(HAVE_POSIX_ACLS)
4699 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4700 const char *pdata,
4701 int total_data,
4702 files_struct *fsp,
4703 const char *fname,
4704 SMB_STRUCT_STAT *psbuf)
4706 uint16 posix_acl_version;
4707 uint16 num_file_acls;
4708 uint16 num_def_acls;
4709 BOOL valid_file_acls = True;
4710 BOOL valid_def_acls = True;
4712 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4713 return NT_STATUS_INVALID_PARAMETER;
4715 posix_acl_version = SVAL(pdata,0);
4716 num_file_acls = SVAL(pdata,2);
4717 num_def_acls = SVAL(pdata,4);
4719 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4720 valid_file_acls = False;
4721 num_file_acls = 0;
4724 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4725 valid_def_acls = False;
4726 num_def_acls = 0;
4729 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4730 return NT_STATUS_INVALID_PARAMETER;
4733 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4734 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4735 return NT_STATUS_INVALID_PARAMETER;
4738 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4739 fname ? fname : fsp->fsp_name,
4740 (unsigned int)num_file_acls,
4741 (unsigned int)num_def_acls));
4743 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4744 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4745 return map_nt_error_from_unix(errno);
4748 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4749 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4750 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4751 return map_nt_error_from_unix(errno);
4753 return NT_STATUS_OK;
4755 #endif
4757 /****************************************************************************
4758 Deal with SMB_SET_POSIX_LOCK.
4759 ****************************************************************************/
4761 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4762 char *inbuf,
4763 int length,
4764 const char *pdata,
4765 int total_data,
4766 files_struct *fsp)
4768 SMB_BIG_UINT count;
4769 SMB_BIG_UINT offset;
4770 uint32 lock_pid;
4771 BOOL blocking_lock = False;
4772 enum brl_type lock_type;
4773 NTSTATUS status = NT_STATUS_OK;
4775 if (fsp == NULL || fsp->fh->fd == -1) {
4776 return NT_STATUS_INVALID_HANDLE;
4779 if (total_data != POSIX_LOCK_DATA_SIZE) {
4780 return NT_STATUS_INVALID_PARAMETER;
4783 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4784 case POSIX_LOCK_TYPE_READ:
4785 lock_type = READ_LOCK;
4786 break;
4787 case POSIX_LOCK_TYPE_WRITE:
4788 /* Return the right POSIX-mappable error code for files opened read-only. */
4789 if (!fsp->can_write) {
4790 return NT_STATUS_INVALID_HANDLE;
4792 lock_type = WRITE_LOCK;
4793 break;
4794 case POSIX_LOCK_TYPE_UNLOCK:
4795 lock_type = UNLOCK_LOCK;
4796 break;
4797 default:
4798 return NT_STATUS_INVALID_PARAMETER;
4801 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4802 blocking_lock = False;
4803 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4804 blocking_lock = True;
4805 } else {
4806 return NT_STATUS_INVALID_PARAMETER;
4809 if (!lp_blocking_locks(SNUM(conn))) {
4810 blocking_lock = False;
4813 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4814 #if defined(HAVE_LONGLONG)
4815 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4816 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4817 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4818 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4819 #else /* HAVE_LONGLONG */
4820 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4821 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4822 #endif /* HAVE_LONGLONG */
4824 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4825 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4826 fsp->fsp_name,
4827 (unsigned int)lock_type,
4828 (unsigned int)lock_pid,
4829 (double)count,
4830 (double)offset ));
4832 if (lock_type == UNLOCK_LOCK) {
4833 status = do_unlock(smbd_messaging_context(),
4834 fsp,
4835 lock_pid,
4836 count,
4837 offset,
4838 POSIX_LOCK);
4839 } else {
4840 uint32 block_smbpid;
4842 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4843 fsp,
4844 lock_pid,
4845 count,
4846 offset,
4847 lock_type,
4848 POSIX_LOCK,
4849 blocking_lock,
4850 &status,
4851 &block_smbpid);
4853 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4855 * A blocking lock was requested. Package up
4856 * this smb into a queued request and push it
4857 * onto the blocking lock queue.
4859 if(push_blocking_lock_request(br_lck,
4860 inbuf, length,
4861 fsp,
4862 -1, /* infinite timeout. */
4864 lock_pid,
4865 lock_type,
4866 POSIX_LOCK,
4867 offset,
4868 count,
4869 block_smbpid)) {
4870 TALLOC_FREE(br_lck);
4871 return status;
4874 TALLOC_FREE(br_lck);
4877 return status;
4880 /****************************************************************************
4881 Deal with SMB_INFO_STANDARD.
4882 ****************************************************************************/
4884 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4885 const char *pdata,
4886 int total_data,
4887 files_struct *fsp,
4888 const char *fname,
4889 const SMB_STRUCT_STAT *psbuf)
4891 struct timespec ts[2];
4893 if (total_data < 12) {
4894 return NT_STATUS_INVALID_PARAMETER;
4897 /* access time */
4898 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4899 /* write time */
4900 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4902 DEBUG(10,("smb_set_info_standard: file %s\n",
4903 fname ? fname : fsp->fsp_name ));
4905 return smb_set_file_time(conn,
4906 fsp,
4907 fname,
4908 psbuf,
4909 ts);
4912 /****************************************************************************
4913 Deal with SMB_SET_FILE_BASIC_INFO.
4914 ****************************************************************************/
4916 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4917 const char *pdata,
4918 int total_data,
4919 files_struct *fsp,
4920 const char *fname,
4921 SMB_STRUCT_STAT *psbuf)
4923 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4924 struct timespec write_time;
4925 struct timespec changed_time;
4926 uint32 dosmode = 0;
4927 struct timespec ts[2];
4928 NTSTATUS status = NT_STATUS_OK;
4930 if (total_data < 36) {
4931 return NT_STATUS_INVALID_PARAMETER;
4934 /* Set the attributes */
4935 dosmode = IVAL(pdata,32);
4936 status = smb_set_file_dosmode(conn,
4937 fname,
4938 psbuf,
4939 dosmode);
4940 if (!NT_STATUS_IS_OK(status)) {
4941 return status;
4944 /* Ignore create time at offset pdata. */
4946 /* access time */
4947 ts[0] = interpret_long_date(pdata+8);
4949 write_time = interpret_long_date(pdata+16);
4950 changed_time = interpret_long_date(pdata+24);
4952 /* mtime */
4953 ts[1] = timespec_min(&write_time, &changed_time);
4955 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4956 ts[1] = write_time;
4959 /* Prefer a defined time to an undefined one. */
4960 if (null_timespec(ts[1])) {
4961 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4964 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4965 fname ? fname : fsp->fsp_name ));
4967 return smb_set_file_time(conn,
4968 fsp,
4969 fname,
4970 psbuf,
4971 ts);
4974 /****************************************************************************
4975 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4976 ****************************************************************************/
4978 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4979 struct smb_request *req,
4980 const char *pdata,
4981 int total_data,
4982 files_struct *fsp,
4983 const char *fname,
4984 SMB_STRUCT_STAT *psbuf)
4986 SMB_BIG_UINT allocation_size = 0;
4987 NTSTATUS status = NT_STATUS_OK;
4988 files_struct *new_fsp = NULL;
4990 if (!VALID_STAT(*psbuf)) {
4991 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4994 if (total_data < 8) {
4995 return NT_STATUS_INVALID_PARAMETER;
4998 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4999 #ifdef LARGE_SMB_OFF_T
5000 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5001 #else /* LARGE_SMB_OFF_T */
5002 if (IVAL(pdata,4) != 0) {
5003 /* more than 32 bits? */
5004 return NT_STATUS_INVALID_PARAMETER;
5006 #endif /* LARGE_SMB_OFF_T */
5008 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5009 fname, (double)allocation_size ));
5011 if (allocation_size) {
5012 allocation_size = smb_roundup(conn, allocation_size);
5015 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5016 fname, (double)allocation_size ));
5018 if (fsp && fsp->fh->fd != -1) {
5019 /* Open file handle. */
5020 /* Only change if needed. */
5021 if (allocation_size != get_file_size(*psbuf)) {
5022 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5023 return map_nt_error_from_unix(errno);
5026 /* But always update the time. */
5027 if (null_timespec(fsp->pending_modtime)) {
5029 * This is equivalent to a write. Ensure it's seen immediately
5030 * if there are no pending writes.
5032 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5034 return NT_STATUS_OK;
5037 /* Pathname or stat or directory file. */
5039 status = open_file_ntcreate(conn, req, fname, psbuf,
5040 FILE_WRITE_DATA,
5041 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5042 FILE_OPEN,
5044 FILE_ATTRIBUTE_NORMAL,
5045 FORCE_OPLOCK_BREAK_TO_NONE,
5046 NULL, &new_fsp);
5048 if (!NT_STATUS_IS_OK(status)) {
5049 /* NB. We check for open_was_deferred in the caller. */
5050 return status;
5053 /* Only change if needed. */
5054 if (allocation_size != get_file_size(*psbuf)) {
5055 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5056 status = map_nt_error_from_unix(errno);
5057 close_file(new_fsp,NORMAL_CLOSE);
5058 return status;
5062 /* Changing the allocation size should set the last mod time. */
5063 /* Don't need to call set_filetime as this will be flushed on
5064 * close. */
5066 fsp_set_pending_modtime(new_fsp, timespec_current());
5068 close_file(new_fsp,NORMAL_CLOSE);
5069 return NT_STATUS_OK;
5072 /****************************************************************************
5073 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5074 ****************************************************************************/
5076 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5077 struct smb_request *req,
5078 const char *pdata,
5079 int total_data,
5080 files_struct *fsp,
5081 const char *fname,
5082 SMB_STRUCT_STAT *psbuf)
5084 SMB_OFF_T size;
5086 if (total_data < 8) {
5087 return NT_STATUS_INVALID_PARAMETER;
5090 size = IVAL(pdata,0);
5091 #ifdef LARGE_SMB_OFF_T
5092 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5093 #else /* LARGE_SMB_OFF_T */
5094 if (IVAL(pdata,4) != 0) {
5095 /* more than 32 bits? */
5096 return NT_STATUS_INVALID_PARAMETER;
5098 #endif /* LARGE_SMB_OFF_T */
5099 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5100 "file %s to %.0f\n", fname, (double)size ));
5102 return smb_set_file_size(conn, req,
5103 fsp,
5104 fname,
5105 psbuf,
5106 size);
5109 /****************************************************************************
5110 Allow a UNIX info mknod.
5111 ****************************************************************************/
5113 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5114 const char *pdata,
5115 int total_data,
5116 const char *fname,
5117 SMB_STRUCT_STAT *psbuf)
5119 uint32 file_type = IVAL(pdata,56);
5120 #if defined(HAVE_MAKEDEV)
5121 uint32 dev_major = IVAL(pdata,60);
5122 uint32 dev_minor = IVAL(pdata,68);
5123 #endif
5124 SMB_DEV_T dev = (SMB_DEV_T)0;
5125 uint32 raw_unixmode = IVAL(pdata,84);
5126 NTSTATUS status;
5127 mode_t unixmode;
5129 if (total_data < 100) {
5130 return NT_STATUS_INVALID_PARAMETER;
5133 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5134 if (!NT_STATUS_IS_OK(status)) {
5135 return status;
5138 #if defined(HAVE_MAKEDEV)
5139 dev = makedev(dev_major, dev_minor);
5140 #endif
5142 switch (file_type) {
5143 #if defined(S_IFIFO)
5144 case UNIX_TYPE_FIFO:
5145 unixmode |= S_IFIFO;
5146 break;
5147 #endif
5148 #if defined(S_IFSOCK)
5149 case UNIX_TYPE_SOCKET:
5150 unixmode |= S_IFSOCK;
5151 break;
5152 #endif
5153 #if defined(S_IFCHR)
5154 case UNIX_TYPE_CHARDEV:
5155 unixmode |= S_IFCHR;
5156 break;
5157 #endif
5158 #if defined(S_IFBLK)
5159 case UNIX_TYPE_BLKDEV:
5160 unixmode |= S_IFBLK;
5161 break;
5162 #endif
5163 default:
5164 return NT_STATUS_INVALID_PARAMETER;
5167 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5168 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5170 /* Ok - do the mknod. */
5171 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5172 return map_nt_error_from_unix(errno);
5175 /* If any of the other "set" calls fail we
5176 * don't want to end up with a half-constructed mknod.
5179 if (lp_inherit_perms(SNUM(conn))) {
5180 inherit_access_acl(
5181 conn, parent_dirname(fname),
5182 fname, unixmode);
5185 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5186 status = map_nt_error_from_unix(errno);
5187 SMB_VFS_UNLINK(conn,fname);
5188 return status;
5190 return NT_STATUS_OK;
5193 /****************************************************************************
5194 Deal with SMB_SET_FILE_UNIX_BASIC.
5195 ****************************************************************************/
5197 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5198 struct smb_request *req,
5199 const char *pdata,
5200 int total_data,
5201 files_struct *fsp,
5202 const char *fname,
5203 SMB_STRUCT_STAT *psbuf)
5205 struct timespec ts[2];
5206 uint32 raw_unixmode;
5207 mode_t unixmode;
5208 SMB_OFF_T size = 0;
5209 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5210 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5211 NTSTATUS status = NT_STATUS_OK;
5212 BOOL delete_on_fail = False;
5213 enum perm_type ptype;
5215 if (total_data < 100) {
5216 return NT_STATUS_INVALID_PARAMETER;
5219 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5220 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5221 size=IVAL(pdata,0); /* first 8 Bytes are size */
5222 #ifdef LARGE_SMB_OFF_T
5223 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5224 #else /* LARGE_SMB_OFF_T */
5225 if (IVAL(pdata,4) != 0) {
5226 /* more than 32 bits? */
5227 return NT_STATUS_INVALID_PARAMETER;
5229 #endif /* LARGE_SMB_OFF_T */
5232 ts[0] = interpret_long_date(pdata+24); /* access_time */
5233 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5234 set_owner = (uid_t)IVAL(pdata,40);
5235 set_grp = (gid_t)IVAL(pdata,48);
5236 raw_unixmode = IVAL(pdata,84);
5238 if (VALID_STAT(*psbuf)) {
5239 if (S_ISDIR(psbuf->st_mode)) {
5240 ptype = PERM_EXISTING_DIR;
5241 } else {
5242 ptype = PERM_EXISTING_FILE;
5244 } else {
5245 ptype = PERM_NEW_FILE;
5248 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5249 if (!NT_STATUS_IS_OK(status)) {
5250 return status;
5253 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5254 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5255 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5257 if (!VALID_STAT(*psbuf)) {
5259 * The only valid use of this is to create character and block
5260 * devices, and named pipes. This is deprecated (IMHO) and
5261 * a new info level should be used for mknod. JRA.
5264 status = smb_unix_mknod(conn,
5265 pdata,
5266 total_data,
5267 fname,
5268 psbuf);
5269 if (!NT_STATUS_IS_OK(status)) {
5270 return status;
5273 /* Ensure we don't try and change anything else. */
5274 raw_unixmode = SMB_MODE_NO_CHANGE;
5275 size = get_file_size(*psbuf);
5276 ts[0] = get_atimespec(psbuf);
5277 ts[1] = get_mtimespec(psbuf);
5279 * We continue here as we might want to change the
5280 * owner uid/gid.
5282 delete_on_fail = True;
5285 #if 1
5286 /* Horrible backwards compatibility hack as an old server bug
5287 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5288 * */
5290 if (!size) {
5291 size = get_file_size(*psbuf);
5293 #endif
5296 * Deal with the UNIX specific mode set.
5299 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5300 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5301 (unsigned int)unixmode, fname ));
5302 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5303 return map_nt_error_from_unix(errno);
5308 * Deal with the UNIX specific uid set.
5311 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5312 int ret;
5314 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5315 (unsigned int)set_owner, fname ));
5317 if (S_ISLNK(psbuf->st_mode)) {
5318 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5319 } else {
5320 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5323 if (ret != 0) {
5324 status = map_nt_error_from_unix(errno);
5325 if (delete_on_fail) {
5326 SMB_VFS_UNLINK(conn,fname);
5328 return status;
5333 * Deal with the UNIX specific gid set.
5336 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5337 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5338 (unsigned int)set_owner, fname ));
5339 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5340 status = map_nt_error_from_unix(errno);
5341 if (delete_on_fail) {
5342 SMB_VFS_UNLINK(conn,fname);
5344 return status;
5348 /* Deal with any size changes. */
5350 status = smb_set_file_size(conn, req,
5351 fsp,
5352 fname,
5353 psbuf,
5354 size);
5355 if (!NT_STATUS_IS_OK(status)) {
5356 return status;
5359 /* Deal with any time changes. */
5361 return smb_set_file_time(conn,
5362 fsp,
5363 fname,
5364 psbuf,
5365 ts);
5368 /****************************************************************************
5369 Deal with SMB_SET_FILE_UNIX_INFO2.
5370 ****************************************************************************/
5372 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5373 struct smb_request *req,
5374 const char *pdata,
5375 int total_data,
5376 files_struct *fsp,
5377 const char *fname,
5378 SMB_STRUCT_STAT *psbuf)
5380 NTSTATUS status;
5381 uint32 smb_fflags;
5382 uint32 smb_fmask;
5384 if (total_data < 116) {
5385 return NT_STATUS_INVALID_PARAMETER;
5388 /* Start by setting all the fields that are common between UNIX_BASIC
5389 * and UNIX_INFO2.
5391 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5392 fsp, fname, psbuf);
5393 if (!NT_STATUS_IS_OK(status)) {
5394 return status;
5397 smb_fflags = IVAL(pdata, 108);
5398 smb_fmask = IVAL(pdata, 112);
5400 /* NB: We should only attempt to alter the file flags if the client
5401 * sends a non-zero mask.
5403 if (smb_fmask != 0) {
5404 int stat_fflags = 0;
5406 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5407 &stat_fflags)) {
5408 /* Client asked to alter a flag we don't understand. */
5409 return NT_STATUS_INVALID_PARAMETER;
5412 if (fsp && fsp->fh->fd != -1) {
5413 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5414 return NT_STATUS_NOT_SUPPORTED;
5415 } else {
5416 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5417 return map_nt_error_from_unix(errno);
5422 /* XXX: need to add support for changing the create_time here. You
5423 * can do this for paths on Darwin with setattrlist(2). The right way
5424 * to hook this up is probably by extending the VFS utimes interface.
5427 return NT_STATUS_OK;
5430 /****************************************************************************
5431 Create a directory with POSIX semantics.
5432 ****************************************************************************/
5434 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5435 struct smb_request *req,
5436 char **ppdata,
5437 int total_data,
5438 const char *fname,
5439 SMB_STRUCT_STAT *psbuf,
5440 int *pdata_return_size)
5442 NTSTATUS status = NT_STATUS_OK;
5443 uint32 raw_unixmode = 0;
5444 uint32 mod_unixmode = 0;
5445 mode_t unixmode = (mode_t)0;
5446 files_struct *fsp = NULL;
5447 uint16 info_level_return = 0;
5448 int info;
5449 char *pdata = *ppdata;
5451 if (total_data < 18) {
5452 return NT_STATUS_INVALID_PARAMETER;
5455 raw_unixmode = IVAL(pdata,8);
5456 /* Next 4 bytes are not yet defined. */
5458 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5459 if (!NT_STATUS_IS_OK(status)) {
5460 return status;
5463 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5465 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5466 fname, (unsigned int)unixmode ));
5468 status = open_directory(conn, req,
5469 fname,
5470 psbuf,
5471 FILE_READ_ATTRIBUTES, /* Just a stat open */
5472 FILE_SHARE_NONE, /* Ignored for stat opens */
5473 FILE_CREATE,
5475 mod_unixmode,
5476 &info,
5477 &fsp);
5479 if (NT_STATUS_IS_OK(status)) {
5480 close_file(fsp, NORMAL_CLOSE);
5483 info_level_return = SVAL(pdata,16);
5485 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5486 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5487 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5488 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5489 } else {
5490 *pdata_return_size = 12;
5493 /* Realloc the data size */
5494 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5495 if (*ppdata == NULL) {
5496 *pdata_return_size = 0;
5497 return NT_STATUS_NO_MEMORY;
5499 pdata = *ppdata;
5501 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5502 SSVAL(pdata,2,0); /* No fnum. */
5503 SIVAL(pdata,4,info); /* Was directory created. */
5505 switch (info_level_return) {
5506 case SMB_QUERY_FILE_UNIX_BASIC:
5507 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5508 SSVAL(pdata,10,0); /* Padding. */
5509 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5510 break;
5511 case SMB_QUERY_FILE_UNIX_INFO2:
5512 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5513 SSVAL(pdata,10,0); /* Padding. */
5514 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5515 break;
5516 default:
5517 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5518 SSVAL(pdata,10,0); /* Padding. */
5519 break;
5522 return status;
5525 /****************************************************************************
5526 Open/Create a file with POSIX semantics.
5527 ****************************************************************************/
5529 static NTSTATUS smb_posix_open(connection_struct *conn,
5530 struct smb_request *req,
5531 char **ppdata,
5532 int total_data,
5533 const char *fname,
5534 SMB_STRUCT_STAT *psbuf,
5535 int *pdata_return_size)
5537 BOOL extended_oplock_granted = False;
5538 char *pdata = *ppdata;
5539 uint32 flags = 0;
5540 uint32 wire_open_mode = 0;
5541 uint32 raw_unixmode = 0;
5542 uint32 mod_unixmode = 0;
5543 uint32 create_disp = 0;
5544 uint32 access_mask = 0;
5545 uint32 create_options = 0;
5546 NTSTATUS status = NT_STATUS_OK;
5547 mode_t unixmode = (mode_t)0;
5548 files_struct *fsp = NULL;
5549 int oplock_request = 0;
5550 int info = 0;
5551 uint16 info_level_return = 0;
5553 if (total_data < 18) {
5554 return NT_STATUS_INVALID_PARAMETER;
5557 flags = IVAL(pdata,0);
5558 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5559 if (oplock_request) {
5560 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5563 wire_open_mode = IVAL(pdata,4);
5565 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5566 return smb_posix_mkdir(conn, req,
5567 ppdata,
5568 total_data,
5569 fname,
5570 psbuf,
5571 pdata_return_size);
5574 switch (wire_open_mode & SMB_ACCMODE) {
5575 case SMB_O_RDONLY:
5576 access_mask = FILE_READ_DATA;
5577 break;
5578 case SMB_O_WRONLY:
5579 access_mask = FILE_WRITE_DATA;
5580 break;
5581 case SMB_O_RDWR:
5582 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5583 break;
5584 default:
5585 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5586 (unsigned int)wire_open_mode ));
5587 return NT_STATUS_INVALID_PARAMETER;
5590 wire_open_mode &= ~SMB_ACCMODE;
5592 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5593 create_disp = FILE_CREATE;
5594 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5595 create_disp = FILE_OVERWRITE_IF;
5596 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5597 create_disp = FILE_OPEN_IF;
5598 } else {
5599 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5600 (unsigned int)wire_open_mode ));
5601 return NT_STATUS_INVALID_PARAMETER;
5604 raw_unixmode = IVAL(pdata,8);
5605 /* Next 4 bytes are not yet defined. */
5607 status = unix_perms_from_wire(conn,
5608 psbuf,
5609 raw_unixmode,
5610 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5611 &unixmode);
5613 if (!NT_STATUS_IS_OK(status)) {
5614 return status;
5617 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5619 if (wire_open_mode & SMB_O_SYNC) {
5620 create_options |= FILE_WRITE_THROUGH;
5622 if (wire_open_mode & SMB_O_APPEND) {
5623 access_mask |= FILE_APPEND_DATA;
5625 if (wire_open_mode & SMB_O_DIRECT) {
5626 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5629 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5630 fname,
5631 (unsigned int)wire_open_mode,
5632 (unsigned int)unixmode ));
5634 status = open_file_ntcreate(conn, req,
5635 fname,
5636 psbuf,
5637 access_mask,
5638 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5639 create_disp,
5640 0, /* no create options yet. */
5641 mod_unixmode,
5642 oplock_request,
5643 &info,
5644 &fsp);
5646 if (!NT_STATUS_IS_OK(status)) {
5647 return status;
5650 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5651 extended_oplock_granted = True;
5654 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5655 extended_oplock_granted = True;
5658 info_level_return = SVAL(pdata,16);
5660 /* Allocate the correct return size. */
5662 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5663 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5664 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5665 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5666 } else {
5667 *pdata_return_size = 12;
5670 /* Realloc the data size */
5671 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5672 if (*ppdata == NULL) {
5673 close_file(fsp,ERROR_CLOSE);
5674 *pdata_return_size = 0;
5675 return NT_STATUS_NO_MEMORY;
5677 pdata = *ppdata;
5679 if (extended_oplock_granted) {
5680 if (flags & REQUEST_BATCH_OPLOCK) {
5681 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5682 } else {
5683 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5685 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5686 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5687 } else {
5688 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5691 SSVAL(pdata,2,fsp->fnum);
5692 SIVAL(pdata,4,info); /* Was file created etc. */
5694 switch (info_level_return) {
5695 case SMB_QUERY_FILE_UNIX_BASIC:
5696 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5697 SSVAL(pdata,10,0); /* padding. */
5698 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5699 break;
5700 case SMB_QUERY_FILE_UNIX_INFO2:
5701 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5702 SSVAL(pdata,10,0); /* padding. */
5703 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5704 break;
5705 default:
5706 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5707 SSVAL(pdata,10,0); /* padding. */
5708 break;
5710 return NT_STATUS_OK;
5713 /****************************************************************************
5714 Delete a file with POSIX semantics.
5715 ****************************************************************************/
5717 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5718 struct smb_request *req,
5719 const char *pdata,
5720 int total_data,
5721 const char *fname,
5722 SMB_STRUCT_STAT *psbuf)
5724 NTSTATUS status = NT_STATUS_OK;
5725 files_struct *fsp = NULL;
5726 uint16 flags = 0;
5727 char del = 1;
5728 int info = 0;
5729 int i;
5730 struct share_mode_lock *lck = NULL;
5732 if (total_data < 2) {
5733 return NT_STATUS_INVALID_PARAMETER;
5736 flags = SVAL(pdata,0);
5738 if (!VALID_STAT(*psbuf)) {
5739 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5742 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5743 !VALID_STAT_OF_DIR(*psbuf)) {
5744 return NT_STATUS_NOT_A_DIRECTORY;
5747 DEBUG(10,("smb_posix_unlink: %s %s\n",
5748 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5749 fname));
5751 if (VALID_STAT_OF_DIR(*psbuf)) {
5752 status = open_directory(conn, req,
5753 fname,
5754 psbuf,
5755 DELETE_ACCESS,
5756 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5757 FILE_OPEN,
5759 FILE_FLAG_POSIX_SEMANTICS|0777,
5760 &info,
5761 &fsp);
5762 } else {
5764 status = open_file_ntcreate(conn, req,
5765 fname,
5766 psbuf,
5767 DELETE_ACCESS,
5768 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5769 FILE_OPEN,
5771 FILE_FLAG_POSIX_SEMANTICS|0777,
5772 0, /* No oplock, but break existing ones. */
5773 &info,
5774 &fsp);
5777 if (!NT_STATUS_IS_OK(status)) {
5778 return status;
5782 * Don't lie to client. If we can't really delete due to
5783 * non-POSIX opens return SHARING_VIOLATION.
5786 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5787 if (lck == NULL) {
5788 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5789 "lock for file %s\n", fsp->fsp_name));
5790 close_file(fsp, NORMAL_CLOSE);
5791 return NT_STATUS_INVALID_PARAMETER;
5795 * See if others still have the file open. If this is the case, then
5796 * don't delete. If all opens are POSIX delete we can set the delete
5797 * on close disposition.
5799 for (i=0; i<lck->num_share_modes; i++) {
5800 struct share_mode_entry *e = &lck->share_modes[i];
5801 if (is_valid_share_mode_entry(e)) {
5802 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5803 continue;
5805 /* Fail with sharing violation. */
5806 close_file(fsp, NORMAL_CLOSE);
5807 TALLOC_FREE(lck);
5808 return NT_STATUS_SHARING_VIOLATION;
5813 * Set the delete on close.
5815 status = smb_set_file_disposition_info(conn,
5816 &del,
5818 fsp,
5819 fname,
5820 psbuf);
5822 if (!NT_STATUS_IS_OK(status)) {
5823 close_file(fsp, NORMAL_CLOSE);
5824 TALLOC_FREE(lck);
5825 return status;
5827 TALLOC_FREE(lck);
5828 return close_file(fsp, NORMAL_CLOSE);
5831 /****************************************************************************
5832 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5833 ****************************************************************************/
5835 static int call_trans2setfilepathinfo(connection_struct *conn,
5836 struct smb_request *req,
5837 char *inbuf, char *outbuf, int length,
5838 int bufsize,
5839 unsigned int tran_call,
5840 char **pparams, int total_params, char **ppdata, int total_data,
5841 unsigned int max_data_bytes)
5843 char *params = *pparams;
5844 char *pdata = *ppdata;
5845 uint16 info_level;
5846 SMB_STRUCT_STAT sbuf;
5847 pstring fname;
5848 files_struct *fsp = NULL;
5849 NTSTATUS status = NT_STATUS_OK;
5850 int data_return_size = 0;
5852 if (!params) {
5853 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5856 ZERO_STRUCT(sbuf);
5858 if (tran_call == TRANSACT2_SETFILEINFO) {
5859 if (total_params < 4) {
5860 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5863 fsp = file_fsp(SVAL(params,0));
5864 info_level = SVAL(params,2);
5866 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5868 * This is actually a SETFILEINFO on a directory
5869 * handle (returned from an NT SMB). NT5.0 seems
5870 * to do this call. JRA.
5872 pstrcpy(fname, fsp->fsp_name);
5873 if (INFO_LEVEL_IS_UNIX(info_level)) {
5874 /* Always do lstat for UNIX calls. */
5875 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5876 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5877 return UNIXERROR(ERRDOS,ERRbadpath);
5879 } else {
5880 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5881 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5882 return UNIXERROR(ERRDOS,ERRbadpath);
5885 } else if (fsp && fsp->print_file) {
5887 * Doing a DELETE_ON_CLOSE should cancel a print job.
5889 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5890 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5892 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5894 SSVAL(params,0,0);
5895 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5896 return(-1);
5897 } else
5898 return (UNIXERROR(ERRDOS,ERRbadpath));
5899 } else {
5901 * Original code - this is an open file.
5903 CHECK_FSP(fsp,conn);
5905 pstrcpy(fname, fsp->fsp_name);
5907 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5908 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5909 return(UNIXERROR(ERRDOS,ERRbadfid));
5912 } else {
5913 /* set path info */
5914 if (total_params < 7) {
5915 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5918 info_level = SVAL(params,0);
5919 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, &params[6],
5920 sizeof(fname), total_params - 6, STR_TERMINATE,
5921 &status);
5922 if (!NT_STATUS_IS_OK(status)) {
5923 return ERROR_NT(status);
5926 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5927 if (!NT_STATUS_IS_OK(status)) {
5928 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5929 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5931 return ERROR_NT(status);
5934 status = unix_convert(conn, fname, False, NULL, &sbuf);
5935 if (!NT_STATUS_IS_OK(status)) {
5936 return ERROR_NT(status);
5939 status = check_name(conn, fname);
5940 if (!NT_STATUS_IS_OK(status)) {
5941 return ERROR_NT(status);
5944 if (INFO_LEVEL_IS_UNIX(info_level)) {
5946 * For CIFS UNIX extensions the target name may not exist.
5949 /* Always do lstat for UNIX calls. */
5950 SMB_VFS_LSTAT(conn,fname,&sbuf);
5952 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5953 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5954 return UNIXERROR(ERRDOS,ERRbadpath);
5958 if (!CAN_WRITE(conn)) {
5959 return ERROR_DOS(ERRSRV,ERRaccess);
5962 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5963 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5966 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5967 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5969 /* Realloc the parameter size */
5970 *pparams = (char *)SMB_REALLOC(*pparams,2);
5971 if (*pparams == NULL) {
5972 return ERROR_NT(NT_STATUS_NO_MEMORY);
5974 params = *pparams;
5976 SSVAL(params,0,0);
5978 if (fsp && !null_timespec(fsp->pending_modtime)) {
5979 /* the pending modtime overrides the current modtime */
5980 set_mtimespec(&sbuf, fsp->pending_modtime);
5983 switch (info_level) {
5985 case SMB_INFO_STANDARD:
5987 status = smb_set_info_standard(conn,
5988 pdata,
5989 total_data,
5990 fsp,
5991 fname,
5992 &sbuf);
5993 break;
5996 case SMB_INFO_SET_EA:
5998 status = smb_info_set_ea(conn,
5999 pdata,
6000 total_data,
6001 fsp,
6002 fname);
6003 break;
6006 case SMB_SET_FILE_BASIC_INFO:
6007 case SMB_FILE_BASIC_INFORMATION:
6009 status = smb_set_file_basic_info(conn,
6010 pdata,
6011 total_data,
6012 fsp,
6013 fname,
6014 &sbuf);
6015 break;
6018 case SMB_FILE_ALLOCATION_INFORMATION:
6019 case SMB_SET_FILE_ALLOCATION_INFO:
6021 status = smb_set_file_allocation_info(conn, req,
6022 pdata,
6023 total_data,
6024 fsp,
6025 fname,
6026 &sbuf);
6027 break;
6030 case SMB_FILE_END_OF_FILE_INFORMATION:
6031 case SMB_SET_FILE_END_OF_FILE_INFO:
6033 status = smb_set_file_end_of_file_info(conn, req,
6034 pdata,
6035 total_data,
6036 fsp,
6037 fname,
6038 &sbuf);
6039 break;
6042 case SMB_FILE_DISPOSITION_INFORMATION:
6043 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6045 #if 0
6046 /* JRA - We used to just ignore this on a path ?
6047 * Shouldn't this be invalid level on a pathname
6048 * based call ?
6050 if (tran_call != TRANSACT2_SETFILEINFO) {
6051 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6053 #endif
6054 status = smb_set_file_disposition_info(conn,
6055 pdata,
6056 total_data,
6057 fsp,
6058 fname,
6059 &sbuf);
6060 break;
6063 case SMB_FILE_POSITION_INFORMATION:
6065 status = smb_file_position_information(conn,
6066 pdata,
6067 total_data,
6068 fsp);
6069 break;
6072 /* From tridge Samba4 :
6073 * MODE_INFORMATION in setfileinfo (I have no
6074 * idea what "mode information" on a file is - it takes a value of 0,
6075 * 2, 4 or 6. What could it be?).
6078 case SMB_FILE_MODE_INFORMATION:
6080 status = smb_file_mode_information(conn,
6081 pdata,
6082 total_data);
6083 break;
6087 * CIFS UNIX extensions.
6090 case SMB_SET_FILE_UNIX_BASIC:
6092 status = smb_set_file_unix_basic(conn, req,
6093 pdata,
6094 total_data,
6095 fsp,
6096 fname,
6097 &sbuf);
6098 break;
6101 case SMB_SET_FILE_UNIX_INFO2:
6103 status = smb_set_file_unix_info2(conn, req,
6104 pdata,
6105 total_data,
6106 fsp,
6107 fname,
6108 &sbuf);
6109 break;
6112 case SMB_SET_FILE_UNIX_LINK:
6114 if (tran_call != TRANSACT2_SETPATHINFO) {
6115 /* We must have a pathname for this. */
6116 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6118 status = smb_set_file_unix_link(conn,
6119 inbuf,
6120 pdata,
6121 total_data,
6122 fname);
6123 break;
6126 case SMB_SET_FILE_UNIX_HLINK:
6128 if (tran_call != TRANSACT2_SETPATHINFO) {
6129 /* We must have a pathname for this. */
6130 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6132 status = smb_set_file_unix_hlink(conn,
6133 inbuf,
6134 outbuf,
6135 pdata,
6136 total_data,
6137 fname);
6138 break;
6141 case SMB_FILE_RENAME_INFORMATION:
6143 status = smb_file_rename_information(conn, req,
6144 inbuf,
6145 outbuf,
6146 pdata,
6147 total_data,
6148 fsp,
6149 fname);
6150 break;
6153 #if defined(HAVE_POSIX_ACLS)
6154 case SMB_SET_POSIX_ACL:
6156 status = smb_set_posix_acl(conn,
6157 pdata,
6158 total_data,
6159 fsp,
6160 fname,
6161 &sbuf);
6162 break;
6164 #endif
6166 case SMB_SET_POSIX_LOCK:
6168 if (tran_call != TRANSACT2_SETFILEINFO) {
6169 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6171 status = smb_set_posix_lock(conn,
6172 inbuf,
6173 length,
6174 pdata,
6175 total_data,
6176 fsp);
6177 break;
6180 case SMB_POSIX_PATH_OPEN:
6182 if (tran_call != TRANSACT2_SETPATHINFO) {
6183 /* We must have a pathname for this. */
6184 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6187 status = smb_posix_open(conn, req,
6188 ppdata,
6189 total_data,
6190 fname,
6191 &sbuf,
6192 &data_return_size);
6193 break;
6196 case SMB_POSIX_PATH_UNLINK:
6198 if (tran_call != TRANSACT2_SETPATHINFO) {
6199 /* We must have a pathname for this. */
6200 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6203 status = smb_posix_unlink(conn, req,
6204 pdata,
6205 total_data,
6206 fname,
6207 &sbuf);
6208 break;
6211 default:
6212 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6216 if (!NT_STATUS_IS_OK(status)) {
6217 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6218 /* We have re-scheduled this call. */
6219 return -1;
6221 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6222 /* We have re-scheduled this call. */
6223 return -1;
6225 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6226 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6228 return ERROR_NT(status);
6231 SSVAL(params,0,0);
6232 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6234 return -1;
6237 /****************************************************************************
6238 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6239 ****************************************************************************/
6241 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6242 char **pparams, int total_params, char **ppdata, int total_data,
6243 unsigned int max_data_bytes)
6245 char *params = *pparams;
6246 char *pdata = *ppdata;
6247 pstring directory;
6248 SMB_STRUCT_STAT sbuf;
6249 NTSTATUS status = NT_STATUS_OK;
6250 struct ea_list *ea_list = NULL;
6252 if (!CAN_WRITE(conn))
6253 return ERROR_DOS(ERRSRV,ERRaccess);
6255 if (total_params < 5) {
6256 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6259 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, &params[4],
6260 sizeof(directory), total_params - 4, STR_TERMINATE,
6261 &status);
6262 if (!NT_STATUS_IS_OK(status)) {
6263 return ERROR_NT(status);
6266 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6268 status = unix_convert(conn, directory, False, NULL, &sbuf);
6269 if (!NT_STATUS_IS_OK(status)) {
6270 return ERROR_NT(status);
6273 status = check_name(conn, directory);
6274 if (!NT_STATUS_IS_OK(status)) {
6275 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6276 return ERROR_NT(status);
6279 /* Any data in this call is an EA list. */
6280 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6281 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6285 * OS/2 workplace shell seems to send SET_EA requests of "null"
6286 * length (4 bytes containing IVAL 4).
6287 * They seem to have no effect. Bug #3212. JRA.
6290 if (total_data != 4) {
6291 if (total_data < 10) {
6292 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6295 if (IVAL(pdata,0) > total_data) {
6296 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6297 IVAL(pdata,0), (unsigned int)total_data));
6298 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6301 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6302 total_data - 4);
6303 if (!ea_list) {
6304 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6306 } else if (IVAL(pdata,0) != 4) {
6307 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6310 status = create_directory(conn, directory);
6312 if (!NT_STATUS_IS_OK(status)) {
6313 return ERROR_NT(status);
6316 /* Try and set any given EA. */
6317 if (ea_list) {
6318 status = set_ea(conn, NULL, directory, ea_list);
6319 if (!NT_STATUS_IS_OK(status)) {
6320 return ERROR_NT(status);
6324 /* Realloc the parameter and data sizes */
6325 *pparams = (char *)SMB_REALLOC(*pparams,2);
6326 if(*pparams == NULL) {
6327 return ERROR_NT(NT_STATUS_NO_MEMORY);
6329 params = *pparams;
6331 SSVAL(params,0,0);
6333 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6335 return(-1);
6338 /****************************************************************************
6339 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6340 We don't actually do this - we just send a null response.
6341 ****************************************************************************/
6343 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6344 char **pparams, int total_params, char **ppdata, int total_data,
6345 unsigned int max_data_bytes)
6347 static uint16 fnf_handle = 257;
6348 char *params = *pparams;
6349 uint16 info_level;
6351 if (total_params < 6) {
6352 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6355 info_level = SVAL(params,4);
6356 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6358 switch (info_level) {
6359 case 1:
6360 case 2:
6361 break;
6362 default:
6363 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6366 /* Realloc the parameter and data sizes */
6367 *pparams = (char *)SMB_REALLOC(*pparams,6);
6368 if (*pparams == NULL) {
6369 return ERROR_NT(NT_STATUS_NO_MEMORY);
6371 params = *pparams;
6373 SSVAL(params,0,fnf_handle);
6374 SSVAL(params,2,0); /* No changes */
6375 SSVAL(params,4,0); /* No EA errors */
6377 fnf_handle++;
6379 if(fnf_handle == 0)
6380 fnf_handle = 257;
6382 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6384 return(-1);
6387 /****************************************************************************
6388 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6389 changes). Currently this does nothing.
6390 ****************************************************************************/
6392 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6393 char **pparams, int total_params, char **ppdata, int total_data,
6394 unsigned int max_data_bytes)
6396 char *params = *pparams;
6398 DEBUG(3,("call_trans2findnotifynext\n"));
6400 /* Realloc the parameter and data sizes */
6401 *pparams = (char *)SMB_REALLOC(*pparams,4);
6402 if (*pparams == NULL) {
6403 return ERROR_NT(NT_STATUS_NO_MEMORY);
6405 params = *pparams;
6407 SSVAL(params,0,0); /* No changes */
6408 SSVAL(params,2,0); /* No EA errors */
6410 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6412 return(-1);
6415 /****************************************************************************
6416 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6417 ****************************************************************************/
6419 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6420 char **pparams, int total_params, char **ppdata, int total_data,
6421 unsigned int max_data_bytes)
6423 char *params = *pparams;
6424 pstring pathname;
6425 int reply_size = 0;
6426 int max_referral_level;
6427 NTSTATUS status = NT_STATUS_OK;
6429 DEBUG(10,("call_trans2getdfsreferral\n"));
6431 if (total_params < 3) {
6432 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6435 max_referral_level = SVAL(params,0);
6437 if(!lp_host_msdfs())
6438 return ERROR_DOS(ERRDOS,ERRbadfunc);
6440 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, &params[2],
6441 sizeof(pathname), total_params - 2, STR_TERMINATE);
6442 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6443 return ERROR_NT(status);
6445 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6446 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6448 return(-1);
6451 #define LMCAT_SPL 0x53
6452 #define LMFUNC_GETJOBID 0x60
6454 /****************************************************************************
6455 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6456 ****************************************************************************/
6458 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6459 char **pparams, int total_params, char **ppdata, int total_data,
6460 unsigned int max_data_bytes)
6462 char *pdata = *ppdata;
6463 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv15));
6465 /* check for an invalid fid before proceeding */
6467 if (!fsp)
6468 return(ERROR_DOS(ERRDOS,ERRbadfid));
6470 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6471 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6472 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6473 if (*ppdata == NULL) {
6474 return ERROR_NT(NT_STATUS_NO_MEMORY);
6476 pdata = *ppdata;
6478 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6479 CAN ACCEPT THIS IN UNICODE. JRA. */
6481 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6482 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6483 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6484 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6485 return(-1);
6486 } else {
6487 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6488 return ERROR_DOS(ERRSRV,ERRerror);
6492 /****************************************************************************
6493 Reply to a SMBfindclose (stop trans2 directory search).
6494 ****************************************************************************/
6496 int reply_findclose(connection_struct *conn,
6497 char *inbuf,char *outbuf,int length,int bufsize)
6499 int outsize = 0;
6500 int dptr_num=SVALS(inbuf,smb_vwv0);
6501 START_PROFILE(SMBfindclose);
6503 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6505 dptr_close(&dptr_num);
6507 outsize = set_message(inbuf, outbuf,0,0,False);
6509 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6511 END_PROFILE(SMBfindclose);
6512 return(outsize);
6515 /****************************************************************************
6516 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6517 ****************************************************************************/
6519 int reply_findnclose(connection_struct *conn,
6520 char *inbuf,char *outbuf,int length,int bufsize)
6522 int outsize = 0;
6523 int dptr_num= -1;
6524 START_PROFILE(SMBfindnclose);
6526 dptr_num = SVAL(inbuf,smb_vwv0);
6528 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6530 /* We never give out valid handles for a
6531 findnotifyfirst - so any dptr_num is ok here.
6532 Just ignore it. */
6534 outsize = set_message(inbuf, outbuf,0,0,False);
6536 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6538 END_PROFILE(SMBfindnclose);
6539 return(outsize);
6542 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6543 struct trans_state *state,
6544 char *inbuf, char *outbuf, int size, int bufsize)
6546 int outsize;
6548 if (Protocol >= PROTOCOL_NT1) {
6549 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6552 /* Now we must call the relevant TRANS2 function */
6553 switch(state->call) {
6554 case TRANSACT2_OPEN:
6556 START_PROFILE(Trans2_open);
6557 outsize = call_trans2open(
6558 conn, req, inbuf, outbuf, bufsize,
6559 &state->param, state->total_param,
6560 &state->data, state->total_data,
6561 state->max_data_return);
6562 END_PROFILE(Trans2_open);
6563 break;
6566 case TRANSACT2_FINDFIRST:
6568 START_PROFILE(Trans2_findfirst);
6569 outsize = call_trans2findfirst(
6570 conn, inbuf, outbuf, bufsize,
6571 &state->param, state->total_param,
6572 &state->data, state->total_data,
6573 state->max_data_return);
6574 END_PROFILE(Trans2_findfirst);
6575 break;
6578 case TRANSACT2_FINDNEXT:
6580 START_PROFILE(Trans2_findnext);
6581 outsize = call_trans2findnext(
6582 conn, inbuf, outbuf, size, bufsize,
6583 &state->param, state->total_param,
6584 &state->data, state->total_data,
6585 state->max_data_return);
6586 END_PROFILE(Trans2_findnext);
6587 break;
6590 case TRANSACT2_QFSINFO:
6592 START_PROFILE(Trans2_qfsinfo);
6593 outsize = call_trans2qfsinfo(
6594 conn, inbuf, outbuf, size, bufsize,
6595 &state->param, state->total_param,
6596 &state->data, state->total_data,
6597 state->max_data_return);
6598 END_PROFILE(Trans2_qfsinfo);
6599 break;
6602 case TRANSACT2_SETFSINFO:
6604 START_PROFILE(Trans2_setfsinfo);
6605 outsize = call_trans2setfsinfo(
6606 conn, inbuf, outbuf, size, bufsize,
6607 &state->param, state->total_param,
6608 &state->data, state->total_data,
6609 state->max_data_return);
6610 END_PROFILE(Trans2_setfsinfo);
6611 break;
6614 case TRANSACT2_QPATHINFO:
6615 case TRANSACT2_QFILEINFO:
6617 START_PROFILE(Trans2_qpathinfo);
6618 outsize = call_trans2qfilepathinfo(
6619 conn, inbuf, outbuf, size, bufsize, state->call,
6620 &state->param, state->total_param,
6621 &state->data, state->total_data,
6622 state->max_data_return);
6623 END_PROFILE(Trans2_qpathinfo);
6624 break;
6627 case TRANSACT2_SETPATHINFO:
6628 case TRANSACT2_SETFILEINFO:
6630 START_PROFILE(Trans2_setpathinfo);
6631 outsize = call_trans2setfilepathinfo(
6632 conn, req, inbuf, outbuf, size, bufsize, state->call,
6633 &state->param, state->total_param,
6634 &state->data, state->total_data,
6635 state->max_data_return);
6636 END_PROFILE(Trans2_setpathinfo);
6637 break;
6640 case TRANSACT2_FINDNOTIFYFIRST:
6642 START_PROFILE(Trans2_findnotifyfirst);
6643 outsize = call_trans2findnotifyfirst(
6644 conn, inbuf, outbuf, size, bufsize,
6645 &state->param, state->total_param,
6646 &state->data, state->total_data,
6647 state->max_data_return);
6648 END_PROFILE(Trans2_findnotifyfirst);
6649 break;
6652 case TRANSACT2_FINDNOTIFYNEXT:
6654 START_PROFILE(Trans2_findnotifynext);
6655 outsize = call_trans2findnotifynext(
6656 conn, inbuf, outbuf, size, bufsize,
6657 &state->param, state->total_param,
6658 &state->data, state->total_data,
6659 state->max_data_return);
6660 END_PROFILE(Trans2_findnotifynext);
6661 break;
6664 case TRANSACT2_MKDIR:
6666 START_PROFILE(Trans2_mkdir);
6667 outsize = call_trans2mkdir(
6668 conn, inbuf, outbuf, size, bufsize,
6669 &state->param, state->total_param,
6670 &state->data, state->total_data,
6671 state->max_data_return);
6672 END_PROFILE(Trans2_mkdir);
6673 break;
6676 case TRANSACT2_GET_DFS_REFERRAL:
6678 START_PROFILE(Trans2_get_dfs_referral);
6679 outsize = call_trans2getdfsreferral(
6680 conn, inbuf, outbuf, size, bufsize,
6681 &state->param, state->total_param,
6682 &state->data, state->total_data,
6683 state->max_data_return);
6684 END_PROFILE(Trans2_get_dfs_referral);
6685 break;
6688 case TRANSACT2_IOCTL:
6690 START_PROFILE(Trans2_ioctl);
6691 outsize = call_trans2ioctl(
6692 conn, inbuf, outbuf, size, bufsize,
6693 &state->param, state->total_param,
6694 &state->data, state->total_data,
6695 state->max_data_return);
6696 END_PROFILE(Trans2_ioctl);
6697 break;
6700 default:
6701 /* Error in request */
6702 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6703 outsize = ERROR_DOS(ERRSRV,ERRerror);
6706 return outsize;
6709 /****************************************************************************
6710 Reply to a SMBtrans2.
6711 ****************************************************************************/
6713 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6714 int size, int bufsize)
6716 int outsize = 0;
6717 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6718 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6719 unsigned int psoff = SVAL(inbuf, smb_psoff);
6720 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6721 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6722 struct trans_state *state;
6723 NTSTATUS result;
6725 START_PROFILE(SMBtrans2);
6727 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6728 if (!NT_STATUS_IS_OK(result)) {
6729 DEBUG(2, ("Got invalid trans2 request: %s\n",
6730 nt_errstr(result)));
6731 END_PROFILE(SMBtrans2);
6732 return ERROR_NT(result);
6735 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6736 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6737 && (tran_call != TRANSACT2_QFILEINFO)) {
6738 END_PROFILE(SMBtrans2);
6739 return ERROR_DOS(ERRSRV,ERRaccess);
6742 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6743 DEBUG(0, ("talloc failed\n"));
6744 END_PROFILE(SMBtrans2);
6745 return ERROR_NT(NT_STATUS_NO_MEMORY);
6748 state->cmd = SMBtrans2;
6750 state->mid = SVAL(inbuf, smb_mid);
6751 state->vuid = SVAL(inbuf, smb_uid);
6752 state->setup_count = SVAL(inbuf, smb_suwcnt);
6753 state->setup = NULL;
6754 state->total_param = SVAL(inbuf, smb_tpscnt);
6755 state->param = NULL;
6756 state->total_data = SVAL(inbuf, smb_tdscnt);
6757 state->data = NULL;
6758 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6759 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6760 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6761 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6762 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6764 state->call = tran_call;
6766 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6767 is so as a sanity check */
6768 if (state->setup_count != 1) {
6770 * Need to have rc=0 for ioctl to get job id for OS/2.
6771 * Network printing will fail if function is not successful.
6772 * Similar function in reply.c will be used if protocol
6773 * is LANMAN1.0 instead of LM1.2X002.
6774 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6775 * outbuf doesn't have to be set(only job id is used).
6777 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6778 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6779 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6780 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6781 } else {
6782 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6783 DEBUG(2,("Transaction is %d\n",tran_call));
6784 TALLOC_FREE(state);
6785 END_PROFILE(SMBtrans2);
6786 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6790 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6791 goto bad_param;
6793 if (state->total_data) {
6794 /* Can't use talloc here, the core routines do realloc on the
6795 * params and data. */
6796 state->data = (char *)SMB_MALLOC(state->total_data);
6797 if (state->data == NULL) {
6798 DEBUG(0,("reply_trans2: data malloc fail for %u "
6799 "bytes !\n", (unsigned int)state->total_data));
6800 TALLOC_FREE(state);
6801 END_PROFILE(SMBtrans2);
6802 return(ERROR_DOS(ERRDOS,ERRnomem));
6804 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6805 goto bad_param;
6806 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6807 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6808 goto bad_param;
6810 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6813 if (state->total_param) {
6814 /* Can't use talloc here, the core routines do realloc on the
6815 * params and data. */
6816 state->param = (char *)SMB_MALLOC(state->total_param);
6817 if (state->param == NULL) {
6818 DEBUG(0,("reply_trans: param malloc fail for %u "
6819 "bytes !\n", (unsigned int)state->total_param));
6820 SAFE_FREE(state->data);
6821 TALLOC_FREE(state);
6822 END_PROFILE(SMBtrans2);
6823 return(ERROR_DOS(ERRDOS,ERRnomem));
6825 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6826 goto bad_param;
6827 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6828 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6829 goto bad_param;
6831 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6834 state->received_data = dscnt;
6835 state->received_param = pscnt;
6837 if ((state->received_param == state->total_param) &&
6838 (state->received_data == state->total_data)) {
6840 struct smb_request req;
6841 init_smb_request(&req, (uint8 *)inbuf);
6843 outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
6844 size, bufsize);
6845 SAFE_FREE(state->data);
6846 SAFE_FREE(state->param);
6847 TALLOC_FREE(state);
6848 END_PROFILE(SMBtrans2);
6849 return outsize;
6852 DLIST_ADD(conn->pending_trans, state);
6854 /* We need to send an interim response then receive the rest
6855 of the parameter/data bytes */
6856 outsize = set_message(inbuf, outbuf,0,0,False);
6857 show_msg(outbuf);
6858 END_PROFILE(SMBtrans2);
6859 return outsize;
6861 bad_param:
6863 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6864 SAFE_FREE(state->data);
6865 SAFE_FREE(state->param);
6866 TALLOC_FREE(state);
6867 END_PROFILE(SMBtrans2);
6868 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6872 /****************************************************************************
6873 Reply to a SMBtranss2
6874 ****************************************************************************/
6876 int reply_transs2(connection_struct *conn,
6877 char *inbuf,char *outbuf,int size,int bufsize)
6879 int outsize = 0;
6880 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6881 struct trans_state *state;
6882 struct smb_request req;
6884 START_PROFILE(SMBtranss2);
6886 show_msg(inbuf);
6888 for (state = conn->pending_trans; state != NULL;
6889 state = state->next) {
6890 if (state->mid == SVAL(inbuf,smb_mid)) {
6891 break;
6895 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6896 END_PROFILE(SMBtranss2);
6897 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6900 /* Revise state->total_param and state->total_data in case they have
6901 changed downwards */
6903 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6904 state->total_param = SVAL(inbuf, smb_tpscnt);
6905 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6906 state->total_data = SVAL(inbuf, smb_tdscnt);
6908 pcnt = SVAL(inbuf, smb_spscnt);
6909 poff = SVAL(inbuf, smb_spsoff);
6910 pdisp = SVAL(inbuf, smb_spsdisp);
6912 dcnt = SVAL(inbuf, smb_sdscnt);
6913 doff = SVAL(inbuf, smb_sdsoff);
6914 ddisp = SVAL(inbuf, smb_sdsdisp);
6916 state->received_param += pcnt;
6917 state->received_data += dcnt;
6919 if ((state->received_data > state->total_data) ||
6920 (state->received_param > state->total_param))
6921 goto bad_param;
6923 if (pcnt) {
6924 if (pdisp+pcnt > state->total_param)
6925 goto bad_param;
6926 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6927 goto bad_param;
6928 if (pdisp > state->total_param)
6929 goto bad_param;
6930 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6931 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6932 goto bad_param;
6933 if (state->param + pdisp < state->param)
6934 goto bad_param;
6936 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6937 pcnt);
6940 if (dcnt) {
6941 if (ddisp+dcnt > state->total_data)
6942 goto bad_param;
6943 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6944 goto bad_param;
6945 if (ddisp > state->total_data)
6946 goto bad_param;
6947 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6948 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6949 goto bad_param;
6950 if (state->data + ddisp < state->data)
6951 goto bad_param;
6953 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6954 dcnt);
6957 if ((state->received_param < state->total_param) ||
6958 (state->received_data < state->total_data)) {
6959 END_PROFILE(SMBtranss2);
6960 return -1;
6963 /* construct_reply_common has done us the favor to pre-fill the
6964 * command field with SMBtranss2 which is wrong :-)
6966 SCVAL(outbuf,smb_com,SMBtrans2);
6968 init_smb_request(&req, (uint8 *)inbuf);
6970 outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
6971 bufsize);
6973 DLIST_REMOVE(conn->pending_trans, state);
6974 SAFE_FREE(state->data);
6975 SAFE_FREE(state->param);
6976 TALLOC_FREE(state);
6978 if (outsize == 0) {
6979 END_PROFILE(SMBtranss2);
6980 return(ERROR_DOS(ERRSRV,ERRnosupport));
6983 END_PROFILE(SMBtranss2);
6984 return(outsize);
6986 bad_param:
6988 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6989 DLIST_REMOVE(conn->pending_trans, state);
6990 SAFE_FREE(state->data);
6991 SAFE_FREE(state->param);
6992 TALLOC_FREE(state);
6993 END_PROFILE(SMBtranss2);
6994 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);