Mark some targets phony
[Samba.git] / source / smbd / trans2.c
blob1401a5b4c60deb32fce1ed4c54f06bd28e1726f8
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 2 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, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "includes.h"
29 extern int max_send;
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
38 static char *store_file_unix_basic(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
43 static char *store_file_unix_basic_info2(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 /********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51 ********************************************************************/
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
55 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
57 /* Only roundup for Windows clients. */
58 enum remote_arch_types ra_type = get_remote_arch();
59 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60 val = SMB_ROUNDUP(val,rval);
62 return val;
65 /********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
67 account sparse files.
68 ********************************************************************/
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 SMB_BIG_UINT ret;
74 if(S_ISDIR(sbuf->st_mode)) {
75 return 0;
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 #else
81 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 #endif
84 if (fsp && fsp->initial_allocation_size)
85 ret = MAX(ret,fsp->initial_allocation_size);
87 return smb_roundup(conn, ret);
90 /****************************************************************************
91 Utility functions for dealing with extended attributes.
92 ****************************************************************************/
94 static const char *prohibited_ea_names[] = {
95 SAMBA_POSIX_INHERITANCE_EA_NAME,
96 SAMBA_XATTR_DOS_ATTRIB,
97 NULL
100 /****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
106 int i;
108 for (i = 0; prohibited_ea_names[i]; i++) {
109 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 return True;
112 return False;
115 /****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120 const char *fname, char *ea_name, struct ea_struct *pea)
122 /* Get the value of this xattr. Max size is 64k. */
123 size_t attr_size = 256;
124 char *val = NULL;
125 ssize_t sizeret;
127 again:
129 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
130 if (!val) {
131 return False;
134 if (fsp && fsp->fh->fd != -1) {
135 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136 } else {
137 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
140 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
141 attr_size = 65536;
142 goto again;
145 if (sizeret == -1) {
146 return False;
149 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150 dump_data(10, val, sizeret);
152 pea->flags = 0;
153 if (strnequal(ea_name, "user.", 5)) {
154 pea->name = &ea_name[5];
155 } else {
156 pea->name = ea_name;
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
160 return True;
163 /****************************************************************************
164 Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168 const char *fname, size_t *pea_total_len)
170 /* Get a list of all xattrs. Max namesize is 64k. */
171 size_t ea_namelist_size = 1024;
172 char *ea_namelist;
173 char *p;
174 ssize_t sizeret;
175 int i;
176 struct ea_list *ea_list_head = NULL;
178 *pea_total_len = 0;
180 if (!lp_ea_support(SNUM(conn))) {
181 return NULL;
184 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
187 if (!ea_namelist) {
188 return NULL;
191 if (fsp && fsp->fh->fd != -1) {
192 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193 } else {
194 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
197 if (sizeret == -1 && errno == ERANGE) {
198 ea_namelist_size *= 2;
199 } else {
200 break;
204 if (sizeret == -1)
205 return NULL;
207 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
209 if (sizeret) {
210 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211 struct ea_list *listp;
213 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
214 continue;
216 listp = TALLOC_P(mem_ctx, struct ea_list);
217 if (!listp)
218 return NULL;
220 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
221 return NULL;
225 fstring dos_ea_name;
226 push_ascii_fstring(dos_ea_name, listp->ea.name);
227 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229 (unsigned int)*pea_total_len, dos_ea_name,
230 (unsigned int)listp->ea.value.length ));
232 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
234 /* Add on 4 for total length. */
235 if (*pea_total_len) {
236 *pea_total_len += 4;
240 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
241 return ea_list_head;
244 /****************************************************************************
245 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246 that was filled.
247 ****************************************************************************/
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250 connection_struct *conn, struct ea_list *ea_list)
252 unsigned int ret_data_size = 4;
253 char *p = pdata;
255 SMB_ASSERT(total_data_size >= 4);
257 if (!lp_ea_support(SNUM(conn))) {
258 SIVAL(pdata,4,0);
259 return 4;
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263 size_t dos_namelen;
264 fstring dos_ea_name;
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
268 break;
270 if (ea_list->ea.value.length > 65535) {
271 break;
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
274 break;
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290 SIVAL(pdata,0,ret_data_size);
291 return ret_data_size;
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
296 size_t total_ea_len = 0;
297 TALLOC_CTX *mem_ctx = NULL;
299 if (!lp_ea_support(SNUM(conn))) {
300 return 0;
302 mem_ctx = talloc_init("estimate_ea_size");
303 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304 talloc_destroy(mem_ctx);
305 return total_ea_len;
308 /****************************************************************************
309 Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
314 size_t total_ea_len;
315 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
318 for (; ea_list; ea_list = ea_list->next) {
319 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321 &unix_ea_name[5], ea_list->ea.name));
322 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
323 break;
326 talloc_destroy(mem_ctx);
329 /****************************************************************************
330 Set or delete an extended attribute.
331 ****************************************************************************/
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
335 if (!lp_ea_support(SNUM(conn))) {
336 return NT_STATUS_EAS_NOT_SUPPORTED;
339 for (;ea_list; ea_list = ea_list->next) {
340 int ret;
341 fstring unix_ea_name;
343 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344 fstrcat(unix_ea_name, ea_list->ea.name);
346 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
348 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
350 if (samba_private_attr_name(unix_ea_name)) {
351 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352 return NT_STATUS_ACCESS_DENIED;
355 if (ea_list->ea.value.length == 0) {
356 /* Remove the attribute. */
357 if (fsp && (fsp->fh->fd != -1)) {
358 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359 unix_ea_name, fsp->fsp_name));
360 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361 } else {
362 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363 unix_ea_name, fname));
364 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 #ifdef ENOATTR
367 /* Removing a non existent attribute always succeeds. */
368 if (ret == -1 && errno == ENOATTR) {
369 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
370 unix_ea_name));
371 ret = 0;
373 #endif
374 } else {
375 if (fsp && (fsp->fh->fd != -1)) {
376 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377 unix_ea_name, fsp->fsp_name));
378 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379 ea_list->ea.value.data, ea_list->ea.value.length, 0);
380 } else {
381 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382 unix_ea_name, fname));
383 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384 ea_list->ea.value.data, ea_list->ea.value.length, 0);
388 if (ret == -1) {
389 #ifdef ENOTSUP
390 if (errno == ENOTSUP) {
391 return NT_STATUS_EAS_NOT_SUPPORTED;
393 #endif
394 return map_nt_error_from_unix(errno);
398 return NT_STATUS_OK;
400 /****************************************************************************
401 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
406 struct ea_list *ea_list_head = NULL;
407 size_t offset = 0;
409 while (offset + 2 < data_size) {
410 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411 unsigned int namelen = CVAL(pdata,offset);
413 offset++; /* Go past the namelen byte. */
415 /* integer wrap paranioa. */
416 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417 (offset > data_size) || (namelen > data_size) ||
418 (offset + namelen >= data_size)) {
419 break;
421 /* Ensure the name is null terminated. */
422 if (pdata[offset + namelen] != '\0') {
423 return NULL;
425 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
426 if (!eal->ea.name) {
427 return NULL;
430 offset += (namelen + 1); /* Go past the name + terminating zero. */
431 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
435 return ea_list_head;
438 /****************************************************************************
439 Read one EA list entry from the buffer.
440 ****************************************************************************/
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
444 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 uint16 val_len;
446 unsigned int namelen;
448 if (!eal) {
449 return NULL;
452 if (data_size < 6) {
453 return NULL;
456 eal->ea.flags = CVAL(pdata,0);
457 namelen = CVAL(pdata,1);
458 val_len = SVAL(pdata,2);
460 if (4 + namelen + 1 + val_len > data_size) {
461 return NULL;
464 /* Ensure the name is null terminated. */
465 if (pdata[namelen + 4] != '\0') {
466 return NULL;
468 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
469 if (!eal->ea.name) {
470 return NULL;
473 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474 if (!eal->ea.value.data) {
475 return NULL;
478 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
480 /* Ensure we're null terminated just in case we print the value. */
481 eal->ea.value.data[val_len] = '\0';
482 /* But don't count the null. */
483 eal->ea.value.length--;
485 if (pbytes_used) {
486 *pbytes_used = 4 + namelen + 1 + val_len;
489 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
492 return eal;
495 /****************************************************************************
496 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
501 struct ea_list *ea_list_head = NULL;
502 size_t offset = 0;
503 size_t bytes_used = 0;
505 while (offset < data_size) {
506 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
508 if (!eal) {
509 return NULL;
512 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513 offset += bytes_used;
516 return ea_list_head;
519 /****************************************************************************
520 Count the total EA size needed.
521 ****************************************************************************/
523 static size_t ea_list_size(struct ea_list *ealist)
525 fstring dos_ea_name;
526 struct ea_list *listp;
527 size_t ret = 0;
529 for (listp = ealist; listp; listp = listp->next) {
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 /* Add on 4 for total length. */
534 if (ret) {
535 ret += 4;
538 return ret;
541 /****************************************************************************
542 Return a union of EA's from a file list and a list of names.
543 The TALLOC context for the two lists *MUST* be identical as we steal
544 memory from one list to add to another. JRA.
545 ****************************************************************************/
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
549 struct ea_list *nlistp, *flistp;
551 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552 for (flistp = file_list; flistp; flistp = flistp->next) {
553 if (strequal(nlistp->ea.name, flistp->ea.name)) {
554 break;
558 if (flistp) {
559 /* Copy the data from this entry. */
560 nlistp->ea.flags = flistp->ea.flags;
561 nlistp->ea.value = flistp->ea.value;
562 } else {
563 /* Null entry. */
564 nlistp->ea.flags = 0;
565 ZERO_STRUCT(nlistp->ea.value);
569 *total_ea_len = ea_list_size(name_list);
570 return name_list;
573 /****************************************************************************
574 Send the required number of replies back.
575 We assume all fields other than the data fields are
576 set correctly for the type of call.
577 HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
580 int send_trans2_replies(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(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(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, char *inbuf, char *outbuf, int bufsize,
743 char **pparams, int total_params, char **ppdata, int total_data,
744 unsigned int max_data_bytes)
746 char *params = *pparams;
747 char *pdata = *ppdata;
748 int deny_mode;
749 int32 open_attr;
750 BOOL oplock_request;
751 #if 0
752 BOOL return_additional_info;
753 int16 open_sattr;
754 time_t open_time;
755 #endif
756 int open_ofun;
757 uint32 open_size;
758 char *pname;
759 pstring fname;
760 SMB_OFF_T size=0;
761 int fattr=0,mtime=0;
762 SMB_INO_T inode = 0;
763 SMB_STRUCT_STAT sbuf;
764 int smb_action = 0;
765 files_struct *fsp;
766 struct ea_list *ea_list = NULL;
767 uint16 flags = 0;
768 NTSTATUS status;
769 uint32 access_mask;
770 uint32 share_mode;
771 uint32 create_disposition;
772 uint32 create_options = 0;
775 * Ensure we have enough parameters to perform the operation.
778 if (total_params < 29) {
779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
782 flags = SVAL(params, 0);
783 deny_mode = SVAL(params, 2);
784 open_attr = SVAL(params,6);
785 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
786 if (oplock_request) {
787 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
790 #if 0
791 return_additional_info = BITSETW(params,0);
792 open_sattr = SVAL(params, 4);
793 open_time = make_unix_date3(params+8);
794 #endif
795 open_ofun = SVAL(params,12);
796 open_size = IVAL(params,14);
797 pname = &params[28];
799 if (IS_IPC(conn)) {
800 return(ERROR_DOS(ERRSRV,ERRaccess));
803 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
809 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
810 (unsigned int)open_ofun, open_size));
812 /* XXXX we need to handle passed times, sattr and flags */
814 status = unix_convert(conn, fname, False, NULL, &sbuf);
815 if (!NT_STATUS_IS_OK(status)) {
816 return ERROR_NT(status);
819 status = check_name(conn, fname);
820 if (!NT_STATUS_IS_OK(status)) {
821 return ERROR_NT(status);
824 if (open_ofun == 0) {
825 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
828 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
829 &access_mask,
830 &share_mode,
831 &create_disposition,
832 &create_options)) {
833 return ERROR_DOS(ERRDOS, ERRbadaccess);
836 /* Any data in this call is an EA list. */
837 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
838 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
841 if (total_data != 4) {
842 if (total_data < 10) {
843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 if (IVAL(pdata,0) > total_data) {
847 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
848 IVAL(pdata,0), (unsigned int)total_data));
849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
852 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
853 total_data - 4);
854 if (!ea_list) {
855 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
857 } else if (IVAL(pdata,0) != 4) {
858 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
861 status = open_file_ntcreate(conn,fname,&sbuf,
862 access_mask,
863 share_mode,
864 create_disposition,
865 create_options,
866 open_attr,
867 oplock_request,
868 &smb_action, &fsp);
870 if (!NT_STATUS_IS_OK(status)) {
871 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
872 /* We have re-scheduled this call. */
873 return -1;
875 return ERROR_OPEN(status);
878 size = get_file_size(sbuf);
879 fattr = dos_mode(conn,fname,&sbuf);
880 mtime = sbuf.st_mtime;
881 inode = sbuf.st_ino;
882 if (fattr & aDIR) {
883 close_file(fsp,ERROR_CLOSE);
884 return(ERROR_DOS(ERRDOS,ERRnoaccess));
887 /* Save the requested allocation size. */
888 /* Allocate space for the file if a size hint is supplied */
889 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
890 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
891 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
892 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
893 if (fsp->is_directory) {
894 close_file(fsp,ERROR_CLOSE);
895 /* Can't set allocation size on a directory. */
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
898 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
899 close_file(fsp,ERROR_CLOSE);
900 return ERROR_NT(NT_STATUS_DISK_FULL);
903 /* Adjust size here to return the right size in the reply.
904 Windows does it this way. */
905 size = fsp->initial_allocation_size;
906 } else {
907 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
911 if (ea_list && smb_action == FILE_WAS_CREATED) {
912 status = set_ea(conn, fsp, fname, ea_list);
913 if (!NT_STATUS_IS_OK(status)) {
914 close_file(fsp,ERROR_CLOSE);
915 return ERROR_NT(status);
919 /* Realloc the size of parameters and data we will return */
920 *pparams = (char *)SMB_REALLOC(*pparams, 30);
921 if(*pparams == NULL ) {
922 return ERROR_NT(NT_STATUS_NO_MEMORY);
924 params = *pparams;
926 SSVAL(params,0,fsp->fnum);
927 SSVAL(params,2,fattr);
928 srv_put_dos_date2(params,4, mtime);
929 SIVAL(params,8, (uint32)size);
930 SSVAL(params,12,deny_mode);
931 SSVAL(params,14,0); /* open_type - file or directory. */
932 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
934 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
935 smb_action |= EXTENDED_OPLOCK_GRANTED;
938 SSVAL(params,18,smb_action);
941 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
943 SIVAL(params,20,inode);
944 SSVAL(params,24,0); /* Padding. */
945 if (flags & 8) {
946 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
947 SIVAL(params, 26, ea_size);
948 } else {
949 SIVAL(params, 26, 0);
952 /* Send the required number of replies */
953 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
955 return -1;
958 /*********************************************************
959 Routine to check if a given string matches exactly.
960 as a special case a mask of "." does NOT match. That
961 is required for correct wildcard semantics
962 Case can be significant or not.
963 **********************************************************/
965 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
967 if (mask[0] == '.' && mask[1] == 0)
968 return False;
969 if (conn->case_sensitive)
970 return strcmp(str,mask)==0;
971 if (StrCaseCmp(str,mask) != 0) {
972 return False;
974 if (dptr_has_wild(conn->dirptr)) {
975 return False;
977 return True;
980 /****************************************************************************
981 Return the filetype for UNIX extensions.
982 ****************************************************************************/
984 static uint32 unix_filetype(mode_t mode)
986 if(S_ISREG(mode))
987 return UNIX_TYPE_FILE;
988 else if(S_ISDIR(mode))
989 return UNIX_TYPE_DIR;
990 #ifdef S_ISLNK
991 else if(S_ISLNK(mode))
992 return UNIX_TYPE_SYMLINK;
993 #endif
994 #ifdef S_ISCHR
995 else if(S_ISCHR(mode))
996 return UNIX_TYPE_CHARDEV;
997 #endif
998 #ifdef S_ISBLK
999 else if(S_ISBLK(mode))
1000 return UNIX_TYPE_BLKDEV;
1001 #endif
1002 #ifdef S_ISFIFO
1003 else if(S_ISFIFO(mode))
1004 return UNIX_TYPE_FIFO;
1005 #endif
1006 #ifdef S_ISSOCK
1007 else if(S_ISSOCK(mode))
1008 return UNIX_TYPE_SOCKET;
1009 #endif
1011 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1012 return UNIX_TYPE_UNKNOWN;
1015 /****************************************************************************
1016 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1017 ****************************************************************************/
1019 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1021 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1022 SMB_STRUCT_STAT *psbuf,
1023 uint32 perms,
1024 enum perm_type ptype,
1025 mode_t *ret_perms)
1027 mode_t ret = 0;
1029 if (perms == SMB_MODE_NO_CHANGE) {
1030 if (!VALID_STAT(*psbuf)) {
1031 return NT_STATUS_INVALID_PARAMETER;
1032 } else {
1033 *ret_perms = psbuf->st_mode;
1034 return NT_STATUS_OK;
1038 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1039 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1040 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1041 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1042 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1043 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1044 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1045 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1046 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1047 #ifdef S_ISVTX
1048 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1049 #endif
1050 #ifdef S_ISGID
1051 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1052 #endif
1053 #ifdef S_ISUID
1054 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1055 #endif
1057 switch (ptype) {
1058 case PERM_NEW_FILE:
1059 /* Apply mode mask */
1060 ret &= lp_create_mask(SNUM(conn));
1061 /* Add in force bits */
1062 ret |= lp_force_create_mode(SNUM(conn));
1063 break;
1064 case PERM_NEW_DIR:
1065 ret &= lp_dir_mask(SNUM(conn));
1066 /* Add in force bits */
1067 ret |= lp_force_dir_mode(SNUM(conn));
1068 break;
1069 case PERM_EXISTING_FILE:
1070 /* Apply mode mask */
1071 ret &= lp_security_mask(SNUM(conn));
1072 /* Add in force bits */
1073 ret |= lp_force_security_mode(SNUM(conn));
1074 break;
1075 case PERM_EXISTING_DIR:
1076 /* Apply mode mask */
1077 ret &= lp_dir_security_mask(SNUM(conn));
1078 /* Add in force bits */
1079 ret |= lp_force_dir_security_mode(SNUM(conn));
1080 break;
1083 *ret_perms = ret;
1084 return NT_STATUS_OK;
1087 /****************************************************************************
1088 Get a level dependent lanman2 dir entry.
1089 ****************************************************************************/
1091 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1092 void *inbuf, char *outbuf,
1093 char *path_mask,uint32 dirtype,int info_level,
1094 int requires_resume_key,
1095 BOOL dont_descend,char **ppdata,
1096 char *base_data, char *end_data, int space_remaining,
1097 BOOL *out_of_space, BOOL *got_exact_match,
1098 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1100 const char *dname;
1101 BOOL found = False;
1102 SMB_STRUCT_STAT sbuf;
1103 pstring mask;
1104 pstring pathreal;
1105 pstring fname;
1106 char *p, *q, *pdata = *ppdata;
1107 uint32 reskey=0;
1108 long prev_dirpos=0;
1109 uint32 mode=0;
1110 SMB_OFF_T file_size = 0;
1111 SMB_BIG_UINT allocation_size = 0;
1112 uint32 len;
1113 struct timespec mdate_ts, adate_ts, create_date_ts;
1114 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1115 char *nameptr;
1116 char *last_entry_ptr;
1117 BOOL was_8_3;
1118 uint32 nt_extmode; /* Used for NT connections instead of mode */
1119 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1120 BOOL check_mangled_names = lp_manglednames(conn->params);
1122 *fname = 0;
1123 *out_of_space = False;
1124 *got_exact_match = False;
1126 ZERO_STRUCT(mdate_ts);
1127 ZERO_STRUCT(adate_ts);
1128 ZERO_STRUCT(create_date_ts);
1130 if (!conn->dirptr)
1131 return(False);
1133 p = strrchr_m(path_mask,'/');
1134 if(p != NULL) {
1135 if(p[1] == '\0')
1136 pstrcpy(mask,"*.*");
1137 else
1138 pstrcpy(mask, p+1);
1139 } else
1140 pstrcpy(mask, path_mask);
1143 while (!found) {
1144 BOOL got_match;
1145 BOOL ms_dfs_link = False;
1147 /* Needed if we run out of space */
1148 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1149 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1152 * Due to bugs in NT client redirectors we are not using
1153 * resume keys any more - set them to zero.
1154 * Check out the related comments in findfirst/findnext.
1155 * JRA.
1158 reskey = 0;
1160 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1161 (long)conn->dirptr,curr_dirpos));
1163 if (!dname)
1164 return(False);
1166 pstrcpy(fname,dname);
1168 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1169 got_match = mask_match(fname, mask, conn->case_sensitive);
1171 if(!got_match && check_mangled_names &&
1172 !mangle_is_8_3(fname, False, conn->params)) {
1175 * It turns out that NT matches wildcards against
1176 * both long *and* short names. This may explain some
1177 * of the wildcard wierdness from old DOS clients
1178 * that some people have been seeing.... JRA.
1181 pstring newname;
1182 pstrcpy( newname, fname);
1183 mangle_map( newname, True, False, conn->params);
1184 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1185 got_match = mask_match(newname, mask, conn->case_sensitive);
1188 if(got_match) {
1189 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1190 if (dont_descend && !isdots)
1191 continue;
1193 pstrcpy(pathreal,conn->dirpath);
1194 if(needslash)
1195 pstrcat(pathreal,"/");
1196 pstrcat(pathreal,dname);
1198 if (INFO_LEVEL_IS_UNIX(info_level)) {
1199 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1200 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1201 pathreal,strerror(errno)));
1202 continue;
1204 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1205 pstring link_target;
1207 /* Needed to show the msdfs symlinks as
1208 * directories */
1210 if(lp_host_msdfs() &&
1211 lp_msdfs_root(SNUM(conn)) &&
1212 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1213 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1214 "as a directory\n",
1215 pathreal));
1216 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1218 } else {
1220 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1221 pathreal,strerror(errno)));
1222 continue;
1226 if (ms_dfs_link) {
1227 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1228 } else {
1229 mode = dos_mode(conn,pathreal,&sbuf);
1232 if (!dir_check_ftype(conn,mode,dirtype)) {
1233 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1234 continue;
1237 if (!(mode & aDIR))
1238 file_size = get_file_size(sbuf);
1239 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1241 mdate_ts = get_mtimespec(&sbuf);
1242 adate_ts = get_atimespec(&sbuf);
1243 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1245 if (lp_dos_filetime_resolution(SNUM(conn))) {
1246 dos_filetime_timespec(&create_date_ts);
1247 dos_filetime_timespec(&mdate_ts);
1248 dos_filetime_timespec(&adate_ts);
1251 create_date = convert_timespec_to_time_t(create_date_ts);
1252 mdate = convert_timespec_to_time_t(mdate_ts);
1253 adate = convert_timespec_to_time_t(adate_ts);
1255 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1257 found = True;
1259 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1263 mangle_map(fname,False,True,conn->params);
1265 p = pdata;
1266 last_entry_ptr = p;
1268 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1270 switch (info_level) {
1271 case SMB_FIND_INFO_STANDARD:
1272 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1273 if(requires_resume_key) {
1274 SIVAL(p,0,reskey);
1275 p += 4;
1277 srv_put_dos_date2(p,0,create_date);
1278 srv_put_dos_date2(p,4,adate);
1279 srv_put_dos_date2(p,8,mdate);
1280 SIVAL(p,12,(uint32)file_size);
1281 SIVAL(p,16,(uint32)allocation_size);
1282 SSVAL(p,20,mode);
1283 p += 23;
1284 nameptr = p;
1285 p += align_string(outbuf, p, 0);
1286 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE);
1287 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1288 if (len > 2) {
1289 SCVAL(nameptr, -1, len - 2);
1290 } else {
1291 SCVAL(nameptr, -1, 0);
1293 } else {
1294 if (len > 1) {
1295 SCVAL(nameptr, -1, len - 1);
1296 } else {
1297 SCVAL(nameptr, -1, 0);
1300 p += len;
1301 break;
1303 case SMB_FIND_EA_SIZE:
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1305 if(requires_resume_key) {
1306 SIVAL(p,0,reskey);
1307 p += 4;
1309 srv_put_dos_date2(p,0,create_date);
1310 srv_put_dos_date2(p,4,adate);
1311 srv_put_dos_date2(p,8,mdate);
1312 SIVAL(p,12,(uint32)file_size);
1313 SIVAL(p,16,(uint32)allocation_size);
1314 SSVAL(p,20,mode);
1316 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1317 SIVAL(p,22,ea_size); /* Extended attributes */
1319 p += 27;
1320 nameptr = p - 1;
1321 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE | STR_NOALIGN);
1322 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1323 if (len > 2) {
1324 len -= 2;
1325 } else {
1326 len = 0;
1328 } else {
1329 if (len > 1) {
1330 len -= 1;
1331 } else {
1332 len = 0;
1335 SCVAL(nameptr,0,len);
1336 p += len;
1337 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1338 break;
1340 case SMB_FIND_EA_LIST:
1342 struct ea_list *file_list = NULL;
1343 size_t ea_len = 0;
1345 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1346 if (!name_list) {
1347 return False;
1349 if(requires_resume_key) {
1350 SIVAL(p,0,reskey);
1351 p += 4;
1353 srv_put_dos_date2(p,0,create_date);
1354 srv_put_dos_date2(p,4,adate);
1355 srv_put_dos_date2(p,8,mdate);
1356 SIVAL(p,12,(uint32)file_size);
1357 SIVAL(p,16,(uint32)allocation_size);
1358 SSVAL(p,20,mode);
1359 p += 22; /* p now points to the EA area. */
1361 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1362 name_list = ea_list_union(name_list, file_list, &ea_len);
1364 /* We need to determine if this entry will fit in the space available. */
1365 /* Max string size is 255 bytes. */
1366 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1367 /* Move the dirptr back to prev_dirpos */
1368 dptr_SeekDir(conn->dirptr, prev_dirpos);
1369 *out_of_space = True;
1370 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1371 return False; /* Not finished - just out of space */
1374 /* Push the ea_data followed by the name. */
1375 p += fill_ea_buffer(ea_ctx, p, space_remaining - (p - pdata), conn, name_list);
1376 nameptr = p;
1377 len = srvstr_push(outbuf, p + 1, fname, PTR_DIFF(end_data, p+1), STR_TERMINATE | STR_NOALIGN);
1378 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1379 if (len > 2) {
1380 len -= 2;
1381 } else {
1382 len = 0;
1384 } else {
1385 if (len > 1) {
1386 len -= 1;
1387 } else {
1388 len = 0;
1391 SCVAL(nameptr,0,len);
1392 p += len + 1;
1393 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1394 break;
1397 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1398 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1399 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1400 p += 4;
1401 SIVAL(p,0,reskey); p += 4;
1402 put_long_date_timespec(p,create_date_ts); p += 8;
1403 put_long_date_timespec(p,adate_ts); p += 8;
1404 put_long_date_timespec(p,mdate_ts); p += 8;
1405 put_long_date_timespec(p,mdate_ts); p += 8;
1406 SOFF_T(p,0,file_size); p += 8;
1407 SOFF_T(p,0,allocation_size); p += 8;
1408 SIVAL(p,0,nt_extmode); p += 4;
1409 q = p; p += 4; /* q is placeholder for name length. */
1411 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1412 SIVAL(p,0,ea_size); /* Extended attributes */
1413 p += 4;
1415 /* Clear the short name buffer. This is
1416 * IMPORTANT as not doing so will trigger
1417 * a Win2k client bug. JRA.
1419 if (!was_8_3 && check_mangled_names) {
1420 pstring mangled_name;
1421 pstrcpy(mangled_name, fname);
1422 mangle_map(mangled_name,True,True,
1423 conn->params);
1424 mangled_name[12] = 0;
1425 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1426 if (len < 24) {
1427 memset(p + 2 + len,'\0',24 - len);
1429 SSVAL(p, 0, len);
1430 } else {
1431 memset(p,'\0',26);
1433 p += 2 + 24;
1434 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1435 SIVAL(q,0,len);
1436 p += len;
1437 SIVAL(p,0,0); /* Ensure any padding is null. */
1438 len = PTR_DIFF(p, pdata);
1439 len = (len + 3) & ~3;
1440 SIVAL(pdata,0,len);
1441 p = pdata + len;
1442 break;
1444 case SMB_FIND_FILE_DIRECTORY_INFO:
1445 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1446 p += 4;
1447 SIVAL(p,0,reskey); p += 4;
1448 put_long_date_timespec(p,create_date_ts); p += 8;
1449 put_long_date_timespec(p,adate_ts); p += 8;
1450 put_long_date_timespec(p,mdate_ts); p += 8;
1451 put_long_date_timespec(p,mdate_ts); p += 8;
1452 SOFF_T(p,0,file_size); p += 8;
1453 SOFF_T(p,0,allocation_size); p += 8;
1454 SIVAL(p,0,nt_extmode); p += 4;
1455 len = srvstr_push(outbuf, p + 4, fname, PTR_DIFF(end_data, p+4), STR_TERMINATE_ASCII);
1456 SIVAL(p,0,len);
1457 p += 4 + len;
1458 SIVAL(p,0,0); /* Ensure any padding is null. */
1459 len = PTR_DIFF(p, pdata);
1460 len = (len + 3) & ~3;
1461 SIVAL(pdata,0,len);
1462 p = pdata + len;
1463 break;
1465 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1466 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1467 p += 4;
1468 SIVAL(p,0,reskey); p += 4;
1469 put_long_date_timespec(p,create_date_ts); p += 8;
1470 put_long_date_timespec(p,adate_ts); p += 8;
1471 put_long_date_timespec(p,mdate_ts); p += 8;
1472 put_long_date_timespec(p,mdate_ts); p += 8;
1473 SOFF_T(p,0,file_size); p += 8;
1474 SOFF_T(p,0,allocation_size); p += 8;
1475 SIVAL(p,0,nt_extmode); p += 4;
1476 q = p; p += 4; /* q is placeholder for name length. */
1478 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1479 SIVAL(p,0,ea_size); /* Extended attributes */
1480 p +=4;
1482 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1483 SIVAL(q, 0, len);
1484 p += len;
1486 SIVAL(p,0,0); /* Ensure any padding is null. */
1487 len = PTR_DIFF(p, pdata);
1488 len = (len + 3) & ~3;
1489 SIVAL(pdata,0,len);
1490 p = pdata + len;
1491 break;
1493 case SMB_FIND_FILE_NAMES_INFO:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1495 p += 4;
1496 SIVAL(p,0,reskey); p += 4;
1497 p += 4;
1498 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1499 acl on a dir (tridge) */
1500 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1501 SIVAL(p, -4, len);
1502 p += len;
1503 SIVAL(p,0,0); /* Ensure any padding is null. */
1504 len = PTR_DIFF(p, pdata);
1505 len = (len + 3) & ~3;
1506 SIVAL(pdata,0,len);
1507 p = pdata + len;
1508 break;
1510 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1511 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1512 p += 4;
1513 SIVAL(p,0,reskey); p += 4;
1514 put_long_date_timespec(p,create_date_ts); p += 8;
1515 put_long_date_timespec(p,adate_ts); p += 8;
1516 put_long_date_timespec(p,mdate_ts); p += 8;
1517 put_long_date_timespec(p,mdate_ts); p += 8;
1518 SOFF_T(p,0,file_size); p += 8;
1519 SOFF_T(p,0,allocation_size); p += 8;
1520 SIVAL(p,0,nt_extmode); p += 4;
1521 q = p; p += 4; /* q is placeholder for name length. */
1523 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1524 SIVAL(p,0,ea_size); /* Extended attributes */
1525 p +=4;
1527 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1528 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1529 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1530 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1531 SIVAL(q, 0, len);
1532 p += len;
1533 SIVAL(p,0,0); /* Ensure any padding is null. */
1534 len = PTR_DIFF(p, pdata);
1535 len = (len + 3) & ~3;
1536 SIVAL(pdata,0,len);
1537 p = pdata + len;
1538 break;
1540 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1541 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1542 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1543 p += 4;
1544 SIVAL(p,0,reskey); p += 4;
1545 put_long_date_timespec(p,create_date_ts); p += 8;
1546 put_long_date_timespec(p,adate_ts); p += 8;
1547 put_long_date_timespec(p,mdate_ts); p += 8;
1548 put_long_date_timespec(p,mdate_ts); p += 8;
1549 SOFF_T(p,0,file_size); p += 8;
1550 SOFF_T(p,0,allocation_size); p += 8;
1551 SIVAL(p,0,nt_extmode); p += 4;
1552 q = p; p += 4; /* q is placeholder for name length */
1554 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1555 SIVAL(p,0,ea_size); /* Extended attributes */
1556 p +=4;
1558 /* Clear the short name buffer. This is
1559 * IMPORTANT as not doing so will trigger
1560 * a Win2k client bug. JRA.
1562 if (!was_8_3 && check_mangled_names) {
1563 pstring mangled_name;
1564 pstrcpy(mangled_name, fname);
1565 mangle_map(mangled_name,True,True,
1566 conn->params);
1567 mangled_name[12] = 0;
1568 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1569 SSVAL(p, 0, len);
1570 if (len < 24) {
1571 memset(p + 2 + len,'\0',24 - len);
1573 SSVAL(p, 0, len);
1574 } else {
1575 memset(p,'\0',26);
1577 p += 26;
1578 SSVAL(p,0,0); p += 2; /* Reserved ? */
1579 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1580 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1581 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII);
1582 SIVAL(q,0,len);
1583 p += len;
1584 SIVAL(p,0,0); /* Ensure any padding is null. */
1585 len = PTR_DIFF(p, pdata);
1586 len = (len + 3) & ~3;
1587 SIVAL(pdata,0,len);
1588 p = pdata + len;
1589 break;
1591 /* CIFS UNIX Extension. */
1593 case SMB_FIND_FILE_UNIX:
1594 case SMB_FIND_FILE_UNIX_INFO2:
1595 p+= 4;
1596 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1598 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1600 if (info_level == SMB_FIND_FILE_UNIX) {
1601 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1602 p = store_file_unix_basic(conn, p,
1603 NULL, &sbuf);
1604 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE);
1605 } else {
1606 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1607 p = store_file_unix_basic_info2(conn, p,
1608 NULL, &sbuf);
1609 nameptr = p;
1610 p += 4;
1611 len = srvstr_push(outbuf, p, fname, PTR_DIFF(end_data, p), 0);
1612 SIVAL(nameptr, 0, len);
1615 p += len;
1616 SIVAL(p,0,0); /* Ensure any padding is null. */
1618 len = PTR_DIFF(p, pdata);
1619 len = (len + 3) & ~3;
1620 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1621 p = pdata + len;
1622 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1624 break;
1626 default:
1627 return(False);
1631 if (PTR_DIFF(p,pdata) > space_remaining) {
1632 /* Move the dirptr back to prev_dirpos */
1633 dptr_SeekDir(conn->dirptr, prev_dirpos);
1634 *out_of_space = True;
1635 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1636 return False; /* Not finished - just out of space */
1639 /* Setup the last entry pointer, as an offset from base_data */
1640 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1641 /* Advance the data pointer to the next slot */
1642 *ppdata = p;
1644 return(found);
1647 /****************************************************************************
1648 Reply to a TRANS2_FINDFIRST.
1649 ****************************************************************************/
1651 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1652 char **pparams, int total_params, char **ppdata, int total_data,
1653 unsigned int max_data_bytes)
1655 /* We must be careful here that we don't return more than the
1656 allowed number of data bytes. If this means returning fewer than
1657 maxentries then so be it. We assume that the redirector has
1658 enough room for the fixed number of parameter bytes it has
1659 requested. */
1660 char *params = *pparams;
1661 char *pdata = *ppdata;
1662 char *data_end;
1663 uint32 dirtype;
1664 int maxentries;
1665 uint16 findfirst_flags;
1666 BOOL close_after_first;
1667 BOOL close_if_end;
1668 BOOL requires_resume_key;
1669 int info_level;
1670 pstring directory;
1671 pstring mask;
1672 char *p;
1673 int last_entry_off=0;
1674 int dptr_num = -1;
1675 int numentries = 0;
1676 int i;
1677 BOOL finished = False;
1678 BOOL dont_descend = False;
1679 BOOL out_of_space = False;
1680 int space_remaining;
1681 BOOL mask_contains_wcard = False;
1682 SMB_STRUCT_STAT sbuf;
1683 TALLOC_CTX *ea_ctx = NULL;
1684 struct ea_list *ea_list = NULL;
1685 NTSTATUS ntstatus = NT_STATUS_OK;
1687 if (total_params < 13) {
1688 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1691 dirtype = SVAL(params,0);
1692 maxentries = SVAL(params,2);
1693 findfirst_flags = SVAL(params,4);
1694 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1695 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1696 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1697 info_level = SVAL(params,6);
1699 *directory = *mask = 0;
1701 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1702 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1703 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1704 info_level, max_data_bytes));
1706 if (!maxentries) {
1707 /* W2K3 seems to treat zero as 1. */
1708 maxentries = 1;
1711 switch (info_level) {
1712 case SMB_FIND_INFO_STANDARD:
1713 case SMB_FIND_EA_SIZE:
1714 case SMB_FIND_EA_LIST:
1715 case SMB_FIND_FILE_DIRECTORY_INFO:
1716 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1717 case SMB_FIND_FILE_NAMES_INFO:
1718 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1719 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1720 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1721 break;
1722 case SMB_FIND_FILE_UNIX:
1723 case SMB_FIND_FILE_UNIX_INFO2:
1724 if (!lp_unix_extensions()) {
1725 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1727 break;
1728 default:
1729 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1732 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1733 if (!NT_STATUS_IS_OK(ntstatus)) {
1734 return ERROR_NT(ntstatus);
1737 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1738 if (!NT_STATUS_IS_OK(ntstatus)) {
1739 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1740 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1742 return ERROR_NT(ntstatus);
1745 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1746 if (!NT_STATUS_IS_OK(ntstatus)) {
1747 return ERROR_NT(ntstatus);
1749 ntstatus = check_name(conn, directory);
1750 if (!NT_STATUS_IS_OK(ntstatus)) {
1751 return ERROR_NT(ntstatus);
1754 p = strrchr_m(directory,'/');
1755 if(p == NULL) {
1756 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1757 if((directory[0] == '.') && (directory[1] == '\0')) {
1758 pstrcpy(mask,"*");
1759 mask_contains_wcard = True;
1760 } else {
1761 pstrcpy(mask,directory);
1763 pstrcpy(directory,"./");
1764 } else {
1765 pstrcpy(mask,p+1);
1766 *p = 0;
1769 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1771 if (info_level == SMB_FIND_EA_LIST) {
1772 uint32 ea_size;
1774 if (total_data < 4) {
1775 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1778 ea_size = IVAL(pdata,0);
1779 if (ea_size != total_data) {
1780 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1781 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1782 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1785 if (!lp_ea_support(SNUM(conn))) {
1786 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1789 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1790 return ERROR_NT(NT_STATUS_NO_MEMORY);
1793 /* Pull out the list of names. */
1794 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1795 if (!ea_list) {
1796 talloc_destroy(ea_ctx);
1797 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1801 *ppdata = (char *)SMB_REALLOC(
1802 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1803 if(*ppdata == NULL ) {
1804 talloc_destroy(ea_ctx);
1805 return ERROR_NT(NT_STATUS_NO_MEMORY);
1807 pdata = *ppdata;
1808 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1810 /* Realloc the params space */
1811 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1812 if (*pparams == NULL) {
1813 talloc_destroy(ea_ctx);
1814 return ERROR_NT(NT_STATUS_NO_MEMORY);
1816 params = *pparams;
1818 /* Save the wildcard match and attribs we are using on this directory -
1819 needed as lanman2 assumes these are being saved between calls */
1821 ntstatus = dptr_create(conn,
1822 directory,
1823 False,
1824 True,
1825 SVAL(inbuf,smb_pid),
1826 mask,
1827 mask_contains_wcard,
1828 dirtype,
1829 &conn->dirptr);
1831 if (!NT_STATUS_IS_OK(ntstatus)) {
1832 talloc_destroy(ea_ctx);
1833 return ERROR_NT(ntstatus);
1836 dptr_num = dptr_dnum(conn->dirptr);
1837 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1839 /* We don't need to check for VOL here as this is returned by
1840 a different TRANS2 call. */
1842 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1843 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1844 dont_descend = True;
1846 p = pdata;
1847 space_remaining = max_data_bytes;
1848 out_of_space = False;
1850 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1851 BOOL got_exact_match = False;
1853 /* this is a heuristic to avoid seeking the dirptr except when
1854 absolutely necessary. It allows for a filename of about 40 chars */
1855 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1856 out_of_space = True;
1857 finished = False;
1858 } else {
1859 finished = !get_lanman2_dir_entry(conn,
1860 inbuf, outbuf,
1861 mask,dirtype,info_level,
1862 requires_resume_key,dont_descend,
1863 &p,pdata,data_end,space_remaining, &out_of_space, &got_exact_match,
1864 &last_entry_off, ea_list, ea_ctx);
1867 if (finished && out_of_space)
1868 finished = False;
1870 if (!finished && !out_of_space)
1871 numentries++;
1874 * As an optimisation if we know we aren't looking
1875 * for a wildcard name (ie. the name matches the wildcard exactly)
1876 * then we can finish on any (first) match.
1877 * This speeds up large directory searches. JRA.
1880 if(got_exact_match)
1881 finished = True;
1883 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1886 talloc_destroy(ea_ctx);
1888 /* Check if we can close the dirptr */
1889 if(close_after_first || (finished && close_if_end)) {
1890 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1891 dptr_close(&dptr_num);
1895 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1896 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1897 * the protocol level is less than NT1. Tested with smbclient. JRA.
1898 * This should fix the OS/2 client bug #2335.
1901 if(numentries == 0) {
1902 dptr_close(&dptr_num);
1903 if (Protocol < PROTOCOL_NT1) {
1904 return ERROR_DOS(ERRDOS,ERRnofiles);
1905 } else {
1906 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1910 /* At this point pdata points to numentries directory entries. */
1912 /* Set up the return parameter block */
1913 SSVAL(params,0,dptr_num);
1914 SSVAL(params,2,numentries);
1915 SSVAL(params,4,finished);
1916 SSVAL(params,6,0); /* Never an EA error */
1917 SSVAL(params,8,last_entry_off);
1919 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1921 if ((! *directory) && dptr_path(dptr_num))
1922 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1924 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1925 smb_fn_name(CVAL(inbuf,smb_com)),
1926 mask, directory, dirtype, numentries ) );
1929 * Force a name mangle here to ensure that the
1930 * mask as an 8.3 name is top of the mangled cache.
1931 * The reasons for this are subtle. Don't remove
1932 * this code unless you know what you are doing
1933 * (see PR#13758). JRA.
1936 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1937 mangle_map(mask, True, True, conn->params);
1939 return(-1);
1942 /****************************************************************************
1943 Reply to a TRANS2_FINDNEXT.
1944 ****************************************************************************/
1946 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1947 char **pparams, int total_params, char **ppdata, int total_data,
1948 unsigned int max_data_bytes)
1950 /* We must be careful here that we don't return more than the
1951 allowed number of data bytes. If this means returning fewer than
1952 maxentries then so be it. We assume that the redirector has
1953 enough room for the fixed number of parameter bytes it has
1954 requested. */
1955 char *params = *pparams;
1956 char *pdata = *ppdata;
1957 char *data_end;
1958 int dptr_num;
1959 int maxentries;
1960 uint16 info_level;
1961 uint32 resume_key;
1962 uint16 findnext_flags;
1963 BOOL close_after_request;
1964 BOOL close_if_end;
1965 BOOL requires_resume_key;
1966 BOOL continue_bit;
1967 BOOL mask_contains_wcard = False;
1968 pstring resume_name;
1969 pstring mask;
1970 pstring directory;
1971 char *p;
1972 uint16 dirtype;
1973 int numentries = 0;
1974 int i, last_entry_off=0;
1975 BOOL finished = False;
1976 BOOL dont_descend = False;
1977 BOOL out_of_space = False;
1978 int space_remaining;
1979 TALLOC_CTX *ea_ctx = NULL;
1980 struct ea_list *ea_list = NULL;
1981 NTSTATUS ntstatus = NT_STATUS_OK;
1983 if (total_params < 13) {
1984 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1987 dptr_num = SVAL(params,0);
1988 maxentries = SVAL(params,2);
1989 info_level = SVAL(params,4);
1990 resume_key = IVAL(params,6);
1991 findnext_flags = SVAL(params,10);
1992 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1993 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1994 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1995 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1997 *mask = *directory = *resume_name = 0;
1999 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2000 if (!NT_STATUS_IS_OK(ntstatus)) {
2001 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2002 complain (it thinks we're asking for the directory above the shared
2003 path or an invalid name). Catch this as the resume name is only compared, never used in
2004 a file access. JRA. */
2005 srvstr_pull(inbuf, resume_name, params+12,
2006 sizeof(resume_name), total_params - 12,
2007 STR_TERMINATE);
2009 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2010 return ERROR_NT(ntstatus);
2014 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2015 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2016 resume_key = %d resume name = %s continue=%d level = %d\n",
2017 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2018 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2020 if (!maxentries) {
2021 /* W2K3 seems to treat zero as 1. */
2022 maxentries = 1;
2025 switch (info_level) {
2026 case SMB_FIND_INFO_STANDARD:
2027 case SMB_FIND_EA_SIZE:
2028 case SMB_FIND_EA_LIST:
2029 case SMB_FIND_FILE_DIRECTORY_INFO:
2030 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2031 case SMB_FIND_FILE_NAMES_INFO:
2032 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2033 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2034 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2035 break;
2036 case SMB_FIND_FILE_UNIX:
2037 case SMB_FIND_FILE_UNIX_INFO2:
2038 if (!lp_unix_extensions()) {
2039 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2041 break;
2042 default:
2043 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2046 if (info_level == SMB_FIND_EA_LIST) {
2047 uint32 ea_size;
2049 if (total_data < 4) {
2050 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2053 ea_size = IVAL(pdata,0);
2054 if (ea_size != total_data) {
2055 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2056 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2057 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2060 if (!lp_ea_support(SNUM(conn))) {
2061 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2064 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2065 return ERROR_NT(NT_STATUS_NO_MEMORY);
2068 /* Pull out the list of names. */
2069 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2070 if (!ea_list) {
2071 talloc_destroy(ea_ctx);
2072 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2076 *ppdata = (char *)SMB_REALLOC(
2077 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2078 if(*ppdata == NULL) {
2079 talloc_destroy(ea_ctx);
2080 return ERROR_NT(NT_STATUS_NO_MEMORY);
2083 pdata = *ppdata;
2084 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2086 /* Realloc the params space */
2087 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2088 if(*pparams == NULL ) {
2089 talloc_destroy(ea_ctx);
2090 return ERROR_NT(NT_STATUS_NO_MEMORY);
2093 params = *pparams;
2095 /* Check that the dptr is valid */
2096 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2097 talloc_destroy(ea_ctx);
2098 return ERROR_DOS(ERRDOS,ERRnofiles);
2101 string_set(&conn->dirpath,dptr_path(dptr_num));
2103 /* Get the wildcard mask from the dptr */
2104 if((p = dptr_wcard(dptr_num))== NULL) {
2105 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2106 talloc_destroy(ea_ctx);
2107 return ERROR_DOS(ERRDOS,ERRnofiles);
2110 pstrcpy(mask, p);
2111 pstrcpy(directory,conn->dirpath);
2113 /* Get the attr mask from the dptr */
2114 dirtype = dptr_attr(dptr_num);
2116 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2117 dptr_num, mask, dirtype,
2118 (long)conn->dirptr,
2119 dptr_TellDir(conn->dirptr)));
2121 /* We don't need to check for VOL here as this is returned by
2122 a different TRANS2 call. */
2124 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2125 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2126 dont_descend = True;
2128 p = pdata;
2129 space_remaining = max_data_bytes;
2130 out_of_space = False;
2133 * Seek to the correct position. We no longer use the resume key but
2134 * depend on the last file name instead.
2137 if(*resume_name && !continue_bit) {
2138 SMB_STRUCT_STAT st;
2140 long current_pos = 0;
2142 * Remember, mangle_map is called by
2143 * get_lanman2_dir_entry(), so the resume name
2144 * could be mangled. Ensure we check the unmangled name.
2147 if (mangle_is_mangled(resume_name, conn->params)) {
2148 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2149 conn->params);
2153 * Fix for NT redirector problem triggered by resume key indexes
2154 * changing between directory scans. We now return a resume key of 0
2155 * and instead look for the filename to continue from (also given
2156 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2157 * findfirst/findnext (as is usual) then the directory pointer
2158 * should already be at the correct place.
2161 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2162 } /* end if resume_name && !continue_bit */
2164 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2165 BOOL got_exact_match = False;
2167 /* this is a heuristic to avoid seeking the dirptr except when
2168 absolutely necessary. It allows for a filename of about 40 chars */
2169 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2170 out_of_space = True;
2171 finished = False;
2172 } else {
2173 finished = !get_lanman2_dir_entry(conn,
2174 inbuf, outbuf,
2175 mask,dirtype,info_level,
2176 requires_resume_key,dont_descend,
2177 &p,pdata,data_end,space_remaining, &out_of_space, &got_exact_match,
2178 &last_entry_off, ea_list, ea_ctx);
2181 if (finished && out_of_space)
2182 finished = False;
2184 if (!finished && !out_of_space)
2185 numentries++;
2188 * As an optimisation if we know we aren't looking
2189 * for a wildcard name (ie. the name matches the wildcard exactly)
2190 * then we can finish on any (first) match.
2191 * This speeds up large directory searches. JRA.
2194 if(got_exact_match)
2195 finished = True;
2197 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2200 talloc_destroy(ea_ctx);
2202 /* Check if we can close the dirptr */
2203 if(close_after_request || (finished && close_if_end)) {
2204 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2205 dptr_close(&dptr_num); /* This frees up the saved mask */
2208 /* Set up the return parameter block */
2209 SSVAL(params,0,numentries);
2210 SSVAL(params,2,finished);
2211 SSVAL(params,4,0); /* Never an EA error */
2212 SSVAL(params,6,last_entry_off);
2214 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2216 if ((! *directory) && dptr_path(dptr_num))
2217 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2219 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2220 smb_fn_name(CVAL(inbuf,smb_com)),
2221 mask, directory, dirtype, numentries ) );
2223 return(-1);
2226 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2228 SMB_ASSERT(extended_info != NULL);
2230 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2231 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2232 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2233 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2234 #ifdef SAMBA_VERSION_REVISION
2235 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2236 #endif
2237 extended_info->samba_subversion = 0;
2238 #ifdef SAMBA_VERSION_RC_RELEASE
2239 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2240 #else
2241 #ifdef SAMBA_VERSION_PRE_RELEASE
2242 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2243 #endif
2244 #endif
2245 #ifdef SAMBA_VERSION_VENDOR_PATCH
2246 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2247 #endif
2248 extended_info->samba_subversion = 0;
2249 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2250 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2251 #endif
2253 memset(extended_info->samba_version_string, 0,
2254 sizeof(extended_info->samba_version_string));
2256 snprintf (extended_info->samba_version_string,
2257 sizeof(extended_info->samba_version_string),
2258 "%s", samba_version_string());
2261 /****************************************************************************
2262 Reply to a TRANS2_QFSINFO (query filesystem info).
2263 ****************************************************************************/
2265 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2266 char **pparams, int total_params, char **ppdata, int total_data,
2267 unsigned int max_data_bytes)
2269 char *pdata;
2270 char *params = *pparams;
2271 uint16 info_level;
2272 int data_len, len;
2273 SMB_STRUCT_STAT st;
2274 const char *vname = volume_label(SNUM(conn));
2275 int snum = SNUM(conn);
2276 char *fstype = lp_fstype(SNUM(conn));
2277 int quota_flag = 0;
2279 if (total_params < 2) {
2280 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2283 info_level = SVAL(params,0);
2285 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2287 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2288 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2289 return ERROR_DOS(ERRSRV,ERRinvdevice);
2292 *ppdata = (char *)SMB_REALLOC(
2293 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2294 if (*ppdata == NULL ) {
2295 return ERROR_NT(NT_STATUS_NO_MEMORY);
2298 pdata = *ppdata;
2299 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2301 switch (info_level) {
2302 case SMB_INFO_ALLOCATION:
2304 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2305 data_len = 18;
2306 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2307 return(UNIXERROR(ERRHRD,ERRgeneral));
2310 block_size = lp_block_size(snum);
2311 if (bsize < block_size) {
2312 SMB_BIG_UINT factor = block_size/bsize;
2313 bsize = block_size;
2314 dsize /= factor;
2315 dfree /= factor;
2317 if (bsize > block_size) {
2318 SMB_BIG_UINT factor = bsize/block_size;
2319 bsize = block_size;
2320 dsize *= factor;
2321 dfree *= factor;
2323 bytes_per_sector = 512;
2324 sectors_per_unit = bsize/bytes_per_sector;
2326 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2327 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2328 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2330 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2331 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2332 SIVAL(pdata,l1_cUnit,dsize);
2333 SIVAL(pdata,l1_cUnitAvail,dfree);
2334 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2335 break;
2338 case SMB_INFO_VOLUME:
2339 /* Return volume name */
2341 * Add volume serial number - hash of a combination of
2342 * the called hostname and the service name.
2344 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2346 * Win2k3 and previous mess this up by sending a name length
2347 * one byte short. I believe only older clients (OS/2 Win9x) use
2348 * this call so try fixing this by adding a terminating null to
2349 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2351 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, max_data_bytes - l2_vol_szVolLabel, STR_NOALIGN|STR_TERMINATE);
2352 SCVAL(pdata,l2_vol_cch,len);
2353 data_len = l2_vol_szVolLabel + len;
2354 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2355 (unsigned)st.st_ctime, len, vname));
2356 break;
2358 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2359 case SMB_FS_ATTRIBUTE_INFORMATION:
2362 #if defined(HAVE_SYS_QUOTAS)
2363 quota_flag = FILE_VOLUME_QUOTAS;
2364 #endif
2366 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2367 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2368 FILE_UNICODE_ON_DISK|
2369 quota_flag); /* FS ATTRIBUTES */
2371 SIVAL(pdata,4,255); /* Max filename component length */
2372 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2373 and will think we can't do long filenames */
2374 len = srvstr_push(outbuf, pdata+12, fstype, max_data_bytes - 12, STR_UNICODE);
2375 SIVAL(pdata,8,len);
2376 data_len = 12 + len;
2377 break;
2379 case SMB_QUERY_FS_LABEL_INFO:
2380 case SMB_FS_LABEL_INFORMATION:
2381 len = srvstr_push(outbuf, pdata+4, vname, max_data_bytes - 4, 0);
2382 data_len = 4 + len;
2383 SIVAL(pdata,0,len);
2384 break;
2386 case SMB_QUERY_FS_VOLUME_INFO:
2387 case SMB_FS_VOLUME_INFORMATION:
2390 * Add volume serial number - hash of a combination of
2391 * the called hostname and the service name.
2393 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2394 (str_checksum(get_local_machine_name())<<16));
2396 /* Max label len is 32 characters. */
2397 len = srvstr_push(outbuf, pdata+18, vname, max_data_bytes - 18, STR_UNICODE);
2398 SIVAL(pdata,12,len);
2399 data_len = 18+len;
2401 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2402 (int)strlen(vname),vname, lp_servicename(snum)));
2403 break;
2405 case SMB_QUERY_FS_SIZE_INFO:
2406 case SMB_FS_SIZE_INFORMATION:
2408 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2409 data_len = 24;
2410 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2411 return(UNIXERROR(ERRHRD,ERRgeneral));
2413 block_size = lp_block_size(snum);
2414 if (bsize < block_size) {
2415 SMB_BIG_UINT factor = block_size/bsize;
2416 bsize = block_size;
2417 dsize /= factor;
2418 dfree /= factor;
2420 if (bsize > block_size) {
2421 SMB_BIG_UINT factor = bsize/block_size;
2422 bsize = block_size;
2423 dsize *= factor;
2424 dfree *= factor;
2426 bytes_per_sector = 512;
2427 sectors_per_unit = bsize/bytes_per_sector;
2428 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2429 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2430 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2431 SBIG_UINT(pdata,0,dsize);
2432 SBIG_UINT(pdata,8,dfree);
2433 SIVAL(pdata,16,sectors_per_unit);
2434 SIVAL(pdata,20,bytes_per_sector);
2435 break;
2438 case SMB_FS_FULL_SIZE_INFORMATION:
2440 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2441 data_len = 32;
2442 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2443 return(UNIXERROR(ERRHRD,ERRgeneral));
2445 block_size = lp_block_size(snum);
2446 if (bsize < block_size) {
2447 SMB_BIG_UINT factor = block_size/bsize;
2448 bsize = block_size;
2449 dsize /= factor;
2450 dfree /= factor;
2452 if (bsize > block_size) {
2453 SMB_BIG_UINT factor = bsize/block_size;
2454 bsize = block_size;
2455 dsize *= factor;
2456 dfree *= factor;
2458 bytes_per_sector = 512;
2459 sectors_per_unit = bsize/bytes_per_sector;
2460 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2461 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2462 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2463 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2464 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2465 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2466 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2467 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2468 break;
2471 case SMB_QUERY_FS_DEVICE_INFO:
2472 case SMB_FS_DEVICE_INFORMATION:
2473 data_len = 8;
2474 SIVAL(pdata,0,0); /* dev type */
2475 SIVAL(pdata,4,0); /* characteristics */
2476 break;
2478 #ifdef HAVE_SYS_QUOTAS
2479 case SMB_FS_QUOTA_INFORMATION:
2481 * what we have to send --metze:
2483 * Unknown1: 24 NULL bytes
2484 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2485 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2486 * Quota Flags: 2 byte :
2487 * Unknown3: 6 NULL bytes
2489 * 48 bytes total
2491 * details for Quota Flags:
2493 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2494 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2495 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2496 * 0x0001 Enable Quotas: enable quota for this fs
2500 /* we need to fake up a fsp here,
2501 * because its not send in this call
2503 files_struct fsp;
2504 SMB_NTQUOTA_STRUCT quotas;
2506 ZERO_STRUCT(fsp);
2507 ZERO_STRUCT(quotas);
2509 fsp.conn = conn;
2510 fsp.fnum = -1;
2512 /* access check */
2513 if (current_user.ut.uid != 0) {
2514 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2515 lp_servicename(SNUM(conn)),conn->user));
2516 return ERROR_DOS(ERRDOS,ERRnoaccess);
2519 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2520 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2521 return ERROR_DOS(ERRSRV,ERRerror);
2524 data_len = 48;
2526 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2528 /* Unknown1 24 NULL bytes*/
2529 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2530 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2531 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2533 /* Default Soft Quota 8 bytes */
2534 SBIG_UINT(pdata,24,quotas.softlim);
2536 /* Default Hard Quota 8 bytes */
2537 SBIG_UINT(pdata,32,quotas.hardlim);
2539 /* Quota flag 2 bytes */
2540 SSVAL(pdata,40,quotas.qflags);
2542 /* Unknown3 6 NULL bytes */
2543 SSVAL(pdata,42,0);
2544 SIVAL(pdata,44,0);
2546 break;
2548 #endif /* HAVE_SYS_QUOTAS */
2549 case SMB_FS_OBJECTID_INFORMATION:
2552 * No object id, but we transmit version information.
2554 struct smb_extended_info extended_info;
2555 samba_extended_info_version (&extended_info);
2556 SIVAL(pdata,16,extended_info.samba_magic);
2557 SIVAL(pdata,20,extended_info.samba_version);
2558 SIVAL(pdata,24,extended_info.samba_subversion);
2559 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2560 memcpy(pdata+36,extended_info.samba_version_string,28);
2561 data_len = 64;
2562 break;
2566 * Query the version and capabilities of the CIFS UNIX extensions
2567 * in use.
2570 case SMB_QUERY_CIFS_UNIX_INFO:
2571 if (!lp_unix_extensions()) {
2572 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2574 data_len = 12;
2575 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2576 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2577 /* We have POSIX ACLs, pathname and locking capability. */
2578 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2579 CIFS_UNIX_POSIX_ACLS_CAP|
2580 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2581 CIFS_UNIX_FCNTL_LOCKS_CAP|
2582 CIFS_UNIX_EXTATTR_CAP|
2583 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2584 break;
2586 case SMB_QUERY_POSIX_FS_INFO:
2588 int rc;
2589 vfs_statvfs_struct svfs;
2591 if (!lp_unix_extensions()) {
2592 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2595 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2597 if (!rc) {
2598 data_len = 56;
2599 SIVAL(pdata,0,svfs.OptimalTransferSize);
2600 SIVAL(pdata,4,svfs.BlockSize);
2601 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2602 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2603 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2604 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2605 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2606 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2607 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2608 #ifdef EOPNOTSUPP
2609 } else if (rc == EOPNOTSUPP) {
2610 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2611 #endif /* EOPNOTSUPP */
2612 } else {
2613 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2614 return ERROR_DOS(ERRSRV,ERRerror);
2616 break;
2619 case SMB_QUERY_POSIX_WHOAMI:
2621 uint32_t flags = 0;
2622 uint32_t sid_bytes;
2623 int i;
2625 if (!lp_unix_extensions()) {
2626 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2629 if (max_data_bytes < 40) {
2630 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2633 /* We ARE guest if global_sid_Builtin_Guests is
2634 * in our list of SIDs.
2636 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2637 current_user.nt_user_token)) {
2638 flags |= SMB_WHOAMI_GUEST;
2641 /* We are NOT guest if global_sid_Authenticated_Users
2642 * is in our list of SIDs.
2644 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2645 current_user.nt_user_token)) {
2646 flags &= ~SMB_WHOAMI_GUEST;
2649 /* NOTE: 8 bytes for UID/GID, irrespective of native
2650 * platform size. This matches
2651 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2653 data_len = 4 /* flags */
2654 + 4 /* flag mask */
2655 + 8 /* uid */
2656 + 8 /* gid */
2657 + 4 /* ngroups */
2658 + 4 /* num_sids */
2659 + 4 /* SID bytes */
2660 + 4 /* pad/reserved */
2661 + (current_user.ut.ngroups * 8)
2662 /* groups list */
2663 + (current_user.nt_user_token->num_sids *
2664 SID_MAX_SIZE)
2665 /* SID list */;
2667 SIVAL(pdata, 0, flags);
2668 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2669 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2670 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2673 if (data_len >= max_data_bytes) {
2674 /* Potential overflow, skip the GIDs and SIDs. */
2676 SIVAL(pdata, 24, 0); /* num_groups */
2677 SIVAL(pdata, 28, 0); /* num_sids */
2678 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2679 SIVAL(pdata, 36, 0); /* reserved */
2681 data_len = 40;
2682 break;
2685 SIVAL(pdata, 24, current_user.ut.ngroups);
2686 SIVAL(pdata, 28,
2687 current_user.nt_user_token->num_sids);
2689 /* We walk the SID list twice, but this call is fairly
2690 * infrequent, and I don't expect that it's performance
2691 * sensitive -- jpeach
2693 for (i = 0, sid_bytes = 0;
2694 i < current_user.nt_user_token->num_sids; ++i) {
2695 sid_bytes +=
2696 sid_size(&current_user.nt_user_token->user_sids[i]);
2699 /* SID list byte count */
2700 SIVAL(pdata, 32, sid_bytes);
2702 /* 4 bytes pad/reserved - must be zero */
2703 SIVAL(pdata, 36, 0);
2704 data_len = 40;
2706 /* GID list */
2707 for (i = 0; i < current_user.ut.ngroups; ++i) {
2708 SBIG_UINT(pdata, data_len,
2709 (SMB_BIG_UINT)current_user.ut.groups[i]);
2710 data_len += 8;
2713 /* SID list */
2714 for (i = 0;
2715 i < current_user.nt_user_token->num_sids; ++i) {
2716 int sid_len =
2717 sid_size(&current_user.nt_user_token->user_sids[i]);
2719 sid_linearize(pdata + data_len, sid_len,
2720 &current_user.nt_user_token->user_sids[i]);
2721 data_len += sid_len;
2724 break;
2727 case SMB_MAC_QUERY_FS_INFO:
2729 * Thursby MAC extension... ONLY on NTFS filesystems
2730 * once we do streams then we don't need this
2732 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2733 data_len = 88;
2734 SIVAL(pdata,84,0x100); /* Don't support mac... */
2735 break;
2737 /* drop through */
2738 default:
2739 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2743 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2745 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2747 return -1;
2750 /****************************************************************************
2751 Reply to a TRANS2_SETFSINFO (set filesystem info).
2752 ****************************************************************************/
2754 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2755 char **pparams, int total_params, char **ppdata, int total_data,
2756 unsigned int max_data_bytes)
2758 char *pdata = *ppdata;
2759 char *params = *pparams;
2760 uint16 info_level;
2761 int outsize;
2763 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2765 /* */
2766 if (total_params < 4) {
2767 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2768 total_params));
2769 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2772 info_level = SVAL(params,2);
2774 switch(info_level) {
2775 case SMB_SET_CIFS_UNIX_INFO:
2777 uint16 client_unix_major;
2778 uint16 client_unix_minor;
2779 uint32 client_unix_cap_low;
2780 uint32 client_unix_cap_high;
2782 if (!lp_unix_extensions()) {
2783 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2786 /* There should be 12 bytes of capabilities set. */
2787 if (total_data < 8) {
2788 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2790 client_unix_major = SVAL(pdata,0);
2791 client_unix_minor = SVAL(pdata,2);
2792 client_unix_cap_low = IVAL(pdata,4);
2793 client_unix_cap_high = IVAL(pdata,8);
2794 /* Just print these values for now. */
2795 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2796 cap_low = 0x%x, cap_high = 0x%x\n",
2797 (unsigned int)client_unix_major,
2798 (unsigned int)client_unix_minor,
2799 (unsigned int)client_unix_cap_low,
2800 (unsigned int)client_unix_cap_high ));
2802 /* Here is where we must switch to posix pathname processing... */
2803 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2804 lp_set_posix_pathnames();
2805 mangle_change_to_posix();
2808 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2809 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2810 /* Client that knows how to do posix locks,
2811 * but not posix open/mkdir operations. Set a
2812 * default type for read/write checks. */
2814 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2817 break;
2819 case SMB_FS_QUOTA_INFORMATION:
2821 files_struct *fsp = NULL;
2822 SMB_NTQUOTA_STRUCT quotas;
2824 ZERO_STRUCT(quotas);
2826 /* access check */
2827 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2828 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2829 lp_servicename(SNUM(conn)),conn->user));
2830 return ERROR_DOS(ERRSRV,ERRaccess);
2833 /* note: normaly there're 48 bytes,
2834 * but we didn't use the last 6 bytes for now
2835 * --metze
2837 fsp = file_fsp(params,0);
2838 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2839 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2840 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2843 if (total_data < 42) {
2844 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2845 total_data));
2846 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2849 /* unknown_1 24 NULL bytes in pdata*/
2851 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2852 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2853 #ifdef LARGE_SMB_OFF_T
2854 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2855 #else /* LARGE_SMB_OFF_T */
2856 if ((IVAL(pdata,28) != 0)&&
2857 ((quotas.softlim != 0xFFFFFFFF)||
2858 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2859 /* more than 32 bits? */
2860 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2862 #endif /* LARGE_SMB_OFF_T */
2864 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2865 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2866 #ifdef LARGE_SMB_OFF_T
2867 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2868 #else /* LARGE_SMB_OFF_T */
2869 if ((IVAL(pdata,36) != 0)&&
2870 ((quotas.hardlim != 0xFFFFFFFF)||
2871 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2872 /* more than 32 bits? */
2873 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2875 #endif /* LARGE_SMB_OFF_T */
2877 /* quota_flags 2 bytes **/
2878 quotas.qflags = SVAL(pdata,40);
2880 /* unknown_2 6 NULL bytes follow*/
2882 /* now set the quotas */
2883 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2884 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2885 return ERROR_DOS(ERRSRV,ERRerror);
2888 break;
2890 default:
2891 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2892 info_level));
2893 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2894 break;
2898 * sending this reply works fine,
2899 * but I'm not sure it's the same
2900 * like windows do...
2901 * --metze
2903 outsize = set_message(outbuf,10,0,True);
2905 return outsize;
2908 #if defined(HAVE_POSIX_ACLS)
2909 /****************************************************************************
2910 Utility function to count the number of entries in a POSIX acl.
2911 ****************************************************************************/
2913 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2915 unsigned int ace_count = 0;
2916 int entry_id = SMB_ACL_FIRST_ENTRY;
2917 SMB_ACL_ENTRY_T entry;
2919 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2920 /* get_next... */
2921 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2922 entry_id = SMB_ACL_NEXT_ENTRY;
2924 ace_count++;
2926 return ace_count;
2929 /****************************************************************************
2930 Utility function to marshall a POSIX acl into wire format.
2931 ****************************************************************************/
2933 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2935 int entry_id = SMB_ACL_FIRST_ENTRY;
2936 SMB_ACL_ENTRY_T entry;
2938 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2939 SMB_ACL_TAG_T tagtype;
2940 SMB_ACL_PERMSET_T permset;
2941 unsigned char perms = 0;
2942 unsigned int own_grp;
2944 /* get_next... */
2945 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2946 entry_id = SMB_ACL_NEXT_ENTRY;
2949 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2950 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2951 return False;
2954 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2955 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2956 return False;
2959 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2960 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2961 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2963 SCVAL(pdata,1,perms);
2965 switch (tagtype) {
2966 case SMB_ACL_USER_OBJ:
2967 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2968 own_grp = (unsigned int)pst->st_uid;
2969 SIVAL(pdata,2,own_grp);
2970 SIVAL(pdata,6,0);
2971 break;
2972 case SMB_ACL_USER:
2974 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2975 if (!puid) {
2976 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2978 own_grp = (unsigned int)*puid;
2979 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2980 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2981 SIVAL(pdata,2,own_grp);
2982 SIVAL(pdata,6,0);
2983 break;
2985 case SMB_ACL_GROUP_OBJ:
2986 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2987 own_grp = (unsigned int)pst->st_gid;
2988 SIVAL(pdata,2,own_grp);
2989 SIVAL(pdata,6,0);
2990 break;
2991 case SMB_ACL_GROUP:
2993 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2994 if (!pgid) {
2995 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2997 own_grp = (unsigned int)*pgid;
2998 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2999 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3000 SIVAL(pdata,2,own_grp);
3001 SIVAL(pdata,6,0);
3002 break;
3004 case SMB_ACL_MASK:
3005 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3006 SIVAL(pdata,2,0xFFFFFFFF);
3007 SIVAL(pdata,6,0xFFFFFFFF);
3008 break;
3009 case SMB_ACL_OTHER:
3010 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3011 SIVAL(pdata,2,0xFFFFFFFF);
3012 SIVAL(pdata,6,0xFFFFFFFF);
3013 break;
3014 default:
3015 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3016 return False;
3018 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3021 return True;
3023 #endif
3025 /****************************************************************************
3026 Store the FILE_UNIX_BASIC info.
3027 ****************************************************************************/
3029 static char *store_file_unix_basic(connection_struct *conn,
3030 char *pdata,
3031 files_struct *fsp,
3032 const SMB_STRUCT_STAT *psbuf)
3034 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3035 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3037 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3038 pdata += 8;
3040 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3041 pdata += 8;
3043 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3044 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3045 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3046 pdata += 24;
3048 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3049 SIVAL(pdata,4,0);
3050 pdata += 8;
3052 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3053 SIVAL(pdata,4,0);
3054 pdata += 8;
3056 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3057 pdata += 4;
3059 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3060 SIVAL(pdata,4,0);
3061 pdata += 8;
3063 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3064 SIVAL(pdata,4,0);
3065 pdata += 8;
3067 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3068 pdata += 8;
3070 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3071 SIVAL(pdata,4,0);
3072 pdata += 8;
3074 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3075 SIVAL(pdata,4,0);
3076 pdata += 8;
3078 return pdata;
3081 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3082 * the chflags(2) (or equivalent) flags.
3084 * XXX: this really should be behind the VFS interface. To do this, we would
3085 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3086 * Each VFS module could then implement it's own mapping as appropriate for the
3087 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3089 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3090 info2_flags_map[] =
3092 #ifdef UF_NODUMP
3093 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3094 #endif
3096 #ifdef UF_IMMUTABLE
3097 { UF_IMMUTABLE, EXT_IMMUTABLE },
3098 #endif
3100 #ifdef UF_APPEND
3101 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3102 #endif
3104 #ifdef UF_HIDDEN
3105 { UF_HIDDEN, EXT_HIDDEN },
3106 #endif
3108 /* Do not remove. We need to guarantee that this array has at least one
3109 * entry to build on HP-UX.
3111 { 0, 0 }
3115 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3116 uint32 *smb_fflags, uint32 *smb_fmask)
3118 #ifdef HAVE_STAT_ST_FLAGS
3119 int i;
3121 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3122 *smb_fmask |= info2_flags_map[i].smb_fflag;
3123 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3124 *smb_fflags |= info2_flags_map[i].smb_fflag;
3127 #endif /* HAVE_STAT_ST_FLAGS */
3130 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3131 const uint32 smb_fflags,
3132 const uint32 smb_fmask,
3133 int *stat_fflags)
3135 #ifdef HAVE_STAT_ST_FLAGS
3136 uint32 max_fmask = 0;
3137 int i;
3139 *stat_fflags = psbuf->st_flags;
3141 /* For each flags requested in smb_fmask, check the state of the
3142 * corresponding flag in smb_fflags and set or clear the matching
3143 * stat flag.
3146 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3147 max_fmask |= info2_flags_map[i].smb_fflag;
3148 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3149 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3150 *stat_fflags |= info2_flags_map[i].stat_fflag;
3151 } else {
3152 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3157 /* If smb_fmask is asking to set any bits that are not supported by
3158 * our flag mappings, we should fail.
3160 if ((smb_fmask & max_fmask) != smb_fmask) {
3161 return False;
3164 return True;
3165 #else
3166 return False;
3167 #endif /* HAVE_STAT_ST_FLAGS */
3171 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3172 * of file flags and birth (create) time.
3174 static char *store_file_unix_basic_info2(connection_struct *conn,
3175 char *pdata,
3176 files_struct *fsp,
3177 const SMB_STRUCT_STAT *psbuf)
3179 uint32 file_flags = 0;
3180 uint32 flags_mask = 0;
3182 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3184 /* Create (birth) time 64 bit */
3185 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3186 pdata += 8;
3188 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3189 SIVAL(pdata, 0, file_flags); /* flags */
3190 SIVAL(pdata, 4, flags_mask); /* mask */
3191 pdata += 8;
3193 return pdata;
3196 /****************************************************************************
3197 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3198 file name or file id).
3199 ****************************************************************************/
3201 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3202 unsigned int tran_call,
3203 char **pparams, int total_params, char **ppdata, int total_data,
3204 unsigned int max_data_bytes)
3206 char *params = *pparams;
3207 char *pdata = *ppdata;
3208 uint16 info_level;
3209 int mode=0;
3210 int nlink;
3211 SMB_OFF_T file_size=0;
3212 SMB_BIG_UINT allocation_size=0;
3213 unsigned int data_size = 0;
3214 unsigned int param_size = 2;
3215 SMB_STRUCT_STAT sbuf;
3216 pstring fname, dos_fname;
3217 char *fullpathname;
3218 char *base_name;
3219 char *p;
3220 SMB_OFF_T pos = 0;
3221 BOOL delete_pending = False;
3222 int len;
3223 time_t create_time, mtime, atime;
3224 struct timespec create_time_ts, mtime_ts, atime_ts;
3225 files_struct *fsp = NULL;
3226 TALLOC_CTX *data_ctx = NULL;
3227 struct ea_list *ea_list = NULL;
3228 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3229 char *lock_data = NULL;
3231 if (!params)
3232 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3234 ZERO_STRUCT(sbuf);
3236 if (tran_call == TRANSACT2_QFILEINFO) {
3237 if (total_params < 4) {
3238 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3241 fsp = file_fsp(params,0);
3242 info_level = SVAL(params,2);
3244 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3246 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3247 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3250 if(fsp && (fsp->fake_file_handle)) {
3252 * This is actually for the QUOTA_FAKE_FILE --metze
3255 pstrcpy(fname, fsp->fsp_name);
3256 /* We know this name is ok, it's already passed the checks. */
3258 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3260 * This is actually a QFILEINFO on a directory
3261 * handle (returned from an NT SMB). NT5.0 seems
3262 * to do this call. JRA.
3264 /* We know this name is ok, it's already passed the checks. */
3265 pstrcpy(fname, fsp->fsp_name);
3267 if (INFO_LEVEL_IS_UNIX(info_level)) {
3268 /* Always do lstat for UNIX calls. */
3269 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3270 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3271 return UNIXERROR(ERRDOS,ERRbadpath);
3273 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3274 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3275 return UNIXERROR(ERRDOS,ERRbadpath);
3278 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3279 } else {
3281 * Original code - this is an open file.
3283 CHECK_FSP(fsp,conn);
3285 pstrcpy(fname, fsp->fsp_name);
3286 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3287 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3288 return(UNIXERROR(ERRDOS,ERRbadfid));
3290 pos = fsp->fh->position_information;
3291 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3292 access_mask = fsp->access_mask;
3294 } else {
3295 NTSTATUS status = NT_STATUS_OK;
3297 /* qpathinfo */
3298 if (total_params < 7) {
3299 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3302 info_level = SVAL(params,0);
3304 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3306 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3307 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3310 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3311 if (!NT_STATUS_IS_OK(status)) {
3312 return ERROR_NT(status);
3315 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3316 if (!NT_STATUS_IS_OK(status)) {
3317 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3318 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3320 return ERROR_NT(status);
3323 status = unix_convert(conn, fname, False, NULL, &sbuf);
3324 if (!NT_STATUS_IS_OK(status)) {
3325 return ERROR_NT(status);
3327 status = check_name(conn, fname);
3328 if (!NT_STATUS_IS_OK(status)) {
3329 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3330 return ERROR_NT(status);
3333 if (INFO_LEVEL_IS_UNIX(info_level)) {
3334 /* Always do lstat for UNIX calls. */
3335 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3336 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3337 return UNIXERROR(ERRDOS,ERRbadpath);
3339 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3340 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3341 return UNIXERROR(ERRDOS,ERRbadpath);
3344 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3345 if (delete_pending) {
3346 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3350 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3351 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3354 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3355 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3357 p = strrchr_m(fname,'/');
3358 if (!p)
3359 base_name = fname;
3360 else
3361 base_name = p+1;
3363 mode = dos_mode(conn,fname,&sbuf);
3364 if (!mode)
3365 mode = FILE_ATTRIBUTE_NORMAL;
3367 nlink = sbuf.st_nlink;
3369 if (nlink && (mode&aDIR)) {
3370 nlink = 1;
3373 if ((nlink > 0) && delete_pending) {
3374 nlink -= 1;
3377 fullpathname = fname;
3378 if (!(mode & aDIR))
3379 file_size = get_file_size(sbuf);
3381 /* Pull out any data sent here before we realloc. */
3382 switch (info_level) {
3383 case SMB_INFO_QUERY_EAS_FROM_LIST:
3385 /* Pull any EA list from the data portion. */
3386 uint32 ea_size;
3388 if (total_data < 4) {
3389 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3391 ea_size = IVAL(pdata,0);
3393 if (total_data > 0 && ea_size != total_data) {
3394 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3395 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3396 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3399 if (!lp_ea_support(SNUM(conn))) {
3400 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3403 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3404 return ERROR_NT(NT_STATUS_NO_MEMORY);
3407 /* Pull out the list of names. */
3408 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3409 if (!ea_list) {
3410 talloc_destroy(data_ctx);
3411 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3413 break;
3416 case SMB_QUERY_POSIX_LOCK:
3418 if (fsp == NULL || fsp->fh->fd == -1) {
3419 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3422 if (total_data != POSIX_LOCK_DATA_SIZE) {
3423 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3426 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3427 return ERROR_NT(NT_STATUS_NO_MEMORY);
3430 /* Copy the lock range data. */
3431 lock_data = (char *)TALLOC_MEMDUP(
3432 data_ctx, pdata, total_data);
3433 if (!lock_data) {
3434 talloc_destroy(data_ctx);
3435 return ERROR_NT(NT_STATUS_NO_MEMORY);
3438 default:
3439 break;
3442 *pparams = (char *)SMB_REALLOC(*pparams,2);
3443 if (*pparams == NULL) {
3444 talloc_destroy(data_ctx);
3445 return ERROR_NT(NT_STATUS_NO_MEMORY);
3447 params = *pparams;
3448 SSVAL(params,0,0);
3449 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3450 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3451 if (*ppdata == NULL ) {
3452 talloc_destroy(data_ctx);
3453 return ERROR_NT(NT_STATUS_NO_MEMORY);
3455 pdata = *ppdata;
3457 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3458 mtime_ts = get_mtimespec(&sbuf);
3459 atime_ts = get_atimespec(&sbuf);
3461 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3463 if (fsp) {
3464 if (!null_timespec(fsp->pending_modtime)) {
3465 /* the pending modtime overrides the current modtime */
3466 mtime_ts = fsp->pending_modtime;
3468 } else {
3469 /* Do we have this path open ? */
3470 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3471 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3472 /* the pending modtime overrides the current modtime */
3473 mtime_ts = fsp1->pending_modtime;
3475 if (fsp1 && fsp1->initial_allocation_size) {
3476 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3480 if (lp_dos_filetime_resolution(SNUM(conn))) {
3481 dos_filetime_timespec(&create_time_ts);
3482 dos_filetime_timespec(&mtime_ts);
3483 dos_filetime_timespec(&atime_ts);
3486 create_time = convert_timespec_to_time_t(create_time_ts);
3487 mtime = convert_timespec_to_time_t(mtime_ts);
3488 atime = convert_timespec_to_time_t(atime_ts);
3490 /* NT expects the name to be in an exact form of the *full*
3491 filename. See the trans2 torture test */
3492 if (strequal(base_name,".")) {
3493 pstrcpy(dos_fname, "\\");
3494 } else {
3495 pstr_sprintf(dos_fname, "\\%s", fname);
3496 string_replace(dos_fname, '/', '\\');
3499 switch (info_level) {
3500 case SMB_INFO_STANDARD:
3501 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3502 data_size = 22;
3503 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3504 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3505 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3506 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3507 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3508 SSVAL(pdata,l1_attrFile,mode);
3509 break;
3511 case SMB_INFO_QUERY_EA_SIZE:
3513 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3514 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3515 data_size = 26;
3516 srv_put_dos_date2(pdata,0,create_time);
3517 srv_put_dos_date2(pdata,4,atime);
3518 srv_put_dos_date2(pdata,8,mtime); /* write time */
3519 SIVAL(pdata,12,(uint32)file_size);
3520 SIVAL(pdata,16,(uint32)allocation_size);
3521 SSVAL(pdata,20,mode);
3522 SIVAL(pdata,22,ea_size);
3523 break;
3526 case SMB_INFO_IS_NAME_VALID:
3527 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3528 if (tran_call == TRANSACT2_QFILEINFO) {
3529 /* os/2 needs this ? really ?*/
3530 return ERROR_DOS(ERRDOS,ERRbadfunc);
3532 data_size = 0;
3533 param_size = 0;
3534 break;
3536 case SMB_INFO_QUERY_EAS_FROM_LIST:
3538 size_t total_ea_len = 0;
3539 struct ea_list *ea_file_list = NULL;
3541 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3543 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3544 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3546 if (!ea_list || (total_ea_len > data_size)) {
3547 talloc_destroy(data_ctx);
3548 data_size = 4;
3549 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3550 break;
3553 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3554 talloc_destroy(data_ctx);
3555 break;
3558 case SMB_INFO_QUERY_ALL_EAS:
3560 /* We have data_size bytes to put EA's into. */
3561 size_t total_ea_len = 0;
3563 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3565 data_ctx = talloc_init("ea_ctx");
3566 if (!data_ctx) {
3567 return ERROR_NT(NT_STATUS_NO_MEMORY);
3570 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3571 if (!ea_list || (total_ea_len > data_size)) {
3572 talloc_destroy(data_ctx);
3573 data_size = 4;
3574 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3575 break;
3578 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3579 talloc_destroy(data_ctx);
3580 break;
3583 case SMB_FILE_BASIC_INFORMATION:
3584 case SMB_QUERY_FILE_BASIC_INFO:
3586 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3587 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3588 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3589 } else {
3590 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3591 data_size = 40;
3592 SIVAL(pdata,36,0);
3594 put_long_date_timespec(pdata,create_time_ts);
3595 put_long_date_timespec(pdata+8,atime_ts);
3596 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3597 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3598 SIVAL(pdata,32,mode);
3600 DEBUG(5,("SMB_QFBI - "));
3601 DEBUG(5,("create: %s ", ctime(&create_time)));
3602 DEBUG(5,("access: %s ", ctime(&atime)));
3603 DEBUG(5,("write: %s ", ctime(&mtime)));
3604 DEBUG(5,("change: %s ", ctime(&mtime)));
3605 DEBUG(5,("mode: %x\n", mode));
3606 break;
3608 case SMB_FILE_STANDARD_INFORMATION:
3609 case SMB_QUERY_FILE_STANDARD_INFO:
3611 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3612 data_size = 24;
3613 SOFF_T(pdata,0,allocation_size);
3614 SOFF_T(pdata,8,file_size);
3615 SIVAL(pdata,16,nlink);
3616 SCVAL(pdata,20,delete_pending?1:0);
3617 SCVAL(pdata,21,(mode&aDIR)?1:0);
3618 SSVAL(pdata,22,0); /* Padding. */
3619 break;
3621 case SMB_FILE_EA_INFORMATION:
3622 case SMB_QUERY_FILE_EA_INFO:
3624 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3625 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3626 data_size = 4;
3627 SIVAL(pdata,0,ea_size);
3628 break;
3631 /* Get the 8.3 name - used if NT SMB was negotiated. */
3632 case SMB_QUERY_FILE_ALT_NAME_INFO:
3633 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3635 pstring short_name;
3637 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3638 pstrcpy(short_name,base_name);
3639 /* Mangle if not already 8.3 */
3640 if(!mangle_is_8_3(short_name, True, conn->params)) {
3641 mangle_map(short_name,True,True,conn->params);
3643 len = srvstr_push(outbuf, pdata+4, short_name, max_data_bytes - 4, STR_UNICODE);
3644 data_size = 4 + len;
3645 SIVAL(pdata,0,len);
3646 break;
3649 case SMB_QUERY_FILE_NAME_INFO:
3651 this must be *exactly* right for ACLs on mapped drives to work
3653 len = srvstr_push(outbuf, pdata+4, dos_fname, max_data_bytes - 4, STR_UNICODE);
3654 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3655 data_size = 4 + len;
3656 SIVAL(pdata,0,len);
3657 break;
3659 case SMB_FILE_ALLOCATION_INFORMATION:
3660 case SMB_QUERY_FILE_ALLOCATION_INFO:
3661 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3662 data_size = 8;
3663 SOFF_T(pdata,0,allocation_size);
3664 break;
3666 case SMB_FILE_END_OF_FILE_INFORMATION:
3667 case SMB_QUERY_FILE_END_OF_FILEINFO:
3668 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3669 data_size = 8;
3670 SOFF_T(pdata,0,file_size);
3671 break;
3673 case SMB_QUERY_FILE_ALL_INFO:
3674 case SMB_FILE_ALL_INFORMATION:
3676 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3677 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3678 put_long_date_timespec(pdata,create_time_ts);
3679 put_long_date_timespec(pdata+8,atime_ts);
3680 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3681 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3682 SIVAL(pdata,32,mode);
3683 SIVAL(pdata,36,0); /* padding. */
3684 pdata += 40;
3685 SOFF_T(pdata,0,allocation_size);
3686 SOFF_T(pdata,8,file_size);
3687 SIVAL(pdata,16,nlink);
3688 SCVAL(pdata,20,delete_pending);
3689 SCVAL(pdata,21,(mode&aDIR)?1:0);
3690 SSVAL(pdata,22,0);
3691 pdata += 24;
3692 SIVAL(pdata,0,ea_size);
3693 pdata += 4; /* EA info */
3694 len = srvstr_push(outbuf, pdata+4, dos_fname, max_data_bytes - (pdata+4 - *ppdata), STR_UNICODE);
3695 SIVAL(pdata,0,len);
3696 pdata += 4 + len;
3697 data_size = PTR_DIFF(pdata,(*ppdata));
3698 break;
3700 case SMB_FILE_INTERNAL_INFORMATION:
3701 /* This should be an index number - looks like
3702 dev/ino to me :-)
3704 I think this causes us to fail the IFSKIT
3705 BasicFileInformationTest. -tpot */
3707 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3708 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3709 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3710 data_size = 8;
3711 break;
3713 case SMB_FILE_ACCESS_INFORMATION:
3714 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3715 SIVAL(pdata,0,access_mask);
3716 data_size = 4;
3717 break;
3719 case SMB_FILE_NAME_INFORMATION:
3720 /* Pathname with leading '\'. */
3722 size_t byte_len;
3723 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3724 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3725 SIVAL(pdata,0,byte_len);
3726 data_size = 4 + byte_len;
3727 break;
3730 case SMB_FILE_DISPOSITION_INFORMATION:
3731 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3732 data_size = 1;
3733 SCVAL(pdata,0,delete_pending);
3734 break;
3736 case SMB_FILE_POSITION_INFORMATION:
3737 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3738 data_size = 8;
3739 SOFF_T(pdata,0,pos);
3740 break;
3742 case SMB_FILE_MODE_INFORMATION:
3743 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3744 SIVAL(pdata,0,mode);
3745 data_size = 4;
3746 break;
3748 case SMB_FILE_ALIGNMENT_INFORMATION:
3749 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3750 SIVAL(pdata,0,0); /* No alignment needed. */
3751 data_size = 4;
3752 break;
3754 #if 0
3756 * NT4 server just returns "invalid query" to this - if we try to answer
3757 * it then NTws gets a BSOD! (tridge).
3758 * W2K seems to want this. JRA.
3760 case SMB_QUERY_FILE_STREAM_INFO:
3761 #endif
3762 case SMB_FILE_STREAM_INFORMATION:
3763 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3764 if (mode & aDIR) {
3765 data_size = 0;
3766 } else {
3767 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3768 SIVAL(pdata,0,0); /* ??? */
3769 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3770 SOFF_T(pdata,8,file_size);
3771 SOFF_T(pdata,16,allocation_size);
3772 data_size = 24 + byte_len;
3774 break;
3776 case SMB_QUERY_COMPRESSION_INFO:
3777 case SMB_FILE_COMPRESSION_INFORMATION:
3778 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3779 SOFF_T(pdata,0,file_size);
3780 SIVAL(pdata,8,0); /* ??? */
3781 SIVAL(pdata,12,0); /* ??? */
3782 data_size = 16;
3783 break;
3785 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3786 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3787 put_long_date_timespec(pdata,create_time_ts);
3788 put_long_date_timespec(pdata+8,atime_ts);
3789 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3790 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3791 SOFF_T(pdata,32,allocation_size);
3792 SOFF_T(pdata,40,file_size);
3793 SIVAL(pdata,48,mode);
3794 SIVAL(pdata,52,0); /* ??? */
3795 data_size = 56;
3796 break;
3798 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3799 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3800 SIVAL(pdata,0,mode);
3801 SIVAL(pdata,4,0);
3802 data_size = 8;
3803 break;
3806 * CIFS UNIX Extensions.
3809 case SMB_QUERY_FILE_UNIX_BASIC:
3811 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3812 data_size = PTR_DIFF(pdata,(*ppdata));
3815 int i;
3816 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3818 for (i=0; i<100; i++)
3819 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3820 DEBUG(4,("\n"));
3823 break;
3825 case SMB_QUERY_FILE_UNIX_INFO2:
3827 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3828 data_size = PTR_DIFF(pdata,(*ppdata));
3831 int i;
3832 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3834 for (i=0; i<100; i++)
3835 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3836 DEBUG(4,("\n"));
3839 break;
3841 case SMB_QUERY_FILE_UNIX_LINK:
3843 pstring buffer;
3845 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3846 #ifdef S_ISLNK
3847 if(!S_ISLNK(sbuf.st_mode))
3848 return(UNIXERROR(ERRSRV,ERRbadlink));
3849 #else
3850 return(UNIXERROR(ERRDOS,ERRbadlink));
3851 #endif
3852 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3853 if (len == -1)
3854 return(UNIXERROR(ERRDOS,ERRnoaccess));
3855 buffer[len] = 0;
3856 len = srvstr_push(outbuf, pdata, buffer, max_data_bytes, STR_TERMINATE);
3857 pdata += len;
3858 data_size = PTR_DIFF(pdata,(*ppdata));
3860 break;
3863 #if defined(HAVE_POSIX_ACLS)
3864 case SMB_QUERY_POSIX_ACL:
3866 SMB_ACL_T file_acl = NULL;
3867 SMB_ACL_T def_acl = NULL;
3868 uint16 num_file_acls = 0;
3869 uint16 num_def_acls = 0;
3871 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3872 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3873 } else {
3874 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3877 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3878 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3879 fname ));
3880 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3883 if (S_ISDIR(sbuf.st_mode)) {
3884 if (fsp && fsp->is_directory) {
3885 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3886 } else {
3887 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3889 def_acl = free_empty_sys_acl(conn, def_acl);
3892 num_file_acls = count_acl_entries(conn, file_acl);
3893 num_def_acls = count_acl_entries(conn, def_acl);
3895 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3896 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3897 data_size,
3898 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3899 SMB_POSIX_ACL_HEADER_SIZE) ));
3900 if (file_acl) {
3901 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3903 if (def_acl) {
3904 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3906 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3909 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3910 SSVAL(pdata,2,num_file_acls);
3911 SSVAL(pdata,4,num_def_acls);
3912 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3913 if (file_acl) {
3914 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3916 if (def_acl) {
3917 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3919 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3921 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3922 if (file_acl) {
3923 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3925 if (def_acl) {
3926 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3928 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3931 if (file_acl) {
3932 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3934 if (def_acl) {
3935 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3937 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3938 break;
3940 #endif
3943 case SMB_QUERY_POSIX_LOCK:
3945 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3946 SMB_BIG_UINT count;
3947 SMB_BIG_UINT offset;
3948 uint32 lock_pid;
3949 enum brl_type lock_type;
3951 if (total_data != POSIX_LOCK_DATA_SIZE) {
3952 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3955 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3956 case POSIX_LOCK_TYPE_READ:
3957 lock_type = READ_LOCK;
3958 break;
3959 case POSIX_LOCK_TYPE_WRITE:
3960 lock_type = WRITE_LOCK;
3961 break;
3962 case POSIX_LOCK_TYPE_UNLOCK:
3963 default:
3964 /* There's no point in asking for an unlock... */
3965 talloc_destroy(data_ctx);
3966 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3969 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3970 #if defined(HAVE_LONGLONG)
3971 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3972 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3973 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3974 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3975 #else /* HAVE_LONGLONG */
3976 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3977 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3978 #endif /* HAVE_LONGLONG */
3980 status = query_lock(fsp,
3981 &lock_pid,
3982 &count,
3983 &offset,
3984 &lock_type,
3985 POSIX_LOCK);
3987 if (ERROR_WAS_LOCK_DENIED(status)) {
3988 /* Here we need to report who has it locked... */
3989 data_size = POSIX_LOCK_DATA_SIZE;
3991 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3992 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3993 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3994 #if defined(HAVE_LONGLONG)
3995 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3996 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3997 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3998 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3999 #else /* HAVE_LONGLONG */
4000 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4001 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4002 #endif /* HAVE_LONGLONG */
4004 } else if (NT_STATUS_IS_OK(status)) {
4005 /* For success we just return a copy of what we sent
4006 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4007 data_size = POSIX_LOCK_DATA_SIZE;
4008 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4009 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4010 } else {
4011 return ERROR_NT(status);
4013 break;
4016 default:
4017 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4020 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4022 return(-1);
4025 /****************************************************************************
4026 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4027 code.
4028 ****************************************************************************/
4030 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4032 SMB_STRUCT_STAT sbuf1, sbuf2;
4033 pstring last_component_oldname;
4034 pstring last_component_newname;
4035 NTSTATUS status = NT_STATUS_OK;
4037 ZERO_STRUCT(sbuf1);
4038 ZERO_STRUCT(sbuf2);
4040 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4041 if (!NT_STATUS_IS_OK(status)) {
4042 return status;
4045 status = check_name(conn, oldname);
4046 if (!NT_STATUS_IS_OK(status)) {
4047 return status;
4050 /* source must already exist. */
4051 if (!VALID_STAT(sbuf1)) {
4052 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4055 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4056 if (!NT_STATUS_IS_OK(status)) {
4057 return status;
4060 status = check_name(conn, newname);
4061 if (!NT_STATUS_IS_OK(status)) {
4062 return status;
4065 /* Disallow if newname already exists. */
4066 if (VALID_STAT(sbuf2)) {
4067 return NT_STATUS_OBJECT_NAME_COLLISION;
4070 /* No links from a directory. */
4071 if (S_ISDIR(sbuf1.st_mode)) {
4072 return NT_STATUS_FILE_IS_A_DIRECTORY;
4075 /* Ensure this is within the share. */
4076 status = reduce_name(conn, oldname);
4077 if (!NT_STATUS_IS_OK(status)) {
4078 return status;
4081 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4083 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4084 status = map_nt_error_from_unix(errno);
4085 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4086 nt_errstr(status), newname, oldname));
4089 return status;
4092 /****************************************************************************
4093 Deal with setting the time from any of the setfilepathinfo functions.
4094 ****************************************************************************/
4096 static NTSTATUS smb_set_file_time(connection_struct *conn,
4097 files_struct *fsp,
4098 const char *fname,
4099 const SMB_STRUCT_STAT *psbuf,
4100 struct timespec ts[2])
4102 uint32 action =
4103 FILE_NOTIFY_CHANGE_LAST_ACCESS
4104 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4107 if (!VALID_STAT(*psbuf)) {
4108 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4111 /* get some defaults (no modifications) if any info is zero or -1. */
4112 if (null_timespec(ts[0])) {
4113 ts[0] = get_atimespec(psbuf);
4114 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4117 if (null_timespec(ts[1])) {
4118 ts[1] = get_mtimespec(psbuf);
4119 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4122 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4123 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4126 * Try and set the times of this file if
4127 * they are different from the current values.
4131 struct timespec mts = get_mtimespec(psbuf);
4132 struct timespec ats = get_atimespec(psbuf);
4133 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4134 return NT_STATUS_OK;
4138 if(fsp != NULL) {
4140 * This was a setfileinfo on an open file.
4141 * NT does this a lot. We also need to
4142 * set the time here, as it can be read by
4143 * FindFirst/FindNext and with the patch for bug #2045
4144 * in smbd/fileio.c it ensures that this timestamp is
4145 * kept sticky even after a write. We save the request
4146 * away and will set it on file close and after a write. JRA.
4149 if (!null_timespec(ts[1])) {
4150 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4151 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4152 fsp_set_pending_modtime(fsp, ts[1]);
4156 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4158 if(file_ntimes(conn, fname, ts)!=0) {
4159 return map_nt_error_from_unix(errno);
4161 if (action != 0) {
4162 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4164 return NT_STATUS_OK;
4167 /****************************************************************************
4168 Deal with setting the dosmode from any of the setfilepathinfo functions.
4169 ****************************************************************************/
4171 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4172 const char *fname,
4173 SMB_STRUCT_STAT *psbuf,
4174 uint32 dosmode)
4176 if (!VALID_STAT(*psbuf)) {
4177 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4180 if (dosmode) {
4181 if (S_ISDIR(psbuf->st_mode)) {
4182 dosmode |= aDIR;
4183 } else {
4184 dosmode &= ~aDIR;
4188 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4190 /* check the mode isn't different, before changing it */
4191 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4193 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4194 fname, (unsigned int)dosmode ));
4196 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4197 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4198 fname, strerror(errno)));
4199 return map_nt_error_from_unix(errno);
4202 return NT_STATUS_OK;
4205 /****************************************************************************
4206 Deal with setting the size from any of the setfilepathinfo functions.
4207 ****************************************************************************/
4209 static NTSTATUS smb_set_file_size(connection_struct *conn,
4210 files_struct *fsp,
4211 const char *fname,
4212 SMB_STRUCT_STAT *psbuf,
4213 SMB_OFF_T size)
4215 NTSTATUS status = NT_STATUS_OK;
4216 files_struct *new_fsp = NULL;
4218 if (!VALID_STAT(*psbuf)) {
4219 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4222 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4224 if (size == get_file_size(*psbuf)) {
4225 return NT_STATUS_OK;
4228 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4229 fname, (double)size ));
4231 if (fsp && fsp->fh->fd != -1) {
4232 /* Handle based call. */
4233 if (vfs_set_filelen(fsp, size) == -1) {
4234 return map_nt_error_from_unix(errno);
4236 return NT_STATUS_OK;
4239 status = open_file_ntcreate(conn, fname, psbuf,
4240 FILE_WRITE_DATA,
4241 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4242 FILE_OPEN,
4244 FILE_ATTRIBUTE_NORMAL,
4245 FORCE_OPLOCK_BREAK_TO_NONE,
4246 NULL, &new_fsp);
4248 if (!NT_STATUS_IS_OK(status)) {
4249 /* NB. We check for open_was_deferred in the caller. */
4250 return status;
4253 if (vfs_set_filelen(new_fsp, size) == -1) {
4254 status = map_nt_error_from_unix(errno);
4255 close_file(new_fsp,NORMAL_CLOSE);
4256 return status;
4259 close_file(new_fsp,NORMAL_CLOSE);
4260 return NT_STATUS_OK;
4263 /****************************************************************************
4264 Deal with SMB_INFO_SET_EA.
4265 ****************************************************************************/
4267 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4268 const char *pdata,
4269 int total_data,
4270 files_struct *fsp,
4271 const char *fname)
4273 struct ea_list *ea_list = NULL;
4274 TALLOC_CTX *ctx = NULL;
4275 NTSTATUS status = NT_STATUS_OK;
4277 if (total_data < 10) {
4279 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4280 length. They seem to have no effect. Bug #3212. JRA */
4282 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4283 /* We're done. We only get EA info in this call. */
4284 return NT_STATUS_OK;
4287 return NT_STATUS_INVALID_PARAMETER;
4290 if (IVAL(pdata,0) > total_data) {
4291 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4292 IVAL(pdata,0), (unsigned int)total_data));
4293 return NT_STATUS_INVALID_PARAMETER;
4296 ctx = talloc_init("SMB_INFO_SET_EA");
4297 if (!ctx) {
4298 return NT_STATUS_NO_MEMORY;
4300 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4301 if (!ea_list) {
4302 talloc_destroy(ctx);
4303 return NT_STATUS_INVALID_PARAMETER;
4305 status = set_ea(conn, fsp, fname, ea_list);
4306 talloc_destroy(ctx);
4308 return status;
4311 /****************************************************************************
4312 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4313 ****************************************************************************/
4315 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4316 const char *pdata,
4317 int total_data,
4318 files_struct *fsp,
4319 const char *fname,
4320 SMB_STRUCT_STAT *psbuf)
4322 NTSTATUS status = NT_STATUS_OK;
4323 BOOL delete_on_close;
4324 uint32 dosmode = 0;
4326 if (total_data < 1) {
4327 return NT_STATUS_INVALID_PARAMETER;
4330 if (fsp == NULL) {
4331 return NT_STATUS_INVALID_HANDLE;
4334 delete_on_close = (CVAL(pdata,0) ? True : False);
4335 dosmode = dos_mode(conn, fname, psbuf);
4337 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4338 "delete_on_close = %u\n",
4339 fsp->fsp_name,
4340 (unsigned int)dosmode,
4341 (unsigned int)delete_on_close ));
4343 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4345 if (!NT_STATUS_IS_OK(status)) {
4346 return status;
4349 /* The set is across all open files on this dev/inode pair. */
4350 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4351 return NT_STATUS_ACCESS_DENIED;
4353 return NT_STATUS_OK;
4356 /****************************************************************************
4357 Deal with SMB_FILE_POSITION_INFORMATION.
4358 ****************************************************************************/
4360 static NTSTATUS smb_file_position_information(connection_struct *conn,
4361 const char *pdata,
4362 int total_data,
4363 files_struct *fsp)
4365 SMB_BIG_UINT position_information;
4367 if (total_data < 8) {
4368 return NT_STATUS_INVALID_PARAMETER;
4371 if (fsp == NULL) {
4372 /* Ignore on pathname based set. */
4373 return NT_STATUS_OK;
4376 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4377 #ifdef LARGE_SMB_OFF_T
4378 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4379 #else /* LARGE_SMB_OFF_T */
4380 if (IVAL(pdata,4) != 0) {
4381 /* more than 32 bits? */
4382 return NT_STATUS_INVALID_PARAMETER;
4384 #endif /* LARGE_SMB_OFF_T */
4386 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4387 fsp->fsp_name, (double)position_information ));
4388 fsp->fh->position_information = position_information;
4389 return NT_STATUS_OK;
4392 /****************************************************************************
4393 Deal with SMB_FILE_MODE_INFORMATION.
4394 ****************************************************************************/
4396 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4397 const char *pdata,
4398 int total_data)
4400 uint32 mode;
4402 if (total_data < 4) {
4403 return NT_STATUS_INVALID_PARAMETER;
4405 mode = IVAL(pdata,0);
4406 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4407 return NT_STATUS_INVALID_PARAMETER;
4409 return NT_STATUS_OK;
4412 /****************************************************************************
4413 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4414 ****************************************************************************/
4416 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4417 char *inbuf,
4418 const char *pdata,
4419 int total_data,
4420 const char *fname)
4422 pstring link_target;
4423 const char *newname = fname;
4424 NTSTATUS status = NT_STATUS_OK;
4426 /* Set a symbolic link. */
4427 /* Don't allow this if follow links is false. */
4429 if (total_data == 0) {
4430 return NT_STATUS_INVALID_PARAMETER;
4433 if (!lp_symlinks(SNUM(conn))) {
4434 return NT_STATUS_ACCESS_DENIED;
4437 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4439 /* !widelinks forces the target path to be within the share. */
4440 /* This means we can interpret the target as a pathname. */
4441 if (!lp_widelinks(SNUM(conn))) {
4442 pstring rel_name;
4443 char *last_dirp = NULL;
4445 if (*link_target == '/') {
4446 /* No absolute paths allowed. */
4447 return NT_STATUS_ACCESS_DENIED;
4449 pstrcpy(rel_name, newname);
4450 last_dirp = strrchr_m(rel_name, '/');
4451 if (last_dirp) {
4452 last_dirp[1] = '\0';
4453 } else {
4454 pstrcpy(rel_name, "./");
4456 pstrcat(rel_name, link_target);
4458 status = check_name(conn, rel_name);
4459 if (!NT_STATUS_IS_OK(status)) {
4460 return status;
4464 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4465 newname, link_target ));
4467 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4468 return map_nt_error_from_unix(errno);
4471 return NT_STATUS_OK;
4474 /****************************************************************************
4475 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4476 ****************************************************************************/
4478 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4479 char *inbuf,
4480 char *outbuf,
4481 const char *pdata,
4482 int total_data,
4483 pstring fname)
4485 pstring oldname;
4486 NTSTATUS status = NT_STATUS_OK;
4488 /* Set a hard link. */
4489 if (total_data == 0) {
4490 return NT_STATUS_INVALID_PARAMETER;
4493 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4494 if (!NT_STATUS_IS_OK(status)) {
4495 return status;
4498 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4499 if (!NT_STATUS_IS_OK(status)) {
4500 return status;
4503 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4504 fname, oldname));
4506 return hardlink_internals(conn, oldname, fname);
4509 /****************************************************************************
4510 Deal with SMB_FILE_RENAME_INFORMATION.
4511 ****************************************************************************/
4513 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4514 char *inbuf,
4515 char *outbuf,
4516 const char *pdata,
4517 int total_data,
4518 files_struct *fsp,
4519 pstring fname)
4521 BOOL overwrite;
4522 /* uint32 root_fid; */ /* Not used */
4523 uint32 len;
4524 pstring newname;
4525 pstring base_name;
4526 BOOL dest_has_wcard = False;
4527 NTSTATUS status = NT_STATUS_OK;
4528 char *p;
4530 if (total_data < 13) {
4531 return NT_STATUS_INVALID_PARAMETER;
4534 overwrite = (CVAL(pdata,0) ? True : False);
4535 /* root_fid = IVAL(pdata,4); */
4536 len = IVAL(pdata,8);
4538 if (len > (total_data - 12) || (len == 0)) {
4539 return NT_STATUS_INVALID_PARAMETER;
4542 srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4543 if (!NT_STATUS_IS_OK(status)) {
4544 return status;
4547 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4548 if (!NT_STATUS_IS_OK(status)) {
4549 return status;
4552 /* Check the new name has no '/' characters. */
4553 if (strchr_m(newname, '/')) {
4554 return NT_STATUS_NOT_SUPPORTED;
4557 /* Create the base directory. */
4558 pstrcpy(base_name, fname);
4559 p = strrchr_m(base_name, '/');
4560 if (p) {
4561 p[1] = '\0';
4562 } else {
4563 pstrcpy(base_name, "./");
4565 /* Append the new name. */
4566 pstrcat(base_name, newname);
4568 if (fsp) {
4569 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4570 fsp->fnum, fsp->fsp_name, base_name ));
4571 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4572 } else {
4573 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4574 fname, newname ));
4575 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4578 return status;
4581 /****************************************************************************
4582 Deal with SMB_SET_POSIX_ACL.
4583 ****************************************************************************/
4585 #if defined(HAVE_POSIX_ACLS)
4586 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4587 const char *pdata,
4588 int total_data,
4589 files_struct *fsp,
4590 const char *fname,
4591 SMB_STRUCT_STAT *psbuf)
4593 uint16 posix_acl_version;
4594 uint16 num_file_acls;
4595 uint16 num_def_acls;
4596 BOOL valid_file_acls = True;
4597 BOOL valid_def_acls = True;
4599 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4600 return NT_STATUS_INVALID_PARAMETER;
4602 posix_acl_version = SVAL(pdata,0);
4603 num_file_acls = SVAL(pdata,2);
4604 num_def_acls = SVAL(pdata,4);
4606 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4607 valid_file_acls = False;
4608 num_file_acls = 0;
4611 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4612 valid_def_acls = False;
4613 num_def_acls = 0;
4616 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4617 return NT_STATUS_INVALID_PARAMETER;
4620 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4621 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4622 return NT_STATUS_INVALID_PARAMETER;
4625 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4626 fname ? fname : fsp->fsp_name,
4627 (unsigned int)num_file_acls,
4628 (unsigned int)num_def_acls));
4630 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4631 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4632 return map_nt_error_from_unix(errno);
4635 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4636 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4637 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4638 return map_nt_error_from_unix(errno);
4640 return NT_STATUS_OK;
4642 #endif
4644 /****************************************************************************
4645 Deal with SMB_SET_POSIX_LOCK.
4646 ****************************************************************************/
4648 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4649 char *inbuf,
4650 int length,
4651 const char *pdata,
4652 int total_data,
4653 files_struct *fsp)
4655 SMB_BIG_UINT count;
4656 SMB_BIG_UINT offset;
4657 uint32 lock_pid;
4658 BOOL blocking_lock = False;
4659 enum brl_type lock_type;
4660 NTSTATUS status = NT_STATUS_OK;
4662 if (fsp == NULL || fsp->fh->fd == -1) {
4663 return NT_STATUS_INVALID_HANDLE;
4666 if (total_data != POSIX_LOCK_DATA_SIZE) {
4667 return NT_STATUS_INVALID_PARAMETER;
4670 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4671 case POSIX_LOCK_TYPE_READ:
4672 lock_type = READ_LOCK;
4673 break;
4674 case POSIX_LOCK_TYPE_WRITE:
4675 /* Return the right POSIX-mappable error code for files opened read-only. */
4676 if (!fsp->can_write) {
4677 return NT_STATUS_INVALID_HANDLE;
4679 lock_type = WRITE_LOCK;
4680 break;
4681 case POSIX_LOCK_TYPE_UNLOCK:
4682 lock_type = UNLOCK_LOCK;
4683 break;
4684 default:
4685 return NT_STATUS_INVALID_PARAMETER;
4688 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4689 blocking_lock = False;
4690 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4691 blocking_lock = True;
4692 } else {
4693 return NT_STATUS_INVALID_PARAMETER;
4696 if (!lp_blocking_locks(SNUM(conn))) {
4697 blocking_lock = False;
4700 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4701 #if defined(HAVE_LONGLONG)
4702 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4703 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4704 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4705 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4706 #else /* HAVE_LONGLONG */
4707 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4708 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4709 #endif /* HAVE_LONGLONG */
4711 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4712 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4713 fsp->fsp_name,
4714 (unsigned int)lock_type,
4715 (unsigned int)lock_pid,
4716 (double)count,
4717 (double)offset ));
4719 if (lock_type == UNLOCK_LOCK) {
4720 status = do_unlock(fsp,
4721 lock_pid,
4722 count,
4723 offset,
4724 POSIX_LOCK);
4725 } else {
4726 uint32 block_smbpid;
4728 struct byte_range_lock *br_lck = do_lock(fsp,
4729 lock_pid,
4730 count,
4731 offset,
4732 lock_type,
4733 POSIX_LOCK,
4734 blocking_lock,
4735 &status,
4736 &block_smbpid);
4738 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4740 * A blocking lock was requested. Package up
4741 * this smb into a queued request and push it
4742 * onto the blocking lock queue.
4744 if(push_blocking_lock_request(br_lck,
4745 inbuf, length,
4746 fsp,
4747 -1, /* infinite timeout. */
4749 lock_pid,
4750 lock_type,
4751 POSIX_LOCK,
4752 offset,
4753 count,
4754 block_smbpid)) {
4755 TALLOC_FREE(br_lck);
4756 return status;
4759 TALLOC_FREE(br_lck);
4762 return status;
4765 /****************************************************************************
4766 Deal with SMB_INFO_STANDARD.
4767 ****************************************************************************/
4769 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4770 const char *pdata,
4771 int total_data,
4772 files_struct *fsp,
4773 const char *fname,
4774 const SMB_STRUCT_STAT *psbuf)
4776 struct timespec ts[2];
4778 if (total_data < 12) {
4779 return NT_STATUS_INVALID_PARAMETER;
4782 /* access time */
4783 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4784 /* write time */
4785 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4787 DEBUG(10,("smb_set_info_standard: file %s\n",
4788 fname ? fname : fsp->fsp_name ));
4790 return smb_set_file_time(conn,
4791 fsp,
4792 fname,
4793 psbuf,
4794 ts);
4797 /****************************************************************************
4798 Deal with SMB_SET_FILE_BASIC_INFO.
4799 ****************************************************************************/
4801 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4802 const char *pdata,
4803 int total_data,
4804 files_struct *fsp,
4805 const char *fname,
4806 SMB_STRUCT_STAT *psbuf)
4808 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4809 struct timespec write_time;
4810 struct timespec changed_time;
4811 uint32 dosmode = 0;
4812 struct timespec ts[2];
4813 NTSTATUS status = NT_STATUS_OK;
4815 if (total_data < 36) {
4816 return NT_STATUS_INVALID_PARAMETER;
4819 /* Set the attributes */
4820 dosmode = IVAL(pdata,32);
4821 status = smb_set_file_dosmode(conn,
4822 fname,
4823 psbuf,
4824 dosmode);
4825 if (!NT_STATUS_IS_OK(status)) {
4826 return status;
4829 /* Ignore create time at offset pdata. */
4831 /* access time */
4832 ts[0] = interpret_long_date(pdata+8);
4834 write_time = interpret_long_date(pdata+16);
4835 changed_time = interpret_long_date(pdata+24);
4837 /* mtime */
4838 ts[1] = timespec_min(&write_time, &changed_time);
4840 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4841 ts[1] = write_time;
4844 /* Prefer a defined time to an undefined one. */
4845 if (null_timespec(ts[1])) {
4846 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4849 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4850 fname ? fname : fsp->fsp_name ));
4852 return smb_set_file_time(conn,
4853 fsp,
4854 fname,
4855 psbuf,
4856 ts);
4859 /****************************************************************************
4860 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4861 ****************************************************************************/
4863 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4864 const char *pdata,
4865 int total_data,
4866 files_struct *fsp,
4867 const char *fname,
4868 SMB_STRUCT_STAT *psbuf)
4870 SMB_BIG_UINT allocation_size = 0;
4871 NTSTATUS status = NT_STATUS_OK;
4872 files_struct *new_fsp = NULL;
4874 if (!VALID_STAT(*psbuf)) {
4875 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4878 if (total_data < 8) {
4879 return NT_STATUS_INVALID_PARAMETER;
4882 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4883 #ifdef LARGE_SMB_OFF_T
4884 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4885 #else /* LARGE_SMB_OFF_T */
4886 if (IVAL(pdata,4) != 0) {
4887 /* more than 32 bits? */
4888 return NT_STATUS_INVALID_PARAMETER;
4890 #endif /* LARGE_SMB_OFF_T */
4892 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4893 fname, (double)allocation_size ));
4895 if (allocation_size) {
4896 allocation_size = smb_roundup(conn, allocation_size);
4899 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4900 fname, (double)allocation_size ));
4902 if (fsp && fsp->fh->fd != -1) {
4903 /* Open file handle. */
4904 /* Only change if needed. */
4905 if (allocation_size != get_file_size(*psbuf)) {
4906 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4907 return map_nt_error_from_unix(errno);
4910 /* But always update the time. */
4911 if (null_timespec(fsp->pending_modtime)) {
4913 * This is equivalent to a write. Ensure it's seen immediately
4914 * if there are no pending writes.
4916 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
4918 return NT_STATUS_OK;
4921 /* Pathname or stat or directory file. */
4923 status = open_file_ntcreate(conn, fname, psbuf,
4924 FILE_WRITE_DATA,
4925 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4926 FILE_OPEN,
4928 FILE_ATTRIBUTE_NORMAL,
4929 FORCE_OPLOCK_BREAK_TO_NONE,
4930 NULL, &new_fsp);
4932 if (!NT_STATUS_IS_OK(status)) {
4933 /* NB. We check for open_was_deferred in the caller. */
4934 return status;
4937 /* Only change if needed. */
4938 if (allocation_size != get_file_size(*psbuf)) {
4939 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4940 status = map_nt_error_from_unix(errno);
4941 close_file(new_fsp,NORMAL_CLOSE);
4942 return status;
4946 /* Changing the allocation size should set the last mod time. */
4947 /* Don't need to call set_filetime as this will be flushed on
4948 * close. */
4950 fsp_set_pending_modtime(new_fsp, timespec_current());
4952 close_file(new_fsp,NORMAL_CLOSE);
4953 return NT_STATUS_OK;
4956 /****************************************************************************
4957 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4958 ****************************************************************************/
4960 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4961 const char *pdata,
4962 int total_data,
4963 files_struct *fsp,
4964 const char *fname,
4965 SMB_STRUCT_STAT *psbuf)
4967 SMB_OFF_T size;
4969 if (total_data < 8) {
4970 return NT_STATUS_INVALID_PARAMETER;
4973 size = IVAL(pdata,0);
4974 #ifdef LARGE_SMB_OFF_T
4975 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4976 #else /* LARGE_SMB_OFF_T */
4977 if (IVAL(pdata,4) != 0) {
4978 /* more than 32 bits? */
4979 return NT_STATUS_INVALID_PARAMETER;
4981 #endif /* LARGE_SMB_OFF_T */
4982 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4983 "file %s to %.0f\n", fname, (double)size ));
4985 return smb_set_file_size(conn,
4986 fsp,
4987 fname,
4988 psbuf,
4989 size);
4992 /****************************************************************************
4993 Allow a UNIX info mknod.
4994 ****************************************************************************/
4996 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4997 const char *pdata,
4998 int total_data,
4999 const char *fname,
5000 SMB_STRUCT_STAT *psbuf)
5002 uint32 file_type = IVAL(pdata,56);
5003 #if defined(HAVE_MAKEDEV)
5004 uint32 dev_major = IVAL(pdata,60);
5005 uint32 dev_minor = IVAL(pdata,68);
5006 #endif
5007 SMB_DEV_T dev = (SMB_DEV_T)0;
5008 uint32 raw_unixmode = IVAL(pdata,84);
5009 NTSTATUS status;
5010 mode_t unixmode;
5012 if (total_data < 100) {
5013 return NT_STATUS_INVALID_PARAMETER;
5016 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5017 if (!NT_STATUS_IS_OK(status)) {
5018 return status;
5021 #if defined(HAVE_MAKEDEV)
5022 dev = makedev(dev_major, dev_minor);
5023 #endif
5025 switch (file_type) {
5026 #if defined(S_IFIFO)
5027 case UNIX_TYPE_FIFO:
5028 unixmode |= S_IFIFO;
5029 break;
5030 #endif
5031 #if defined(S_IFSOCK)
5032 case UNIX_TYPE_SOCKET:
5033 unixmode |= S_IFSOCK;
5034 break;
5035 #endif
5036 #if defined(S_IFCHR)
5037 case UNIX_TYPE_CHARDEV:
5038 unixmode |= S_IFCHR;
5039 break;
5040 #endif
5041 #if defined(S_IFBLK)
5042 case UNIX_TYPE_BLKDEV:
5043 unixmode |= S_IFBLK;
5044 break;
5045 #endif
5046 default:
5047 return NT_STATUS_INVALID_PARAMETER;
5050 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5051 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5053 /* Ok - do the mknod. */
5054 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5055 return map_nt_error_from_unix(errno);
5058 /* If any of the other "set" calls fail we
5059 * don't want to end up with a half-constructed mknod.
5062 if (lp_inherit_perms(SNUM(conn))) {
5063 inherit_access_acl(
5064 conn, parent_dirname(fname),
5065 fname, unixmode);
5068 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5069 status = map_nt_error_from_unix(errno);
5070 SMB_VFS_UNLINK(conn,fname);
5071 return status;
5073 return NT_STATUS_OK;
5076 /****************************************************************************
5077 Deal with SMB_SET_FILE_UNIX_BASIC.
5078 ****************************************************************************/
5080 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5081 const char *pdata,
5082 int total_data,
5083 files_struct *fsp,
5084 const char *fname,
5085 SMB_STRUCT_STAT *psbuf)
5087 struct timespec ts[2];
5088 uint32 raw_unixmode;
5089 mode_t unixmode;
5090 SMB_OFF_T size = 0;
5091 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5092 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5093 NTSTATUS status = NT_STATUS_OK;
5094 BOOL delete_on_fail = False;
5095 enum perm_type ptype;
5097 if (total_data < 100) {
5098 return NT_STATUS_INVALID_PARAMETER;
5101 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5102 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5103 size=IVAL(pdata,0); /* first 8 Bytes are size */
5104 #ifdef LARGE_SMB_OFF_T
5105 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5106 #else /* LARGE_SMB_OFF_T */
5107 if (IVAL(pdata,4) != 0) {
5108 /* more than 32 bits? */
5109 return NT_STATUS_INVALID_PARAMETER;
5111 #endif /* LARGE_SMB_OFF_T */
5114 ts[0] = interpret_long_date(pdata+24); /* access_time */
5115 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5116 set_owner = (uid_t)IVAL(pdata,40);
5117 set_grp = (gid_t)IVAL(pdata,48);
5118 raw_unixmode = IVAL(pdata,84);
5120 if (VALID_STAT(*psbuf)) {
5121 if (S_ISDIR(psbuf->st_mode)) {
5122 ptype = PERM_EXISTING_DIR;
5123 } else {
5124 ptype = PERM_EXISTING_FILE;
5126 } else {
5127 ptype = PERM_NEW_FILE;
5130 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5131 if (!NT_STATUS_IS_OK(status)) {
5132 return status;
5135 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5136 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5137 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5139 if (!VALID_STAT(*psbuf)) {
5141 * The only valid use of this is to create character and block
5142 * devices, and named pipes. This is deprecated (IMHO) and
5143 * a new info level should be used for mknod. JRA.
5146 status = smb_unix_mknod(conn,
5147 pdata,
5148 total_data,
5149 fname,
5150 psbuf);
5151 if (!NT_STATUS_IS_OK(status)) {
5152 return status;
5155 /* Ensure we don't try and change anything else. */
5156 raw_unixmode = SMB_MODE_NO_CHANGE;
5157 size = get_file_size(*psbuf);
5158 ts[0] = get_atimespec(psbuf);
5159 ts[1] = get_mtimespec(psbuf);
5161 * We continue here as we might want to change the
5162 * owner uid/gid.
5164 delete_on_fail = True;
5167 #if 1
5168 /* Horrible backwards compatibility hack as an old server bug
5169 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5170 * */
5172 if (!size) {
5173 size = get_file_size(*psbuf);
5175 #endif
5178 * Deal with the UNIX specific mode set.
5181 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5182 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5183 (unsigned int)unixmode, fname ));
5184 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5185 return map_nt_error_from_unix(errno);
5190 * Deal with the UNIX specific uid set.
5193 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5194 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5195 (unsigned int)set_owner, fname ));
5196 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5197 status = map_nt_error_from_unix(errno);
5198 if (delete_on_fail) {
5199 SMB_VFS_UNLINK(conn,fname);
5201 return status;
5206 * Deal with the UNIX specific gid set.
5209 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5210 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5211 (unsigned int)set_owner, fname ));
5212 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5213 status = map_nt_error_from_unix(errno);
5214 if (delete_on_fail) {
5215 SMB_VFS_UNLINK(conn,fname);
5217 return status;
5221 /* Deal with any size changes. */
5223 status = smb_set_file_size(conn,
5224 fsp,
5225 fname,
5226 psbuf,
5227 size);
5228 if (!NT_STATUS_IS_OK(status)) {
5229 return status;
5232 /* Deal with any time changes. */
5234 return smb_set_file_time(conn,
5235 fsp,
5236 fname,
5237 psbuf,
5238 ts);
5241 /****************************************************************************
5242 Deal with SMB_SET_FILE_UNIX_INFO2.
5243 ****************************************************************************/
5245 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5246 const char *pdata,
5247 int total_data,
5248 files_struct *fsp,
5249 const char *fname,
5250 SMB_STRUCT_STAT *psbuf)
5252 NTSTATUS status;
5253 uint32 smb_fflags;
5254 uint32 smb_fmask;
5256 if (total_data < 116) {
5257 return NT_STATUS_INVALID_PARAMETER;
5260 /* Start by setting all the fields that are common between UNIX_BASIC
5261 * and UNIX_INFO2.
5263 status = smb_set_file_unix_basic(conn, pdata, total_data,
5264 fsp, fname, psbuf);
5265 if (!NT_STATUS_IS_OK(status)) {
5266 return status;
5269 smb_fflags = IVAL(pdata, 108);
5270 smb_fmask = IVAL(pdata, 112);
5272 /* NB: We should only attempt to alter the file flags if the client
5273 * sends a non-zero mask.
5275 if (smb_fmask != 0) {
5276 int stat_fflags = 0;
5278 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5279 &stat_fflags)) {
5280 /* Client asked to alter a flag we don't understand. */
5281 return NT_STATUS_INVALID_PARAMETER;
5284 if (fsp && fsp->fh->fd != -1) {
5285 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5286 return NT_STATUS_NOT_SUPPORTED;
5287 } else {
5288 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5289 return map_nt_error_from_unix(errno);
5294 /* XXX: need to add support for changing the create_time here. You
5295 * can do this for paths on Darwin with setattrlist(2). The right way
5296 * to hook this up is probably by extending the VFS utimes interface.
5299 return NT_STATUS_OK;
5302 /****************************************************************************
5303 Create a directory with POSIX semantics.
5304 ****************************************************************************/
5306 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5307 char **ppdata,
5308 int total_data,
5309 const char *fname,
5310 SMB_STRUCT_STAT *psbuf,
5311 int *pdata_return_size)
5313 NTSTATUS status = NT_STATUS_OK;
5314 uint32 raw_unixmode = 0;
5315 uint32 mod_unixmode = 0;
5316 mode_t unixmode = (mode_t)0;
5317 files_struct *fsp = NULL;
5318 uint16 info_level_return = 0;
5319 int info;
5320 char *pdata = *ppdata;
5322 if (total_data < 18) {
5323 return NT_STATUS_INVALID_PARAMETER;
5326 raw_unixmode = IVAL(pdata,8);
5327 /* Next 4 bytes are not yet defined. */
5329 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5330 if (!NT_STATUS_IS_OK(status)) {
5331 return status;
5334 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5336 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5337 fname, (unsigned int)unixmode ));
5339 status = open_directory(conn,
5340 fname,
5341 psbuf,
5342 FILE_READ_ATTRIBUTES, /* Just a stat open */
5343 FILE_SHARE_NONE, /* Ignored for stat opens */
5344 FILE_CREATE,
5346 mod_unixmode,
5347 &info,
5348 &fsp);
5350 if (NT_STATUS_IS_OK(status)) {
5351 close_file(fsp, NORMAL_CLOSE);
5354 info_level_return = SVAL(pdata,16);
5356 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5357 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5358 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5359 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5360 } else {
5361 *pdata_return_size = 12;
5364 /* Realloc the data size */
5365 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5366 if (*ppdata == NULL) {
5367 *pdata_return_size = 0;
5368 return NT_STATUS_NO_MEMORY;
5370 pdata = *ppdata;
5372 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5373 SSVAL(pdata,2,0); /* No fnum. */
5374 SIVAL(pdata,4,info); /* Was directory created. */
5376 switch (info_level_return) {
5377 case SMB_QUERY_FILE_UNIX_BASIC:
5378 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5379 SSVAL(pdata,10,0); /* Padding. */
5380 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5381 break;
5382 case SMB_QUERY_FILE_UNIX_INFO2:
5383 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5384 SSVAL(pdata,10,0); /* Padding. */
5385 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5386 break;
5387 default:
5388 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5389 SSVAL(pdata,10,0); /* Padding. */
5390 break;
5393 return status;
5396 /****************************************************************************
5397 Open/Create a file with POSIX semantics.
5398 ****************************************************************************/
5400 static NTSTATUS smb_posix_open(connection_struct *conn,
5401 char **ppdata,
5402 int total_data,
5403 const char *fname,
5404 SMB_STRUCT_STAT *psbuf,
5405 int *pdata_return_size)
5407 BOOL extended_oplock_granted = False;
5408 char *pdata = *ppdata;
5409 uint32 flags = 0;
5410 uint32 wire_open_mode = 0;
5411 uint32 raw_unixmode = 0;
5412 uint32 mod_unixmode = 0;
5413 uint32 create_disp = 0;
5414 uint32 access_mask = 0;
5415 uint32 create_options = 0;
5416 NTSTATUS status = NT_STATUS_OK;
5417 mode_t unixmode = (mode_t)0;
5418 files_struct *fsp = NULL;
5419 int oplock_request = 0;
5420 int info = 0;
5421 uint16 info_level_return = 0;
5423 if (total_data < 18) {
5424 return NT_STATUS_INVALID_PARAMETER;
5427 flags = IVAL(pdata,0);
5428 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5429 if (oplock_request) {
5430 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5433 wire_open_mode = IVAL(pdata,4);
5435 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5436 return smb_posix_mkdir(conn,
5437 ppdata,
5438 total_data,
5439 fname,
5440 psbuf,
5441 pdata_return_size);
5444 switch (wire_open_mode & SMB_ACCMODE) {
5445 case SMB_O_RDONLY:
5446 access_mask = FILE_READ_DATA;
5447 break;
5448 case SMB_O_WRONLY:
5449 access_mask = FILE_WRITE_DATA;
5450 break;
5451 case SMB_O_RDWR:
5452 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5453 break;
5454 default:
5455 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5456 (unsigned int)wire_open_mode ));
5457 return NT_STATUS_INVALID_PARAMETER;
5460 wire_open_mode &= ~SMB_ACCMODE;
5462 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5463 create_disp = FILE_CREATE;
5464 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5465 create_disp = FILE_OVERWRITE_IF;
5466 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5467 create_disp = FILE_OPEN_IF;
5468 } else {
5469 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5470 (unsigned int)wire_open_mode ));
5471 return NT_STATUS_INVALID_PARAMETER;
5474 raw_unixmode = IVAL(pdata,8);
5475 /* Next 4 bytes are not yet defined. */
5477 status = unix_perms_from_wire(conn,
5478 psbuf,
5479 raw_unixmode,
5480 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5481 &unixmode);
5483 if (!NT_STATUS_IS_OK(status)) {
5484 return status;
5487 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5489 if (wire_open_mode & SMB_O_SYNC) {
5490 create_options |= FILE_WRITE_THROUGH;
5492 if (wire_open_mode & SMB_O_APPEND) {
5493 access_mask |= FILE_APPEND_DATA;
5495 if (wire_open_mode & SMB_O_DIRECT) {
5496 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5499 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5500 fname,
5501 (unsigned int)wire_open_mode,
5502 (unsigned int)unixmode ));
5504 status = open_file_ntcreate(conn,
5505 fname,
5506 psbuf,
5507 access_mask,
5508 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5509 create_disp,
5510 0, /* no create options yet. */
5511 mod_unixmode,
5512 oplock_request,
5513 &info,
5514 &fsp);
5516 if (!NT_STATUS_IS_OK(status)) {
5517 return status;
5520 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5521 extended_oplock_granted = True;
5524 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5525 extended_oplock_granted = True;
5528 info_level_return = SVAL(pdata,16);
5530 /* Allocate the correct return size. */
5532 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5533 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5534 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5535 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5536 } else {
5537 *pdata_return_size = 12;
5540 /* Realloc the data size */
5541 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5542 if (*ppdata == NULL) {
5543 close_file(fsp,ERROR_CLOSE);
5544 *pdata_return_size = 0;
5545 return NT_STATUS_NO_MEMORY;
5547 pdata = *ppdata;
5549 if (extended_oplock_granted) {
5550 if (flags & REQUEST_BATCH_OPLOCK) {
5551 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5552 } else {
5553 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5555 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5556 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5557 } else {
5558 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5561 SSVAL(pdata,2,fsp->fnum);
5562 SIVAL(pdata,4,info); /* Was file created etc. */
5564 switch (info_level_return) {
5565 case SMB_QUERY_FILE_UNIX_BASIC:
5566 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5567 SSVAL(pdata,10,0); /* padding. */
5568 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5569 break;
5570 case SMB_QUERY_FILE_UNIX_INFO2:
5571 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5572 SSVAL(pdata,10,0); /* padding. */
5573 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5574 break;
5575 default:
5576 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5577 SSVAL(pdata,10,0); /* padding. */
5578 break;
5580 return NT_STATUS_OK;
5583 /****************************************************************************
5584 Delete a file with POSIX semantics.
5585 ****************************************************************************/
5587 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5588 const char *pdata,
5589 int total_data,
5590 const char *fname,
5591 SMB_STRUCT_STAT *psbuf)
5593 NTSTATUS status = NT_STATUS_OK;
5594 files_struct *fsp = NULL;
5595 uint16 flags = 0;
5596 char del = 1;
5597 int info = 0;
5598 int i;
5599 struct share_mode_lock *lck = NULL;
5601 if (total_data < 2) {
5602 return NT_STATUS_INVALID_PARAMETER;
5605 flags = SVAL(pdata,0);
5607 if (!VALID_STAT(*psbuf)) {
5608 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5611 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5612 !VALID_STAT_OF_DIR(*psbuf)) {
5613 return NT_STATUS_NOT_A_DIRECTORY;
5616 DEBUG(10,("smb_posix_unlink: %s %s\n",
5617 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5618 fname));
5620 if (VALID_STAT_OF_DIR(*psbuf)) {
5621 status = open_directory(conn,
5622 fname,
5623 psbuf,
5624 DELETE_ACCESS,
5625 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5626 FILE_OPEN,
5628 FILE_FLAG_POSIX_SEMANTICS|0777,
5629 &info,
5630 &fsp);
5631 } else {
5633 status = open_file_ntcreate(conn,
5634 fname,
5635 psbuf,
5636 DELETE_ACCESS,
5637 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5638 FILE_OPEN,
5640 FILE_FLAG_POSIX_SEMANTICS|0777,
5641 0, /* No oplock, but break existing ones. */
5642 &info,
5643 &fsp);
5646 if (!NT_STATUS_IS_OK(status)) {
5647 return status;
5651 * Don't lie to client. If we can't really delete due to
5652 * non-POSIX opens return SHARING_VIOLATION.
5655 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
5656 if (lck == NULL) {
5657 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5658 "lock for file %s\n", fsp->fsp_name));
5659 close_file(fsp, NORMAL_CLOSE);
5660 return NT_STATUS_INVALID_PARAMETER;
5664 * See if others still have the file open. If this is the case, then
5665 * don't delete. If all opens are POSIX delete we can set the delete
5666 * on close disposition.
5668 for (i=0; i<lck->num_share_modes; i++) {
5669 struct share_mode_entry *e = &lck->share_modes[i];
5670 if (is_valid_share_mode_entry(e)) {
5671 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5672 continue;
5674 /* Fail with sharing violation. */
5675 close_file(fsp, NORMAL_CLOSE);
5676 TALLOC_FREE(lck);
5677 return NT_STATUS_SHARING_VIOLATION;
5682 * Set the delete on close.
5684 status = smb_set_file_disposition_info(conn,
5685 &del,
5687 fsp,
5688 fname,
5689 psbuf);
5691 if (!NT_STATUS_IS_OK(status)) {
5692 close_file(fsp, NORMAL_CLOSE);
5693 TALLOC_FREE(lck);
5694 return status;
5696 TALLOC_FREE(lck);
5697 return close_file(fsp, NORMAL_CLOSE);
5700 /****************************************************************************
5701 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5702 ****************************************************************************/
5704 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5705 unsigned int tran_call,
5706 char **pparams, int total_params, char **ppdata, int total_data,
5707 unsigned int max_data_bytes)
5709 char *params = *pparams;
5710 char *pdata = *ppdata;
5711 uint16 info_level;
5712 SMB_STRUCT_STAT sbuf;
5713 pstring fname;
5714 files_struct *fsp = NULL;
5715 NTSTATUS status = NT_STATUS_OK;
5716 int data_return_size = 0;
5718 if (!params) {
5719 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5722 ZERO_STRUCT(sbuf);
5724 if (tran_call == TRANSACT2_SETFILEINFO) {
5725 if (total_params < 4) {
5726 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5729 fsp = file_fsp(params,0);
5730 info_level = SVAL(params,2);
5732 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5734 * This is actually a SETFILEINFO on a directory
5735 * handle (returned from an NT SMB). NT5.0 seems
5736 * to do this call. JRA.
5738 pstrcpy(fname, fsp->fsp_name);
5739 if (INFO_LEVEL_IS_UNIX(info_level)) {
5740 /* Always do lstat for UNIX calls. */
5741 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5742 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5743 return UNIXERROR(ERRDOS,ERRbadpath);
5745 } else {
5746 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5747 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5748 return UNIXERROR(ERRDOS,ERRbadpath);
5751 } else if (fsp && fsp->print_file) {
5753 * Doing a DELETE_ON_CLOSE should cancel a print job.
5755 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5756 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5758 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5760 SSVAL(params,0,0);
5761 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5762 return(-1);
5763 } else
5764 return (UNIXERROR(ERRDOS,ERRbadpath));
5765 } else {
5767 * Original code - this is an open file.
5769 CHECK_FSP(fsp,conn);
5771 pstrcpy(fname, fsp->fsp_name);
5773 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5774 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5775 return(UNIXERROR(ERRDOS,ERRbadfid));
5778 } else {
5779 /* set path info */
5780 if (total_params < 7) {
5781 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5784 info_level = SVAL(params,0);
5785 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5786 if (!NT_STATUS_IS_OK(status)) {
5787 return ERROR_NT(status);
5790 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5791 if (!NT_STATUS_IS_OK(status)) {
5792 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5793 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5795 return ERROR_NT(status);
5798 status = unix_convert(conn, fname, False, NULL, &sbuf);
5799 if (!NT_STATUS_IS_OK(status)) {
5800 return ERROR_NT(status);
5803 status = check_name(conn, fname);
5804 if (!NT_STATUS_IS_OK(status)) {
5805 return ERROR_NT(status);
5808 if (INFO_LEVEL_IS_UNIX(info_level)) {
5810 * For CIFS UNIX extensions the target name may not exist.
5813 /* Always do lstat for UNIX calls. */
5814 SMB_VFS_LSTAT(conn,fname,&sbuf);
5816 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5817 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5818 return UNIXERROR(ERRDOS,ERRbadpath);
5822 if (!CAN_WRITE(conn)) {
5823 return ERROR_DOS(ERRSRV,ERRaccess);
5826 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5827 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5830 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5831 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5833 /* Realloc the parameter size */
5834 *pparams = (char *)SMB_REALLOC(*pparams,2);
5835 if (*pparams == NULL) {
5836 return ERROR_NT(NT_STATUS_NO_MEMORY);
5838 params = *pparams;
5840 SSVAL(params,0,0);
5842 if (fsp && !null_timespec(fsp->pending_modtime)) {
5843 /* the pending modtime overrides the current modtime */
5844 set_mtimespec(&sbuf, fsp->pending_modtime);
5847 switch (info_level) {
5849 case SMB_INFO_STANDARD:
5851 status = smb_set_info_standard(conn,
5852 pdata,
5853 total_data,
5854 fsp,
5855 fname,
5856 &sbuf);
5857 break;
5860 case SMB_INFO_SET_EA:
5862 status = smb_info_set_ea(conn,
5863 pdata,
5864 total_data,
5865 fsp,
5866 fname);
5867 break;
5870 case SMB_SET_FILE_BASIC_INFO:
5871 case SMB_FILE_BASIC_INFORMATION:
5873 status = smb_set_file_basic_info(conn,
5874 pdata,
5875 total_data,
5876 fsp,
5877 fname,
5878 &sbuf);
5879 break;
5882 case SMB_FILE_ALLOCATION_INFORMATION:
5883 case SMB_SET_FILE_ALLOCATION_INFO:
5885 status = smb_set_file_allocation_info(conn,
5886 pdata,
5887 total_data,
5888 fsp,
5889 fname,
5890 &sbuf);
5891 break;
5894 case SMB_FILE_END_OF_FILE_INFORMATION:
5895 case SMB_SET_FILE_END_OF_FILE_INFO:
5897 status = smb_set_file_end_of_file_info(conn,
5898 pdata,
5899 total_data,
5900 fsp,
5901 fname,
5902 &sbuf);
5903 break;
5906 case SMB_FILE_DISPOSITION_INFORMATION:
5907 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5909 #if 0
5910 /* JRA - We used to just ignore this on a path ?
5911 * Shouldn't this be invalid level on a pathname
5912 * based call ?
5914 if (tran_call != TRANSACT2_SETFILEINFO) {
5915 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5917 #endif
5918 status = smb_set_file_disposition_info(conn,
5919 pdata,
5920 total_data,
5921 fsp,
5922 fname,
5923 &sbuf);
5924 break;
5927 case SMB_FILE_POSITION_INFORMATION:
5929 status = smb_file_position_information(conn,
5930 pdata,
5931 total_data,
5932 fsp);
5933 break;
5936 /* From tridge Samba4 :
5937 * MODE_INFORMATION in setfileinfo (I have no
5938 * idea what "mode information" on a file is - it takes a value of 0,
5939 * 2, 4 or 6. What could it be?).
5942 case SMB_FILE_MODE_INFORMATION:
5944 status = smb_file_mode_information(conn,
5945 pdata,
5946 total_data);
5947 break;
5951 * CIFS UNIX extensions.
5954 case SMB_SET_FILE_UNIX_BASIC:
5956 status = smb_set_file_unix_basic(conn,
5957 pdata,
5958 total_data,
5959 fsp,
5960 fname,
5961 &sbuf);
5962 break;
5965 case SMB_SET_FILE_UNIX_INFO2:
5967 status = smb_set_file_unix_info2(conn,
5968 pdata,
5969 total_data,
5970 fsp,
5971 fname,
5972 &sbuf);
5973 break;
5976 case SMB_SET_FILE_UNIX_LINK:
5978 if (tran_call != TRANSACT2_SETPATHINFO) {
5979 /* We must have a pathname for this. */
5980 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5982 status = smb_set_file_unix_link(conn,
5983 inbuf,
5984 pdata,
5985 total_data,
5986 fname);
5987 break;
5990 case SMB_SET_FILE_UNIX_HLINK:
5992 if (tran_call != TRANSACT2_SETPATHINFO) {
5993 /* We must have a pathname for this. */
5994 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5996 status = smb_set_file_unix_hlink(conn,
5997 inbuf,
5998 outbuf,
5999 pdata,
6000 total_data,
6001 fname);
6002 break;
6005 case SMB_FILE_RENAME_INFORMATION:
6007 status = smb_file_rename_information(conn,
6008 inbuf,
6009 outbuf,
6010 pdata,
6011 total_data,
6012 fsp,
6013 fname);
6014 break;
6017 #if defined(HAVE_POSIX_ACLS)
6018 case SMB_SET_POSIX_ACL:
6020 status = smb_set_posix_acl(conn,
6021 pdata,
6022 total_data,
6023 fsp,
6024 fname,
6025 &sbuf);
6026 break;
6028 #endif
6030 case SMB_SET_POSIX_LOCK:
6032 if (tran_call != TRANSACT2_SETFILEINFO) {
6033 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6035 status = smb_set_posix_lock(conn,
6036 inbuf,
6037 length,
6038 pdata,
6039 total_data,
6040 fsp);
6041 break;
6044 case SMB_POSIX_PATH_OPEN:
6046 if (tran_call != TRANSACT2_SETPATHINFO) {
6047 /* We must have a pathname for this. */
6048 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6051 status = smb_posix_open(conn,
6052 ppdata,
6053 total_data,
6054 fname,
6055 &sbuf,
6056 &data_return_size);
6057 break;
6060 case SMB_POSIX_PATH_UNLINK:
6062 if (tran_call != TRANSACT2_SETPATHINFO) {
6063 /* We must have a pathname for this. */
6064 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6067 status = smb_posix_unlink(conn,
6068 pdata,
6069 total_data,
6070 fname,
6071 &sbuf);
6072 break;
6075 default:
6076 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6080 if (!NT_STATUS_IS_OK(status)) {
6081 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6082 /* We have re-scheduled this call. */
6083 return -1;
6085 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6086 /* We have re-scheduled this call. */
6087 return -1;
6089 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6090 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6092 if (info_level == SMB_POSIX_PATH_OPEN) {
6093 return ERROR_OPEN(status);
6095 return ERROR_NT(status);
6098 SSVAL(params,0,0);
6099 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6101 return -1;
6104 /****************************************************************************
6105 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6106 ****************************************************************************/
6108 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6109 char **pparams, int total_params, char **ppdata, int total_data,
6110 unsigned int max_data_bytes)
6112 char *params = *pparams;
6113 char *pdata = *ppdata;
6114 pstring directory;
6115 SMB_STRUCT_STAT sbuf;
6116 NTSTATUS status = NT_STATUS_OK;
6117 struct ea_list *ea_list = NULL;
6119 if (!CAN_WRITE(conn))
6120 return ERROR_DOS(ERRSRV,ERRaccess);
6122 if (total_params < 5) {
6123 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6126 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6127 if (!NT_STATUS_IS_OK(status)) {
6128 return ERROR_NT(status);
6131 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6133 status = unix_convert(conn, directory, False, NULL, &sbuf);
6134 if (!NT_STATUS_IS_OK(status)) {
6135 return ERROR_NT(status);
6138 status = check_name(conn, directory);
6139 if (!NT_STATUS_IS_OK(status)) {
6140 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6141 return ERROR_NT(status);
6144 /* Any data in this call is an EA list. */
6145 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6146 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6150 * OS/2 workplace shell seems to send SET_EA requests of "null"
6151 * length (4 bytes containing IVAL 4).
6152 * They seem to have no effect. Bug #3212. JRA.
6155 if (total_data != 4) {
6156 if (total_data < 10) {
6157 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6160 if (IVAL(pdata,0) > total_data) {
6161 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6162 IVAL(pdata,0), (unsigned int)total_data));
6163 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6166 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6167 total_data - 4);
6168 if (!ea_list) {
6169 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6171 } else if (IVAL(pdata,0) != 4) {
6172 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6175 status = create_directory(conn, directory);
6177 if (!NT_STATUS_IS_OK(status)) {
6178 return ERROR_NT(status);
6181 /* Try and set any given EA. */
6182 if (ea_list) {
6183 status = set_ea(conn, NULL, directory, ea_list);
6184 if (!NT_STATUS_IS_OK(status)) {
6185 return ERROR_NT(status);
6189 /* Realloc the parameter and data sizes */
6190 *pparams = (char *)SMB_REALLOC(*pparams,2);
6191 if(*pparams == NULL) {
6192 return ERROR_NT(NT_STATUS_NO_MEMORY);
6194 params = *pparams;
6196 SSVAL(params,0,0);
6198 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6200 return(-1);
6203 /****************************************************************************
6204 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6205 We don't actually do this - we just send a null response.
6206 ****************************************************************************/
6208 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6209 char **pparams, int total_params, char **ppdata, int total_data,
6210 unsigned int max_data_bytes)
6212 static uint16 fnf_handle = 257;
6213 char *params = *pparams;
6214 uint16 info_level;
6216 if (total_params < 6) {
6217 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6220 info_level = SVAL(params,4);
6221 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6223 switch (info_level) {
6224 case 1:
6225 case 2:
6226 break;
6227 default:
6228 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6231 /* Realloc the parameter and data sizes */
6232 *pparams = (char *)SMB_REALLOC(*pparams,6);
6233 if (*pparams == NULL) {
6234 return ERROR_NT(NT_STATUS_NO_MEMORY);
6236 params = *pparams;
6238 SSVAL(params,0,fnf_handle);
6239 SSVAL(params,2,0); /* No changes */
6240 SSVAL(params,4,0); /* No EA errors */
6242 fnf_handle++;
6244 if(fnf_handle == 0)
6245 fnf_handle = 257;
6247 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6249 return(-1);
6252 /****************************************************************************
6253 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6254 changes). Currently this does nothing.
6255 ****************************************************************************/
6257 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6258 char **pparams, int total_params, char **ppdata, int total_data,
6259 unsigned int max_data_bytes)
6261 char *params = *pparams;
6263 DEBUG(3,("call_trans2findnotifynext\n"));
6265 /* Realloc the parameter and data sizes */
6266 *pparams = (char *)SMB_REALLOC(*pparams,4);
6267 if (*pparams == NULL) {
6268 return ERROR_NT(NT_STATUS_NO_MEMORY);
6270 params = *pparams;
6272 SSVAL(params,0,0); /* No changes */
6273 SSVAL(params,2,0); /* No EA errors */
6275 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6277 return(-1);
6280 /****************************************************************************
6281 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6282 ****************************************************************************/
6284 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6285 char **pparams, int total_params, char **ppdata, int total_data,
6286 unsigned int max_data_bytes)
6288 char *params = *pparams;
6289 pstring pathname;
6290 int reply_size = 0;
6291 int max_referral_level;
6292 NTSTATUS status = NT_STATUS_OK;
6294 DEBUG(10,("call_trans2getdfsreferral\n"));
6296 if (total_params < 3) {
6297 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6300 max_referral_level = SVAL(params,0);
6302 if(!lp_host_msdfs())
6303 return ERROR_DOS(ERRDOS,ERRbadfunc);
6305 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6306 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6307 return ERROR_NT(status);
6309 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6310 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6312 return(-1);
6315 #define LMCAT_SPL 0x53
6316 #define LMFUNC_GETJOBID 0x60
6318 /****************************************************************************
6319 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6320 ****************************************************************************/
6322 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6323 char **pparams, int total_params, char **ppdata, int total_data,
6324 unsigned int max_data_bytes)
6326 char *pdata = *ppdata;
6327 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6329 /* check for an invalid fid before proceeding */
6331 if (!fsp)
6332 return(ERROR_DOS(ERRDOS,ERRbadfid));
6334 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6335 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6336 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6337 if (*ppdata == NULL) {
6338 return ERROR_NT(NT_STATUS_NO_MEMORY);
6340 pdata = *ppdata;
6342 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6343 CAN ACCEPT THIS IN UNICODE. JRA. */
6345 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6346 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6347 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6348 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6349 return(-1);
6350 } else {
6351 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6352 return ERROR_DOS(ERRSRV,ERRerror);
6356 /****************************************************************************
6357 Reply to a SMBfindclose (stop trans2 directory search).
6358 ****************************************************************************/
6360 int reply_findclose(connection_struct *conn,
6361 char *inbuf,char *outbuf,int length,int bufsize)
6363 int outsize = 0;
6364 int dptr_num=SVALS(inbuf,smb_vwv0);
6365 START_PROFILE(SMBfindclose);
6367 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6369 dptr_close(&dptr_num);
6371 outsize = set_message(outbuf,0,0,False);
6373 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6375 END_PROFILE(SMBfindclose);
6376 return(outsize);
6379 /****************************************************************************
6380 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6381 ****************************************************************************/
6383 int reply_findnclose(connection_struct *conn,
6384 char *inbuf,char *outbuf,int length,int bufsize)
6386 int outsize = 0;
6387 int dptr_num= -1;
6388 START_PROFILE(SMBfindnclose);
6390 dptr_num = SVAL(inbuf,smb_vwv0);
6392 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6394 /* We never give out valid handles for a
6395 findnotifyfirst - so any dptr_num is ok here.
6396 Just ignore it. */
6398 outsize = set_message(outbuf,0,0,False);
6400 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6402 END_PROFILE(SMBfindnclose);
6403 return(outsize);
6406 int handle_trans2(connection_struct *conn,
6407 struct trans_state *state,
6408 char *inbuf, char *outbuf, int size, int bufsize)
6410 int outsize;
6412 if (Protocol >= PROTOCOL_NT1) {
6413 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6416 /* Now we must call the relevant TRANS2 function */
6417 switch(state->call) {
6418 case TRANSACT2_OPEN:
6420 START_PROFILE(Trans2_open);
6421 outsize = call_trans2open(
6422 conn, inbuf, outbuf, bufsize,
6423 &state->param, state->total_param,
6424 &state->data, state->total_data,
6425 state->max_data_return);
6426 END_PROFILE(Trans2_open);
6427 break;
6430 case TRANSACT2_FINDFIRST:
6432 START_PROFILE(Trans2_findfirst);
6433 outsize = call_trans2findfirst(
6434 conn, inbuf, outbuf, bufsize,
6435 &state->param, state->total_param,
6436 &state->data, state->total_data,
6437 state->max_data_return);
6438 END_PROFILE(Trans2_findfirst);
6439 break;
6442 case TRANSACT2_FINDNEXT:
6444 START_PROFILE(Trans2_findnext);
6445 outsize = call_trans2findnext(
6446 conn, inbuf, outbuf, size, bufsize,
6447 &state->param, state->total_param,
6448 &state->data, state->total_data,
6449 state->max_data_return);
6450 END_PROFILE(Trans2_findnext);
6451 break;
6454 case TRANSACT2_QFSINFO:
6456 START_PROFILE(Trans2_qfsinfo);
6457 outsize = call_trans2qfsinfo(
6458 conn, inbuf, outbuf, size, bufsize,
6459 &state->param, state->total_param,
6460 &state->data, state->total_data,
6461 state->max_data_return);
6462 END_PROFILE(Trans2_qfsinfo);
6463 break;
6466 case TRANSACT2_SETFSINFO:
6468 START_PROFILE(Trans2_setfsinfo);
6469 outsize = call_trans2setfsinfo(
6470 conn, inbuf, outbuf, size, bufsize,
6471 &state->param, state->total_param,
6472 &state->data, state->total_data,
6473 state->max_data_return);
6474 END_PROFILE(Trans2_setfsinfo);
6475 break;
6478 case TRANSACT2_QPATHINFO:
6479 case TRANSACT2_QFILEINFO:
6481 START_PROFILE(Trans2_qpathinfo);
6482 outsize = call_trans2qfilepathinfo(
6483 conn, inbuf, outbuf, size, bufsize, state->call,
6484 &state->param, state->total_param,
6485 &state->data, state->total_data,
6486 state->max_data_return);
6487 END_PROFILE(Trans2_qpathinfo);
6488 break;
6491 case TRANSACT2_SETPATHINFO:
6492 case TRANSACT2_SETFILEINFO:
6494 START_PROFILE(Trans2_setpathinfo);
6495 outsize = call_trans2setfilepathinfo(
6496 conn, inbuf, outbuf, size, bufsize, state->call,
6497 &state->param, state->total_param,
6498 &state->data, state->total_data,
6499 state->max_data_return);
6500 END_PROFILE(Trans2_setpathinfo);
6501 break;
6504 case TRANSACT2_FINDNOTIFYFIRST:
6506 START_PROFILE(Trans2_findnotifyfirst);
6507 outsize = call_trans2findnotifyfirst(
6508 conn, inbuf, outbuf, size, bufsize,
6509 &state->param, state->total_param,
6510 &state->data, state->total_data,
6511 state->max_data_return);
6512 END_PROFILE(Trans2_findnotifyfirst);
6513 break;
6516 case TRANSACT2_FINDNOTIFYNEXT:
6518 START_PROFILE(Trans2_findnotifynext);
6519 outsize = call_trans2findnotifynext(
6520 conn, inbuf, outbuf, size, bufsize,
6521 &state->param, state->total_param,
6522 &state->data, state->total_data,
6523 state->max_data_return);
6524 END_PROFILE(Trans2_findnotifynext);
6525 break;
6528 case TRANSACT2_MKDIR:
6530 START_PROFILE(Trans2_mkdir);
6531 outsize = call_trans2mkdir(
6532 conn, inbuf, outbuf, size, bufsize,
6533 &state->param, state->total_param,
6534 &state->data, state->total_data,
6535 state->max_data_return);
6536 END_PROFILE(Trans2_mkdir);
6537 break;
6540 case TRANSACT2_GET_DFS_REFERRAL:
6542 START_PROFILE(Trans2_get_dfs_referral);
6543 outsize = call_trans2getdfsreferral(
6544 conn, inbuf, outbuf, size, bufsize,
6545 &state->param, state->total_param,
6546 &state->data, state->total_data,
6547 state->max_data_return);
6548 END_PROFILE(Trans2_get_dfs_referral);
6549 break;
6552 case TRANSACT2_IOCTL:
6554 START_PROFILE(Trans2_ioctl);
6555 outsize = call_trans2ioctl(
6556 conn, inbuf, outbuf, size, bufsize,
6557 &state->param, state->total_param,
6558 &state->data, state->total_data,
6559 state->max_data_return);
6560 END_PROFILE(Trans2_ioctl);
6561 break;
6564 default:
6565 /* Error in request */
6566 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6567 outsize = ERROR_DOS(ERRSRV,ERRerror);
6570 return outsize;
6573 /****************************************************************************
6574 Reply to a SMBtrans2.
6575 ****************************************************************************/
6577 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6578 int size, int bufsize)
6580 int outsize = 0;
6581 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6582 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6583 unsigned int psoff = SVAL(inbuf, smb_psoff);
6584 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6585 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6586 unsigned int av_size = size-4;
6587 struct trans_state *state;
6588 NTSTATUS result;
6590 START_PROFILE(SMBtrans2);
6592 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6593 if (!NT_STATUS_IS_OK(result)) {
6594 DEBUG(2, ("Got invalid trans2 request: %s\n",
6595 nt_errstr(result)));
6596 END_PROFILE(SMBtrans2);
6597 return ERROR_NT(result);
6600 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6601 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6602 END_PROFILE(SMBtrans2);
6603 return ERROR_DOS(ERRSRV,ERRaccess);
6606 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6607 DEBUG(0, ("talloc failed\n"));
6608 END_PROFILE(SMBtrans2);
6609 return ERROR_NT(NT_STATUS_NO_MEMORY);
6612 state->cmd = SMBtrans2;
6614 state->mid = SVAL(inbuf, smb_mid);
6615 state->vuid = SVAL(inbuf, smb_uid);
6616 state->setup_count = SVAL(inbuf, smb_suwcnt);
6617 state->setup = NULL;
6618 state->total_param = SVAL(inbuf, smb_tpscnt);
6619 state->param = NULL;
6620 state->total_data = SVAL(inbuf, smb_tdscnt);
6621 state->data = NULL;
6622 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6623 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6624 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6625 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6626 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6628 state->call = tran_call;
6630 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6631 is so as a sanity check */
6632 if (state->setup_count != 1) {
6634 * Need to have rc=0 for ioctl to get job id for OS/2.
6635 * Network printing will fail if function is not successful.
6636 * Similar function in reply.c will be used if protocol
6637 * is LANMAN1.0 instead of LM1.2X002.
6638 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6639 * outbuf doesn't have to be set(only job id is used).
6641 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6642 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6643 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6644 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6645 } else {
6646 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6647 DEBUG(2,("Transaction is %d\n",tran_call));
6648 TALLOC_FREE(state);
6649 END_PROFILE(SMBtrans2);
6650 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6654 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6655 goto bad_param;
6657 if (state->total_data) {
6658 /* Can't use talloc here, the core routines do realloc on the
6659 * params and data. */
6660 state->data = (char *)SMB_MALLOC(state->total_data);
6661 if (state->data == NULL) {
6662 DEBUG(0,("reply_trans2: data malloc fail for %u "
6663 "bytes !\n", (unsigned int)state->total_data));
6664 TALLOC_FREE(state);
6665 END_PROFILE(SMBtrans2);
6666 return(ERROR_DOS(ERRDOS,ERRnomem));
6669 if (dscnt > state->total_data ||
6670 dsoff+dscnt < dsoff) {
6671 goto bad_param;
6674 if (dsoff > av_size ||
6675 dscnt > av_size ||
6676 dsoff+dscnt > av_size) {
6677 goto bad_param;
6680 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6683 if (state->total_param) {
6684 /* Can't use talloc here, the core routines do realloc on the
6685 * params and data. */
6686 state->param = (char *)SMB_MALLOC(state->total_param);
6687 if (state->param == NULL) {
6688 DEBUG(0,("reply_trans: param malloc fail for %u "
6689 "bytes !\n", (unsigned int)state->total_param));
6690 SAFE_FREE(state->data);
6691 TALLOC_FREE(state);
6692 END_PROFILE(SMBtrans2);
6693 return(ERROR_DOS(ERRDOS,ERRnomem));
6696 if (pscnt > state->total_param ||
6697 psoff+pscnt < psoff) {
6698 goto bad_param;
6701 if (psoff > av_size ||
6702 pscnt > av_size ||
6703 psoff+pscnt > av_size) {
6704 goto bad_param;
6707 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6710 state->received_data = dscnt;
6711 state->received_param = pscnt;
6713 if ((state->received_param == state->total_param) &&
6714 (state->received_data == state->total_data)) {
6716 outsize = handle_trans2(conn, state, inbuf, outbuf,
6717 size, bufsize);
6718 SAFE_FREE(state->data);
6719 SAFE_FREE(state->param);
6720 TALLOC_FREE(state);
6721 END_PROFILE(SMBtrans2);
6722 return outsize;
6725 DLIST_ADD(conn->pending_trans, state);
6727 /* We need to send an interim response then receive the rest
6728 of the parameter/data bytes */
6729 outsize = set_message(outbuf,0,0,False);
6730 show_msg(outbuf);
6731 END_PROFILE(SMBtrans2);
6732 return outsize;
6734 bad_param:
6736 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6737 SAFE_FREE(state->data);
6738 SAFE_FREE(state->param);
6739 TALLOC_FREE(state);
6740 END_PROFILE(SMBtrans2);
6741 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6745 /****************************************************************************
6746 Reply to a SMBtranss2
6747 ****************************************************************************/
6749 int reply_transs2(connection_struct *conn,
6750 char *inbuf,char *outbuf,int size,int bufsize)
6752 int outsize = 0;
6753 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6754 unsigned int av_size = size-4;
6755 struct trans_state *state;
6757 START_PROFILE(SMBtranss2);
6759 show_msg(inbuf);
6761 for (state = conn->pending_trans; state != NULL;
6762 state = state->next) {
6763 if (state->mid == SVAL(inbuf,smb_mid)) {
6764 break;
6768 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6769 END_PROFILE(SMBtranss2);
6770 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6773 /* Revise state->total_param and state->total_data in case they have
6774 changed downwards */
6776 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6777 state->total_param = SVAL(inbuf, smb_tpscnt);
6778 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6779 state->total_data = SVAL(inbuf, smb_tdscnt);
6781 pcnt = SVAL(inbuf, smb_spscnt);
6782 poff = SVAL(inbuf, smb_spsoff);
6783 pdisp = SVAL(inbuf, smb_spsdisp);
6785 dcnt = SVAL(inbuf, smb_sdscnt);
6786 doff = SVAL(inbuf, smb_sdsoff);
6787 ddisp = SVAL(inbuf, smb_sdsdisp);
6789 state->received_param += pcnt;
6790 state->received_data += dcnt;
6792 if ((state->received_data > state->total_data) ||
6793 (state->received_param > state->total_param))
6794 goto bad_param;
6796 if (pcnt) {
6797 if (pdisp > state->total_param ||
6798 pcnt > state->total_param ||
6799 pdisp+pcnt > state->total_param ||
6800 pdisp+pcnt < pdisp) {
6801 goto bad_param;
6804 if (poff > av_size ||
6805 pcnt > av_size ||
6806 poff+pcnt > av_size ||
6807 poff+pcnt < poff) {
6808 goto bad_param;
6811 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6812 pcnt);
6815 if (dcnt) {
6816 if (ddisp > state->total_data ||
6817 dcnt > state->total_data ||
6818 ddisp+dcnt > state->total_data ||
6819 ddisp+dcnt < ddisp) {
6820 goto bad_param;
6823 if (ddisp > av_size ||
6824 dcnt > av_size ||
6825 ddisp+dcnt > av_size ||
6826 ddisp+dcnt < ddisp) {
6827 goto bad_param;
6830 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6831 dcnt);
6834 if ((state->received_param < state->total_param) ||
6835 (state->received_data < state->total_data)) {
6836 END_PROFILE(SMBtranss2);
6837 return -1;
6840 /* construct_reply_common has done us the favor to pre-fill the
6841 * command field with SMBtranss2 which is wrong :-)
6843 SCVAL(outbuf,smb_com,SMBtrans2);
6845 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6847 DLIST_REMOVE(conn->pending_trans, state);
6848 SAFE_FREE(state->data);
6849 SAFE_FREE(state->param);
6850 TALLOC_FREE(state);
6852 if (outsize == 0) {
6853 END_PROFILE(SMBtranss2);
6854 return(ERROR_DOS(ERRSRV,ERRnosupport));
6857 END_PROFILE(SMBtranss2);
6858 return(outsize);
6860 bad_param:
6862 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6863 DLIST_REMOVE(conn->pending_trans, state);
6864 SAFE_FREE(state->data);
6865 SAFE_FREE(state->param);
6866 TALLOC_FREE(state);
6867 END_PROFILE(SMBtranss2);
6868 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);