r21603: Horrible backwards compatibility hack as an old server bug
[Samba.git] / source / smbd / trans2.c
blob5bbd618231b5336d529fad09dcbeafe2f4ba0a4a
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
9 Extensively modified by Andrew Tridgell, 1995
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 /********************************************************************
38 Roundup a value to the nearest allocation roundup size boundary.
39 Only do this for Windows clients.
40 ********************************************************************/
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
44 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
46 /* Only roundup for Windows clients. */
47 enum remote_arch_types ra_type = get_remote_arch();
48 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49 val = SMB_ROUNDUP(val,rval);
51 return val;
54 /********************************************************************
55 Given a stat buffer return the allocated size on disk, taking into
56 account sparse files.
57 ********************************************************************/
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
61 SMB_BIG_UINT ret;
63 if(S_ISDIR(sbuf->st_mode)) {
64 return 0;
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
69 #else
70 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
71 #endif
73 if (fsp && fsp->initial_allocation_size)
74 ret = MAX(ret,fsp->initial_allocation_size);
76 return smb_roundup(conn, ret);
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 static const char *prohibited_ea_names[] = {
84 SAMBA_POSIX_INHERITANCE_EA_NAME,
85 SAMBA_XATTR_DOS_ATTRIB,
86 NULL
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
95 int i;
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 return True;
101 return False;
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
113 char *val = NULL;
114 ssize_t sizeret;
116 again:
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
119 if (!val) {
120 return False;
123 if (fsp && fsp->fh->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
125 } else {
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130 attr_size = 65536;
131 goto again;
134 if (sizeret == -1) {
135 return False;
138 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139 dump_data(10, val, sizeret);
141 pea->flags = 0;
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
144 } else {
145 pea->name = ea_name;
147 pea->value.data = (unsigned char *)val;
148 pea->value.length = (size_t)sizeret;
149 return True;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157 const char *fname, size_t *pea_total_len)
159 /* Get a list of all xattrs. Max namesize is 64k. */
160 size_t ea_namelist_size = 1024;
161 char *ea_namelist;
162 char *p;
163 ssize_t sizeret;
164 int i;
165 struct ea_list *ea_list_head = NULL;
167 *pea_total_len = 0;
169 if (!lp_ea_support(SNUM(conn))) {
170 return NULL;
173 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
174 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
176 if (!ea_namelist) {
177 return NULL;
180 if (fsp && fsp->fh->fd != -1) {
181 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
182 } else {
183 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
186 if (sizeret == -1 && errno == ERANGE) {
187 ea_namelist_size *= 2;
188 } else {
189 break;
193 if (sizeret == -1)
194 return NULL;
196 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
198 if (sizeret) {
199 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
200 struct ea_list *listp;
202 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
203 continue;
205 listp = TALLOC_P(mem_ctx, struct ea_list);
206 if (!listp)
207 return NULL;
209 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
210 return NULL;
214 fstring dos_ea_name;
215 push_ascii_fstring(dos_ea_name, listp->ea.name);
216 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
217 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
218 (unsigned int)*pea_total_len, dos_ea_name,
219 (unsigned int)listp->ea.value.length ));
221 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
223 /* Add on 4 for total length. */
224 if (*pea_total_len) {
225 *pea_total_len += 4;
229 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
230 return ea_list_head;
233 /****************************************************************************
234 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
235 that was filled.
236 ****************************************************************************/
238 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
239 connection_struct *conn, struct ea_list *ea_list)
241 unsigned int ret_data_size = 4;
242 char *p = pdata;
244 SMB_ASSERT(total_data_size >= 4);
246 if (!lp_ea_support(SNUM(conn))) {
247 SIVAL(pdata,4,0);
248 return 4;
251 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
252 size_t dos_namelen;
253 fstring dos_ea_name;
254 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
255 dos_namelen = strlen(dos_ea_name);
256 if (dos_namelen > 255 || dos_namelen == 0) {
257 break;
259 if (ea_list->ea.value.length > 65535) {
260 break;
262 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
263 break;
266 /* We know we have room. */
267 SCVAL(p,0,ea_list->ea.flags);
268 SCVAL(p,1,dos_namelen);
269 SSVAL(p,2,ea_list->ea.value.length);
270 fstrcpy(p+4, dos_ea_name);
271 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
273 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
274 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
277 ret_data_size = PTR_DIFF(p, pdata);
278 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
279 SIVAL(pdata,0,ret_data_size);
280 return ret_data_size;
283 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
285 size_t total_ea_len = 0;
286 TALLOC_CTX *mem_ctx = NULL;
288 if (!lp_ea_support(SNUM(conn))) {
289 return 0;
291 mem_ctx = talloc_init("estimate_ea_size");
292 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
293 talloc_destroy(mem_ctx);
294 return total_ea_len;
297 /****************************************************************************
298 Ensure the EA name is case insensitive by matching any existing EA name.
299 ****************************************************************************/
301 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
303 size_t total_ea_len;
304 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
305 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
307 for (; ea_list; ea_list = ea_list->next) {
308 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
309 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
310 &unix_ea_name[5], ea_list->ea.name));
311 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
312 break;
315 talloc_destroy(mem_ctx);
318 /****************************************************************************
319 Set or delete an extended attribute.
320 ****************************************************************************/
322 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
324 if (!lp_ea_support(SNUM(conn))) {
325 return NT_STATUS_EAS_NOT_SUPPORTED;
328 for (;ea_list; ea_list = ea_list->next) {
329 int ret;
330 fstring unix_ea_name;
332 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
333 fstrcat(unix_ea_name, ea_list->ea.name);
335 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
337 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
339 if (samba_private_attr_name(unix_ea_name)) {
340 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
341 return NT_STATUS_ACCESS_DENIED;
344 if (ea_list->ea.value.length == 0) {
345 /* Remove the attribute. */
346 if (fsp && (fsp->fh->fd != -1)) {
347 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
348 unix_ea_name, fsp->fsp_name));
349 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
350 } else {
351 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
352 unix_ea_name, fname));
353 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
355 #ifdef ENOATTR
356 /* Removing a non existent attribute always succeeds. */
357 if (ret == -1 && errno == ENOATTR) {
358 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
359 unix_ea_name));
360 ret = 0;
362 #endif
363 } else {
364 if (fsp && (fsp->fh->fd != -1)) {
365 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
366 unix_ea_name, fsp->fsp_name));
367 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
368 ea_list->ea.value.data, ea_list->ea.value.length, 0);
369 } else {
370 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
371 unix_ea_name, fname));
372 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
373 ea_list->ea.value.data, ea_list->ea.value.length, 0);
377 if (ret == -1) {
378 #ifdef ENOTSUP
379 if (errno == ENOTSUP) {
380 return NT_STATUS_EAS_NOT_SUPPORTED;
382 #endif
383 return map_nt_error_from_unix(errno);
387 return NT_STATUS_OK;
389 /****************************************************************************
390 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
391 ****************************************************************************/
393 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
395 struct ea_list *ea_list_head = NULL;
396 size_t offset = 0;
398 while (offset + 2 < data_size) {
399 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
400 unsigned int namelen = CVAL(pdata,offset);
402 offset++; /* Go past the namelen byte. */
404 /* integer wrap paranioa. */
405 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
406 (offset > data_size) || (namelen > data_size) ||
407 (offset + namelen >= data_size)) {
408 break;
410 /* Ensure the name is null terminated. */
411 if (pdata[offset + namelen] != '\0') {
412 return NULL;
414 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
415 if (!eal->ea.name) {
416 return NULL;
419 offset += (namelen + 1); /* Go past the name + terminating zero. */
420 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
421 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
424 return ea_list_head;
427 /****************************************************************************
428 Read one EA list entry from the buffer.
429 ****************************************************************************/
431 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
433 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
434 uint16 val_len;
435 unsigned int namelen;
437 if (!eal) {
438 return NULL;
441 if (data_size < 6) {
442 return NULL;
445 eal->ea.flags = CVAL(pdata,0);
446 namelen = CVAL(pdata,1);
447 val_len = SVAL(pdata,2);
449 if (4 + namelen + 1 + val_len > data_size) {
450 return NULL;
453 /* Ensure the name is null terminated. */
454 if (pdata[namelen + 4] != '\0') {
455 return NULL;
457 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
458 if (!eal->ea.name) {
459 return NULL;
462 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
463 if (!eal->ea.value.data) {
464 return NULL;
467 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
469 /* Ensure we're null terminated just in case we print the value. */
470 eal->ea.value.data[val_len] = '\0';
471 /* But don't count the null. */
472 eal->ea.value.length--;
474 if (pbytes_used) {
475 *pbytes_used = 4 + namelen + 1 + val_len;
478 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
479 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
481 return eal;
484 /****************************************************************************
485 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
486 ****************************************************************************/
488 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
490 struct ea_list *ea_list_head = NULL;
491 size_t offset = 0;
492 size_t bytes_used = 0;
494 while (offset < data_size) {
495 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
497 if (!eal) {
498 return NULL;
501 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
502 offset += bytes_used;
505 return ea_list_head;
508 /****************************************************************************
509 Count the total EA size needed.
510 ****************************************************************************/
512 static size_t ea_list_size(struct ea_list *ealist)
514 fstring dos_ea_name;
515 struct ea_list *listp;
516 size_t ret = 0;
518 for (listp = ealist; listp; listp = listp->next) {
519 push_ascii_fstring(dos_ea_name, listp->ea.name);
520 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
522 /* Add on 4 for total length. */
523 if (ret) {
524 ret += 4;
527 return ret;
530 /****************************************************************************
531 Return a union of EA's from a file list and a list of names.
532 The TALLOC context for the two lists *MUST* be identical as we steal
533 memory from one list to add to another. JRA.
534 ****************************************************************************/
536 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
538 struct ea_list *nlistp, *flistp;
540 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
541 for (flistp = file_list; flistp; flistp = flistp->next) {
542 if (strequal(nlistp->ea.name, flistp->ea.name)) {
543 break;
547 if (flistp) {
548 /* Copy the data from this entry. */
549 nlistp->ea.flags = flistp->ea.flags;
550 nlistp->ea.value = flistp->ea.value;
551 } else {
552 /* Null entry. */
553 nlistp->ea.flags = 0;
554 ZERO_STRUCT(nlistp->ea.value);
558 *total_ea_len = ea_list_size(name_list);
559 return name_list;
562 /****************************************************************************
563 Send the required number of replies back.
564 We assume all fields other than the data fields are
565 set correctly for the type of call.
566 HACK ! Always assumes smb_setup field is zero.
567 ****************************************************************************/
569 int send_trans2_replies(char *outbuf,
570 int bufsize,
571 const char *params,
572 int paramsize,
573 const char *pdata,
574 int datasize,
575 int max_data_bytes)
577 /* As we are using a protocol > LANMAN1 then the max_send
578 variable must have been set in the sessetupX call.
579 This takes precedence over the max_xmit field in the
580 global struct. These different max_xmit variables should
581 be merged as this is now too confusing */
583 int data_to_send = datasize;
584 int params_to_send = paramsize;
585 int useable_space;
586 const char *pp = params;
587 const char *pd = pdata;
588 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
589 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
590 int data_alignment_offset = 0;
592 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
594 set_message(outbuf,10,0,True);
596 /* Modify the data_to_send and datasize and set the error if
597 we're trying to send more than max_data_bytes. We still send
598 the part of the packet(s) that fit. Strange, but needed
599 for OS/2. */
601 if (max_data_bytes > 0 && datasize > max_data_bytes) {
602 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
603 max_data_bytes, datasize ));
604 datasize = data_to_send = max_data_bytes;
605 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
608 /* If there genuinely are no parameters or data to send just send the empty packet */
610 if(params_to_send == 0 && data_to_send == 0) {
611 show_msg(outbuf);
612 if (!send_smb(smbd_server_fd(),outbuf))
613 exit_server_cleanly("send_trans2_replies: send_smb failed.");
614 return 0;
617 /* When sending params and data ensure that both are nicely aligned */
618 /* Only do this alignment when there is also data to send - else
619 can cause NT redirector problems. */
621 if (((params_to_send % 4) != 0) && (data_to_send != 0))
622 data_alignment_offset = 4 - (params_to_send % 4);
624 /* Space is bufsize minus Netbios over TCP header minus SMB header */
625 /* The alignment_offset is to align the param bytes on an even byte
626 boundary. NT 4.0 Beta needs this to work correctly. */
628 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
630 /* useable_space can never be more than max_send minus the alignment offset. */
632 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
634 while (params_to_send || data_to_send) {
635 /* Calculate whether we will totally or partially fill this packet */
637 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
639 /* We can never send more than useable_space */
641 * Note that 'useable_space' does not include the alignment offsets,
642 * but we must include the alignment offsets in the calculation of
643 * the length of the data we send over the wire, as the alignment offsets
644 * are sent here. Fix from Marc_Jacobsen@hp.com.
647 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
649 set_message(outbuf, 10, total_sent_thistime, True);
651 /* Set total params and data to be sent */
652 SSVAL(outbuf,smb_tprcnt,paramsize);
653 SSVAL(outbuf,smb_tdrcnt,datasize);
655 /* Calculate how many parameters and data we can fit into
656 * this packet. Parameters get precedence
659 params_sent_thistime = MIN(params_to_send,useable_space);
660 data_sent_thistime = useable_space - params_sent_thistime;
661 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
663 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
665 /* smb_proff is the offset from the start of the SMB header to the
666 parameter bytes, however the first 4 bytes of outbuf are
667 the Netbios over TCP header. Thus use smb_base() to subtract
668 them from the calculation */
670 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
672 if(params_sent_thistime == 0)
673 SSVAL(outbuf,smb_prdisp,0);
674 else
675 /* Absolute displacement of param bytes sent in this packet */
676 SSVAL(outbuf,smb_prdisp,pp - params);
678 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
679 if(data_sent_thistime == 0) {
680 SSVAL(outbuf,smb_droff,0);
681 SSVAL(outbuf,smb_drdisp, 0);
682 } else {
683 /* The offset of the data bytes is the offset of the
684 parameter bytes plus the number of parameters being sent this time */
685 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
686 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
687 SSVAL(outbuf,smb_drdisp, pd - pdata);
690 /* Copy the param bytes into the packet */
692 if(params_sent_thistime)
693 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
695 /* Copy in the data bytes */
696 if(data_sent_thistime)
697 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
698 data_alignment_offset,pd,data_sent_thistime);
700 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
701 params_sent_thistime, data_sent_thistime, useable_space));
702 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
703 params_to_send, data_to_send, paramsize, datasize));
705 /* Send the packet */
706 show_msg(outbuf);
707 if (!send_smb(smbd_server_fd(),outbuf))
708 exit_server_cleanly("send_trans2_replies: send_smb failed.");
710 pp += params_sent_thistime;
711 pd += data_sent_thistime;
713 params_to_send -= params_sent_thistime;
714 data_to_send -= data_sent_thistime;
716 /* Sanity check */
717 if(params_to_send < 0 || data_to_send < 0) {
718 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
719 params_to_send, data_to_send));
720 return -1;
724 return 0;
727 /****************************************************************************
728 Reply to a TRANSACT2_OPEN.
729 ****************************************************************************/
731 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
732 char **pparams, int total_params, char **ppdata, int total_data,
733 unsigned int max_data_bytes)
735 char *params = *pparams;
736 char *pdata = *ppdata;
737 int deny_mode;
738 int32 open_attr;
739 BOOL oplock_request;
740 #if 0
741 BOOL return_additional_info;
742 int16 open_sattr;
743 time_t open_time;
744 #endif
745 int open_ofun;
746 uint32 open_size;
747 char *pname;
748 pstring fname;
749 SMB_OFF_T size=0;
750 int fattr=0,mtime=0;
751 SMB_INO_T inode = 0;
752 SMB_STRUCT_STAT sbuf;
753 int smb_action = 0;
754 files_struct *fsp;
755 struct ea_list *ea_list = NULL;
756 uint16 flags = 0;
757 NTSTATUS status;
758 uint32 access_mask;
759 uint32 share_mode;
760 uint32 create_disposition;
761 uint32 create_options = 0;
764 * Ensure we have enough parameters to perform the operation.
767 if (total_params < 29) {
768 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
771 flags = SVAL(params, 0);
772 deny_mode = SVAL(params, 2);
773 open_attr = SVAL(params,6);
774 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
775 if (oplock_request) {
776 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
779 #if 0
780 return_additional_info = BITSETW(params,0);
781 open_sattr = SVAL(params, 4);
782 open_time = make_unix_date3(params+8);
783 #endif
784 open_ofun = SVAL(params,12);
785 open_size = IVAL(params,14);
786 pname = &params[28];
788 if (IS_IPC(conn)) {
789 return(ERROR_DOS(ERRSRV,ERRaccess));
792 srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
793 if (!NT_STATUS_IS_OK(status)) {
794 return ERROR_NT(status);
797 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
798 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
799 (unsigned int)open_ofun, open_size));
801 /* XXXX we need to handle passed times, sattr and flags */
803 status = unix_convert(conn, fname, False, NULL, &sbuf);
804 if (!NT_STATUS_IS_OK(status)) {
805 return ERROR_NT(status);
808 status = check_name(conn, fname);
809 if (!NT_STATUS_IS_OK(status)) {
810 return ERROR_NT(status);
813 if (open_ofun == 0) {
814 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
817 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
818 &access_mask,
819 &share_mode,
820 &create_disposition,
821 &create_options)) {
822 return ERROR_DOS(ERRDOS, ERRbadaccess);
825 /* Any data in this call is an EA list. */
826 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
827 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
830 if (total_data != 4) {
831 if (total_data < 10) {
832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
835 if (IVAL(pdata,0) > total_data) {
836 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
837 IVAL(pdata,0), (unsigned int)total_data));
838 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
841 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
842 total_data - 4);
843 if (!ea_list) {
844 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
846 } else if (IVAL(pdata,0) != 4) {
847 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
850 status = open_file_ntcreate(conn,fname,&sbuf,
851 access_mask,
852 share_mode,
853 create_disposition,
854 create_options,
855 open_attr,
856 oplock_request,
857 &smb_action, &fsp);
859 if (!NT_STATUS_IS_OK(status)) {
860 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
861 /* We have re-scheduled this call. */
862 return -1;
864 return ERROR_NT(status);
867 size = get_file_size(sbuf);
868 fattr = dos_mode(conn,fname,&sbuf);
869 mtime = sbuf.st_mtime;
870 inode = sbuf.st_ino;
871 if (fattr & aDIR) {
872 close_file(fsp,ERROR_CLOSE);
873 return(ERROR_DOS(ERRDOS,ERRnoaccess));
876 /* Save the requested allocation size. */
877 /* Allocate space for the file if a size hint is supplied */
878 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
879 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
880 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
881 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
882 if (fsp->is_directory) {
883 close_file(fsp,ERROR_CLOSE);
884 /* Can't set allocation size on a directory. */
885 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
887 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
888 close_file(fsp,ERROR_CLOSE);
889 return ERROR_NT(NT_STATUS_DISK_FULL);
892 /* Adjust size here to return the right size in the reply.
893 Windows does it this way. */
894 size = fsp->initial_allocation_size;
895 } else {
896 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
900 if (ea_list && smb_action == FILE_WAS_CREATED) {
901 status = set_ea(conn, fsp, fname, ea_list);
902 if (!NT_STATUS_IS_OK(status)) {
903 close_file(fsp,ERROR_CLOSE);
904 return ERROR_NT(status);
908 /* Realloc the size of parameters and data we will return */
909 *pparams = (char *)SMB_REALLOC(*pparams, 30);
910 if(*pparams == NULL ) {
911 return ERROR_NT(NT_STATUS_NO_MEMORY);
913 params = *pparams;
915 SSVAL(params,0,fsp->fnum);
916 SSVAL(params,2,fattr);
917 srv_put_dos_date2(params,4, mtime);
918 SIVAL(params,8, (uint32)size);
919 SSVAL(params,12,deny_mode);
920 SSVAL(params,14,0); /* open_type - file or directory. */
921 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
923 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
924 smb_action |= EXTENDED_OPLOCK_GRANTED;
927 SSVAL(params,18,smb_action);
930 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
932 SIVAL(params,20,inode);
933 SSVAL(params,24,0); /* Padding. */
934 if (flags & 8) {
935 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
936 SIVAL(params, 26, ea_size);
937 } else {
938 SIVAL(params, 26, 0);
941 /* Send the required number of replies */
942 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
944 return -1;
947 /*********************************************************
948 Routine to check if a given string matches exactly.
949 as a special case a mask of "." does NOT match. That
950 is required for correct wildcard semantics
951 Case can be significant or not.
952 **********************************************************/
954 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
956 if (mask[0] == '.' && mask[1] == 0)
957 return False;
958 if (conn->case_sensitive)
959 return strcmp(str,mask)==0;
960 if (StrCaseCmp(str,mask) != 0) {
961 return False;
963 if (dptr_has_wild(conn->dirptr)) {
964 return False;
966 return True;
969 /****************************************************************************
970 Return the filetype for UNIX extensions.
971 ****************************************************************************/
973 static uint32 unix_filetype(mode_t mode)
975 if(S_ISREG(mode))
976 return UNIX_TYPE_FILE;
977 else if(S_ISDIR(mode))
978 return UNIX_TYPE_DIR;
979 #ifdef S_ISLNK
980 else if(S_ISLNK(mode))
981 return UNIX_TYPE_SYMLINK;
982 #endif
983 #ifdef S_ISCHR
984 else if(S_ISCHR(mode))
985 return UNIX_TYPE_CHARDEV;
986 #endif
987 #ifdef S_ISBLK
988 else if(S_ISBLK(mode))
989 return UNIX_TYPE_BLKDEV;
990 #endif
991 #ifdef S_ISFIFO
992 else if(S_ISFIFO(mode))
993 return UNIX_TYPE_FIFO;
994 #endif
995 #ifdef S_ISSOCK
996 else if(S_ISSOCK(mode))
997 return UNIX_TYPE_SOCKET;
998 #endif
1000 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1001 return UNIX_TYPE_UNKNOWN;
1004 /****************************************************************************
1005 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1006 ****************************************************************************/
1008 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1010 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1011 SMB_STRUCT_STAT *psbuf,
1012 uint32 perms,
1013 enum perm_type ptype,
1014 mode_t *ret_perms)
1016 mode_t ret = 0;
1018 if (perms == SMB_MODE_NO_CHANGE) {
1019 if (!VALID_STAT(*psbuf)) {
1020 return NT_STATUS_INVALID_PARAMETER;
1021 } else {
1022 *ret_perms = psbuf->st_mode;
1023 return NT_STATUS_OK;
1027 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1028 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1029 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1030 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1031 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1032 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1033 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1034 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1035 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1036 #ifdef S_ISVTX
1037 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1038 #endif
1039 #ifdef S_ISGID
1040 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1041 #endif
1042 #ifdef S_ISUID
1043 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1044 #endif
1046 switch (ptype) {
1047 case PERM_NEW_FILE:
1048 /* Apply mode mask */
1049 ret &= lp_create_mask(SNUM(conn));
1050 /* Add in force bits */
1051 ret |= lp_force_create_mode(SNUM(conn));
1052 break;
1053 case PERM_NEW_DIR:
1054 ret &= lp_dir_mask(SNUM(conn));
1055 /* Add in force bits */
1056 ret |= lp_force_dir_mode(SNUM(conn));
1057 break;
1058 case PERM_EXISTING_FILE:
1059 /* Apply mode mask */
1060 ret &= lp_security_mask(SNUM(conn));
1061 /* Add in force bits */
1062 ret |= lp_force_security_mode(SNUM(conn));
1063 break;
1064 case PERM_EXISTING_DIR:
1065 /* Apply mode mask */
1066 ret &= lp_dir_security_mask(SNUM(conn));
1067 /* Add in force bits */
1068 ret |= lp_force_dir_security_mode(SNUM(conn));
1069 break;
1072 *ret_perms = ret;
1073 return NT_STATUS_OK;
1076 /****************************************************************************
1077 Get a level dependent lanman2 dir entry.
1078 ****************************************************************************/
1080 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1081 void *inbuf, char *outbuf,
1082 char *path_mask,uint32 dirtype,int info_level,
1083 int requires_resume_key,
1084 BOOL dont_descend,char **ppdata,
1085 char *base_data, int space_remaining,
1086 BOOL *out_of_space, BOOL *got_exact_match,
1087 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1089 const char *dname;
1090 BOOL found = False;
1091 SMB_STRUCT_STAT sbuf;
1092 pstring mask;
1093 pstring pathreal;
1094 pstring fname;
1095 char *p, *q, *pdata = *ppdata;
1096 uint32 reskey=0;
1097 long prev_dirpos=0;
1098 uint32 mode=0;
1099 SMB_OFF_T file_size = 0;
1100 SMB_BIG_UINT allocation_size = 0;
1101 uint32 len;
1102 struct timespec mdate_ts, adate_ts, create_date_ts;
1103 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1104 char *nameptr;
1105 char *last_entry_ptr;
1106 BOOL was_8_3;
1107 uint32 nt_extmode; /* Used for NT connections instead of mode */
1108 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1109 BOOL check_mangled_names = lp_manglednames(conn->params);
1111 *fname = 0;
1112 *out_of_space = False;
1113 *got_exact_match = False;
1115 ZERO_STRUCT(mdate_ts);
1116 ZERO_STRUCT(adate_ts);
1117 ZERO_STRUCT(create_date_ts);
1119 if (!conn->dirptr)
1120 return(False);
1122 p = strrchr_m(path_mask,'/');
1123 if(p != NULL) {
1124 if(p[1] == '\0')
1125 pstrcpy(mask,"*.*");
1126 else
1127 pstrcpy(mask, p+1);
1128 } else
1129 pstrcpy(mask, path_mask);
1132 while (!found) {
1133 BOOL got_match;
1134 BOOL ms_dfs_link = False;
1136 /* Needed if we run out of space */
1137 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1138 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1141 * Due to bugs in NT client redirectors we are not using
1142 * resume keys any more - set them to zero.
1143 * Check out the related comments in findfirst/findnext.
1144 * JRA.
1147 reskey = 0;
1149 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1150 (long)conn->dirptr,curr_dirpos));
1152 if (!dname)
1153 return(False);
1155 pstrcpy(fname,dname);
1157 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1158 got_match = mask_match(fname, mask, conn->case_sensitive);
1160 if(!got_match && check_mangled_names &&
1161 !mangle_is_8_3(fname, False, conn->params)) {
1164 * It turns out that NT matches wildcards against
1165 * both long *and* short names. This may explain some
1166 * of the wildcard wierdness from old DOS clients
1167 * that some people have been seeing.... JRA.
1170 pstring newname;
1171 pstrcpy( newname, fname);
1172 mangle_map( newname, True, False, conn->params);
1173 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1174 got_match = mask_match(newname, mask, conn->case_sensitive);
1177 if(got_match) {
1178 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1179 if (dont_descend && !isdots)
1180 continue;
1182 pstrcpy(pathreal,conn->dirpath);
1183 if(needslash)
1184 pstrcat(pathreal,"/");
1185 pstrcat(pathreal,dname);
1187 if (INFO_LEVEL_IS_UNIX(info_level)) {
1188 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1189 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1190 pathreal,strerror(errno)));
1191 continue;
1193 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1195 /* Needed to show the msdfs symlinks as
1196 * directories */
1198 if(lp_host_msdfs() &&
1199 lp_msdfs_root(SNUM(conn)) &&
1200 ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1202 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1203 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1205 } else {
1207 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1208 pathreal,strerror(errno)));
1209 continue;
1213 if (ms_dfs_link) {
1214 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1215 } else {
1216 mode = dos_mode(conn,pathreal,&sbuf);
1219 if (!dir_check_ftype(conn,mode,dirtype)) {
1220 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1221 continue;
1224 if (!(mode & aDIR))
1225 file_size = get_file_size(sbuf);
1226 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1228 mdate_ts = get_mtimespec(&sbuf);
1229 adate_ts = get_atimespec(&sbuf);
1230 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1232 if (lp_dos_filetime_resolution(SNUM(conn))) {
1233 dos_filetime_timespec(&create_date_ts);
1234 dos_filetime_timespec(&mdate_ts);
1235 dos_filetime_timespec(&adate_ts);
1238 create_date = convert_timespec_to_time_t(create_date_ts);
1239 mdate = convert_timespec_to_time_t(mdate_ts);
1240 adate = convert_timespec_to_time_t(adate_ts);
1242 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1244 found = True;
1246 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1250 mangle_map(fname,False,True,conn->params);
1252 p = pdata;
1253 last_entry_ptr = p;
1255 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1257 switch (info_level) {
1258 case SMB_FIND_INFO_STANDARD:
1259 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1260 if(requires_resume_key) {
1261 SIVAL(p,0,reskey);
1262 p += 4;
1264 srv_put_dos_date2(p,0,create_date);
1265 srv_put_dos_date2(p,4,adate);
1266 srv_put_dos_date2(p,8,mdate);
1267 SIVAL(p,12,(uint32)file_size);
1268 SIVAL(p,16,(uint32)allocation_size);
1269 SSVAL(p,20,mode);
1270 p += 23;
1271 nameptr = p;
1272 p += align_string(outbuf, p, 0);
1273 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1274 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1275 if (len > 2) {
1276 SCVAL(nameptr, -1, len - 2);
1277 } else {
1278 SCVAL(nameptr, -1, 0);
1280 } else {
1281 if (len > 1) {
1282 SCVAL(nameptr, -1, len - 1);
1283 } else {
1284 SCVAL(nameptr, -1, 0);
1287 p += len;
1288 break;
1290 case SMB_FIND_EA_SIZE:
1291 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1292 if(requires_resume_key) {
1293 SIVAL(p,0,reskey);
1294 p += 4;
1296 srv_put_dos_date2(p,0,create_date);
1297 srv_put_dos_date2(p,4,adate);
1298 srv_put_dos_date2(p,8,mdate);
1299 SIVAL(p,12,(uint32)file_size);
1300 SIVAL(p,16,(uint32)allocation_size);
1301 SSVAL(p,20,mode);
1303 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1304 SIVAL(p,22,ea_size); /* Extended attributes */
1306 p += 27;
1307 nameptr = p - 1;
1308 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1309 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1310 if (len > 2) {
1311 len -= 2;
1312 } else {
1313 len = 0;
1315 } else {
1316 if (len > 1) {
1317 len -= 1;
1318 } else {
1319 len = 0;
1322 SCVAL(nameptr,0,len);
1323 p += len;
1324 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1325 break;
1327 case SMB_FIND_EA_LIST:
1329 struct ea_list *file_list = NULL;
1330 size_t ea_len = 0;
1332 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1333 if (!name_list) {
1334 return False;
1336 if(requires_resume_key) {
1337 SIVAL(p,0,reskey);
1338 p += 4;
1340 srv_put_dos_date2(p,0,create_date);
1341 srv_put_dos_date2(p,4,adate);
1342 srv_put_dos_date2(p,8,mdate);
1343 SIVAL(p,12,(uint32)file_size);
1344 SIVAL(p,16,(uint32)allocation_size);
1345 SSVAL(p,20,mode);
1346 p += 22; /* p now points to the EA area. */
1348 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1349 name_list = ea_list_union(name_list, file_list, &ea_len);
1351 /* We need to determine if this entry will fit in the space available. */
1352 /* Max string size is 255 bytes. */
1353 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1354 /* Move the dirptr back to prev_dirpos */
1355 dptr_SeekDir(conn->dirptr, prev_dirpos);
1356 *out_of_space = True;
1357 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1358 return False; /* Not finished - just out of space */
1361 /* Push the ea_data followed by the name. */
1362 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1363 nameptr = p;
1364 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1365 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1366 if (len > 2) {
1367 len -= 2;
1368 } else {
1369 len = 0;
1371 } else {
1372 if (len > 1) {
1373 len -= 1;
1374 } else {
1375 len = 0;
1378 SCVAL(nameptr,0,len);
1379 p += len + 1;
1380 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1381 break;
1384 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1385 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1386 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1387 p += 4;
1388 SIVAL(p,0,reskey); p += 4;
1389 put_long_date_timespec(p,create_date_ts); p += 8;
1390 put_long_date_timespec(p,adate_ts); p += 8;
1391 put_long_date_timespec(p,mdate_ts); p += 8;
1392 put_long_date_timespec(p,mdate_ts); p += 8;
1393 SOFF_T(p,0,file_size); p += 8;
1394 SOFF_T(p,0,allocation_size); p += 8;
1395 SIVAL(p,0,nt_extmode); p += 4;
1396 q = p; p += 4; /* q is placeholder for name length. */
1398 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1399 SIVAL(p,0,ea_size); /* Extended attributes */
1400 p += 4;
1402 /* Clear the short name buffer. This is
1403 * IMPORTANT as not doing so will trigger
1404 * a Win2k client bug. JRA.
1406 if (!was_8_3 && check_mangled_names) {
1407 pstring mangled_name;
1408 pstrcpy(mangled_name, fname);
1409 mangle_map(mangled_name,True,True,
1410 conn->params);
1411 mangled_name[12] = 0;
1412 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1413 if (len < 24) {
1414 memset(p + 2 + len,'\0',24 - len);
1416 SSVAL(p, 0, len);
1417 } else {
1418 memset(p,'\0',26);
1420 p += 2 + 24;
1421 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1422 SIVAL(q,0,len);
1423 p += len;
1424 SIVAL(p,0,0); /* Ensure any padding is null. */
1425 len = PTR_DIFF(p, pdata);
1426 len = (len + 3) & ~3;
1427 SIVAL(pdata,0,len);
1428 p = pdata + len;
1429 break;
1431 case SMB_FIND_FILE_DIRECTORY_INFO:
1432 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1433 p += 4;
1434 SIVAL(p,0,reskey); p += 4;
1435 put_long_date_timespec(p,create_date_ts); p += 8;
1436 put_long_date_timespec(p,adate_ts); p += 8;
1437 put_long_date_timespec(p,mdate_ts); p += 8;
1438 put_long_date_timespec(p,mdate_ts); p += 8;
1439 SOFF_T(p,0,file_size); p += 8;
1440 SOFF_T(p,0,allocation_size); p += 8;
1441 SIVAL(p,0,nt_extmode); p += 4;
1442 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1443 SIVAL(p,0,len);
1444 p += 4 + len;
1445 SIVAL(p,0,0); /* Ensure any padding is null. */
1446 len = PTR_DIFF(p, pdata);
1447 len = (len + 3) & ~3;
1448 SIVAL(pdata,0,len);
1449 p = pdata + len;
1450 break;
1452 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1453 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1454 p += 4;
1455 SIVAL(p,0,reskey); p += 4;
1456 put_long_date_timespec(p,create_date_ts); p += 8;
1457 put_long_date_timespec(p,adate_ts); p += 8;
1458 put_long_date_timespec(p,mdate_ts); p += 8;
1459 put_long_date_timespec(p,mdate_ts); p += 8;
1460 SOFF_T(p,0,file_size); p += 8;
1461 SOFF_T(p,0,allocation_size); p += 8;
1462 SIVAL(p,0,nt_extmode); p += 4;
1463 q = p; p += 4; /* q is placeholder for name length. */
1465 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1466 SIVAL(p,0,ea_size); /* Extended attributes */
1467 p +=4;
1469 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1470 SIVAL(q, 0, len);
1471 p += len;
1473 SIVAL(p,0,0); /* Ensure any padding is null. */
1474 len = PTR_DIFF(p, pdata);
1475 len = (len + 3) & ~3;
1476 SIVAL(pdata,0,len);
1477 p = pdata + len;
1478 break;
1480 case SMB_FIND_FILE_NAMES_INFO:
1481 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1482 p += 4;
1483 SIVAL(p,0,reskey); p += 4;
1484 p += 4;
1485 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1486 acl on a dir (tridge) */
1487 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1488 SIVAL(p, -4, len);
1489 p += len;
1490 SIVAL(p,0,0); /* Ensure any padding is null. */
1491 len = PTR_DIFF(p, pdata);
1492 len = (len + 3) & ~3;
1493 SIVAL(pdata,0,len);
1494 p = pdata + len;
1495 break;
1497 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1498 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1499 p += 4;
1500 SIVAL(p,0,reskey); p += 4;
1501 put_long_date_timespec(p,create_date_ts); p += 8;
1502 put_long_date_timespec(p,adate_ts); p += 8;
1503 put_long_date_timespec(p,mdate_ts); p += 8;
1504 put_long_date_timespec(p,mdate_ts); p += 8;
1505 SOFF_T(p,0,file_size); p += 8;
1506 SOFF_T(p,0,allocation_size); p += 8;
1507 SIVAL(p,0,nt_extmode); p += 4;
1508 q = p; p += 4; /* q is placeholder for name length. */
1510 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1511 SIVAL(p,0,ea_size); /* Extended attributes */
1512 p +=4;
1514 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1515 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1516 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1517 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1518 SIVAL(q, 0, len);
1519 p += len;
1520 SIVAL(p,0,0); /* Ensure any padding is null. */
1521 len = PTR_DIFF(p, pdata);
1522 len = (len + 3) & ~3;
1523 SIVAL(pdata,0,len);
1524 p = pdata + len;
1525 break;
1527 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1528 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1529 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1530 p += 4;
1531 SIVAL(p,0,reskey); p += 4;
1532 put_long_date_timespec(p,create_date_ts); p += 8;
1533 put_long_date_timespec(p,adate_ts); p += 8;
1534 put_long_date_timespec(p,mdate_ts); p += 8;
1535 put_long_date_timespec(p,mdate_ts); p += 8;
1536 SOFF_T(p,0,file_size); p += 8;
1537 SOFF_T(p,0,allocation_size); p += 8;
1538 SIVAL(p,0,nt_extmode); p += 4;
1539 q = p; p += 4; /* q is placeholder for name length */
1541 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1542 SIVAL(p,0,ea_size); /* Extended attributes */
1543 p +=4;
1545 /* Clear the short name buffer. This is
1546 * IMPORTANT as not doing so will trigger
1547 * a Win2k client bug. JRA.
1549 if (!was_8_3 && check_mangled_names) {
1550 pstring mangled_name;
1551 pstrcpy(mangled_name, fname);
1552 mangle_map(mangled_name,True,True,
1553 conn->params);
1554 mangled_name[12] = 0;
1555 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1556 SSVAL(p, 0, len);
1557 if (len < 24) {
1558 memset(p + 2 + len,'\0',24 - len);
1560 SSVAL(p, 0, len);
1561 } else {
1562 memset(p,'\0',26);
1564 p += 26;
1565 SSVAL(p,0,0); p += 2; /* Reserved ? */
1566 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1567 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1568 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1569 SIVAL(q,0,len);
1570 p += len;
1571 SIVAL(p,0,0); /* Ensure any padding is null. */
1572 len = PTR_DIFF(p, pdata);
1573 len = (len + 3) & ~3;
1574 SIVAL(pdata,0,len);
1575 p = pdata + len;
1576 break;
1578 /* CIFS UNIX Extension. */
1580 case SMB_FIND_FILE_UNIX:
1581 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1582 p+= 4;
1583 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1585 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1586 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1587 p+= 8;
1589 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1590 p+= 8;
1592 put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */
1593 put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
1594 put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
1595 p+= 24;
1597 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1598 SIVAL(p,4,0);
1599 p+= 8;
1601 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1602 SIVAL(p,4,0);
1603 p+= 8;
1605 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1606 p+= 4;
1608 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1609 SIVAL(p,4,0);
1610 p+= 8;
1612 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1613 SIVAL(p,4,0);
1614 p+= 8;
1616 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1617 p+= 8;
1619 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1620 SIVAL(p,4,0);
1621 p+= 8;
1623 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1624 SIVAL(p,4,0);
1625 p+= 8;
1627 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1628 p += len;
1629 SIVAL(p,0,0); /* Ensure any padding is null. */
1631 len = PTR_DIFF(p, pdata);
1632 len = (len + 3) & ~3;
1633 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1634 p = pdata + len;
1635 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1637 break;
1639 default:
1640 return(False);
1644 if (PTR_DIFF(p,pdata) > space_remaining) {
1645 /* Move the dirptr back to prev_dirpos */
1646 dptr_SeekDir(conn->dirptr, prev_dirpos);
1647 *out_of_space = True;
1648 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1649 return False; /* Not finished - just out of space */
1652 /* Setup the last entry pointer, as an offset from base_data */
1653 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1654 /* Advance the data pointer to the next slot */
1655 *ppdata = p;
1657 return(found);
1660 /****************************************************************************
1661 Reply to a TRANS2_FINDFIRST.
1662 ****************************************************************************/
1664 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1665 char **pparams, int total_params, char **ppdata, int total_data,
1666 unsigned int max_data_bytes)
1668 /* We must be careful here that we don't return more than the
1669 allowed number of data bytes. If this means returning fewer than
1670 maxentries then so be it. We assume that the redirector has
1671 enough room for the fixed number of parameter bytes it has
1672 requested. */
1673 char *params = *pparams;
1674 char *pdata = *ppdata;
1675 uint32 dirtype;
1676 int maxentries;
1677 uint16 findfirst_flags;
1678 BOOL close_after_first;
1679 BOOL close_if_end;
1680 BOOL requires_resume_key;
1681 int info_level;
1682 pstring directory;
1683 pstring mask;
1684 char *p;
1685 int last_entry_off=0;
1686 int dptr_num = -1;
1687 int numentries = 0;
1688 int i;
1689 BOOL finished = False;
1690 BOOL dont_descend = False;
1691 BOOL out_of_space = False;
1692 int space_remaining;
1693 BOOL mask_contains_wcard = False;
1694 SMB_STRUCT_STAT sbuf;
1695 TALLOC_CTX *ea_ctx = NULL;
1696 struct ea_list *ea_list = NULL;
1697 NTSTATUS ntstatus = NT_STATUS_OK;
1699 if (total_params < 13) {
1700 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1703 dirtype = SVAL(params,0);
1704 maxentries = SVAL(params,2);
1705 findfirst_flags = SVAL(params,4);
1706 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1707 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1708 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1709 info_level = SVAL(params,6);
1711 *directory = *mask = 0;
1713 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1714 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1715 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1716 info_level, max_data_bytes));
1718 if (!maxentries) {
1719 /* W2K3 seems to treat zero as 1. */
1720 maxentries = 1;
1723 switch (info_level) {
1724 case SMB_FIND_INFO_STANDARD:
1725 case SMB_FIND_EA_SIZE:
1726 case SMB_FIND_EA_LIST:
1727 case SMB_FIND_FILE_DIRECTORY_INFO:
1728 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1729 case SMB_FIND_FILE_NAMES_INFO:
1730 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1731 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1732 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1733 break;
1734 case SMB_FIND_FILE_UNIX:
1735 if (!lp_unix_extensions()) {
1736 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1738 break;
1739 default:
1740 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1743 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1744 if (!NT_STATUS_IS_OK(ntstatus)) {
1745 return ERROR_NT(ntstatus);
1748 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1750 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1751 if (!NT_STATUS_IS_OK(ntstatus)) {
1752 return ERROR_NT(ntstatus);
1754 ntstatus = check_name(conn, directory);
1755 if (!NT_STATUS_IS_OK(ntstatus)) {
1756 return ERROR_NT(ntstatus);
1759 p = strrchr_m(directory,'/');
1760 if(p == NULL) {
1761 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1762 if((directory[0] == '.') && (directory[1] == '\0')) {
1763 pstrcpy(mask,"*");
1764 mask_contains_wcard = True;
1765 } else {
1766 pstrcpy(mask,directory);
1768 pstrcpy(directory,"./");
1769 } else {
1770 pstrcpy(mask,p+1);
1771 *p = 0;
1774 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1776 if (info_level == SMB_FIND_EA_LIST) {
1777 uint32 ea_size;
1779 if (total_data < 4) {
1780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1783 ea_size = IVAL(pdata,0);
1784 if (ea_size != total_data) {
1785 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1786 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1787 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1790 if (!lp_ea_support(SNUM(conn))) {
1791 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1794 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1795 return ERROR_NT(NT_STATUS_NO_MEMORY);
1798 /* Pull out the list of names. */
1799 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1800 if (!ea_list) {
1801 talloc_destroy(ea_ctx);
1802 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1806 *ppdata = (char *)SMB_REALLOC(
1807 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1808 if(*ppdata == NULL ) {
1809 talloc_destroy(ea_ctx);
1810 return ERROR_NT(NT_STATUS_NO_MEMORY);
1812 pdata = *ppdata;
1814 /* Realloc the params space */
1815 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1816 if (*pparams == NULL) {
1817 talloc_destroy(ea_ctx);
1818 return ERROR_NT(NT_STATUS_NO_MEMORY);
1820 params = *pparams;
1822 /* Save the wildcard match and attribs we are using on this directory -
1823 needed as lanman2 assumes these are being saved between calls */
1825 ntstatus = dptr_create(conn,
1826 directory,
1827 False,
1828 True,
1829 SVAL(inbuf,smb_pid),
1830 mask,
1831 mask_contains_wcard,
1832 dirtype,
1833 &conn->dirptr);
1835 if (!NT_STATUS_IS_OK(ntstatus)) {
1836 talloc_destroy(ea_ctx);
1837 return ERROR_NT(ntstatus);
1840 dptr_num = dptr_dnum(conn->dirptr);
1841 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1843 /* We don't need to check for VOL here as this is returned by
1844 a different TRANS2 call. */
1846 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1847 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1848 dont_descend = True;
1850 p = pdata;
1851 space_remaining = max_data_bytes;
1852 out_of_space = False;
1854 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1855 BOOL got_exact_match = False;
1857 /* this is a heuristic to avoid seeking the dirptr except when
1858 absolutely necessary. It allows for a filename of about 40 chars */
1859 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1860 out_of_space = True;
1861 finished = False;
1862 } else {
1863 finished = !get_lanman2_dir_entry(conn,
1864 inbuf, outbuf,
1865 mask,dirtype,info_level,
1866 requires_resume_key,dont_descend,
1867 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1868 &last_entry_off, ea_list, ea_ctx);
1871 if (finished && out_of_space)
1872 finished = False;
1874 if (!finished && !out_of_space)
1875 numentries++;
1878 * As an optimisation if we know we aren't looking
1879 * for a wildcard name (ie. the name matches the wildcard exactly)
1880 * then we can finish on any (first) match.
1881 * This speeds up large directory searches. JRA.
1884 if(got_exact_match)
1885 finished = True;
1887 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1890 talloc_destroy(ea_ctx);
1892 /* Check if we can close the dirptr */
1893 if(close_after_first || (finished && close_if_end)) {
1894 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1895 dptr_close(&dptr_num);
1899 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1900 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1901 * the protocol level is less than NT1. Tested with smbclient. JRA.
1902 * This should fix the OS/2 client bug #2335.
1905 if(numentries == 0) {
1906 dptr_close(&dptr_num);
1907 if (Protocol < PROTOCOL_NT1) {
1908 return ERROR_DOS(ERRDOS,ERRnofiles);
1909 } else {
1910 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1914 /* At this point pdata points to numentries directory entries. */
1916 /* Set up the return parameter block */
1917 SSVAL(params,0,dptr_num);
1918 SSVAL(params,2,numentries);
1919 SSVAL(params,4,finished);
1920 SSVAL(params,6,0); /* Never an EA error */
1921 SSVAL(params,8,last_entry_off);
1923 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1925 if ((! *directory) && dptr_path(dptr_num))
1926 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1928 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1929 smb_fn_name(CVAL(inbuf,smb_com)),
1930 mask, directory, dirtype, numentries ) );
1933 * Force a name mangle here to ensure that the
1934 * mask as an 8.3 name is top of the mangled cache.
1935 * The reasons for this are subtle. Don't remove
1936 * this code unless you know what you are doing
1937 * (see PR#13758). JRA.
1940 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1941 mangle_map(mask, True, True, conn->params);
1943 return(-1);
1946 /****************************************************************************
1947 Reply to a TRANS2_FINDNEXT.
1948 ****************************************************************************/
1950 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1951 char **pparams, int total_params, char **ppdata, int total_data,
1952 unsigned int max_data_bytes)
1954 /* We must be careful here that we don't return more than the
1955 allowed number of data bytes. If this means returning fewer than
1956 maxentries then so be it. We assume that the redirector has
1957 enough room for the fixed number of parameter bytes it has
1958 requested. */
1959 char *params = *pparams;
1960 char *pdata = *ppdata;
1961 int dptr_num;
1962 int maxentries;
1963 uint16 info_level;
1964 uint32 resume_key;
1965 uint16 findnext_flags;
1966 BOOL close_after_request;
1967 BOOL close_if_end;
1968 BOOL requires_resume_key;
1969 BOOL continue_bit;
1970 BOOL mask_contains_wcard = False;
1971 pstring resume_name;
1972 pstring mask;
1973 pstring directory;
1974 char *p;
1975 uint16 dirtype;
1976 int numentries = 0;
1977 int i, last_entry_off=0;
1978 BOOL finished = False;
1979 BOOL dont_descend = False;
1980 BOOL out_of_space = False;
1981 int space_remaining;
1982 TALLOC_CTX *ea_ctx = NULL;
1983 struct ea_list *ea_list = NULL;
1984 NTSTATUS ntstatus = NT_STATUS_OK;
1986 if (total_params < 13) {
1987 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1990 dptr_num = SVAL(params,0);
1991 maxentries = SVAL(params,2);
1992 info_level = SVAL(params,4);
1993 resume_key = IVAL(params,6);
1994 findnext_flags = SVAL(params,10);
1995 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1996 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1997 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1998 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2000 *mask = *directory = *resume_name = 0;
2002 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2003 if (!NT_STATUS_IS_OK(ntstatus)) {
2004 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2005 complain (it thinks we're asking for the directory above the shared
2006 path or an invalid name). Catch this as the resume name is only compared, never used in
2007 a file access. JRA. */
2008 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2009 pstrcpy(resume_name, "..");
2010 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2011 pstrcpy(resume_name, ".");
2012 } else {
2013 return ERROR_NT(ntstatus);
2017 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2018 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2019 resume_key = %d resume name = %s continue=%d level = %d\n",
2020 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2021 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2023 if (!maxentries) {
2024 /* W2K3 seems to treat zero as 1. */
2025 maxentries = 1;
2028 switch (info_level) {
2029 case SMB_FIND_INFO_STANDARD:
2030 case SMB_FIND_EA_SIZE:
2031 case SMB_FIND_EA_LIST:
2032 case SMB_FIND_FILE_DIRECTORY_INFO:
2033 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2034 case SMB_FIND_FILE_NAMES_INFO:
2035 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2036 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2038 break;
2039 case SMB_FIND_FILE_UNIX:
2040 if (!lp_unix_extensions()) {
2041 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2043 break;
2044 default:
2045 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2048 if (info_level == SMB_FIND_EA_LIST) {
2049 uint32 ea_size;
2051 if (total_data < 4) {
2052 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2055 ea_size = IVAL(pdata,0);
2056 if (ea_size != total_data) {
2057 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2058 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2059 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2062 if (!lp_ea_support(SNUM(conn))) {
2063 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2066 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2067 return ERROR_NT(NT_STATUS_NO_MEMORY);
2070 /* Pull out the list of names. */
2071 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2072 if (!ea_list) {
2073 talloc_destroy(ea_ctx);
2074 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2078 *ppdata = (char *)SMB_REALLOC(
2079 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2080 if(*ppdata == NULL) {
2081 talloc_destroy(ea_ctx);
2082 return ERROR_NT(NT_STATUS_NO_MEMORY);
2085 pdata = *ppdata;
2087 /* Realloc the params space */
2088 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2089 if(*pparams == NULL ) {
2090 talloc_destroy(ea_ctx);
2091 return ERROR_NT(NT_STATUS_NO_MEMORY);
2094 params = *pparams;
2096 /* Check that the dptr is valid */
2097 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2098 talloc_destroy(ea_ctx);
2099 return ERROR_DOS(ERRDOS,ERRnofiles);
2102 string_set(&conn->dirpath,dptr_path(dptr_num));
2104 /* Get the wildcard mask from the dptr */
2105 if((p = dptr_wcard(dptr_num))== NULL) {
2106 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2107 talloc_destroy(ea_ctx);
2108 return ERROR_DOS(ERRDOS,ERRnofiles);
2111 pstrcpy(mask, p);
2112 pstrcpy(directory,conn->dirpath);
2114 /* Get the attr mask from the dptr */
2115 dirtype = dptr_attr(dptr_num);
2117 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2118 dptr_num, mask, dirtype,
2119 (long)conn->dirptr,
2120 dptr_TellDir(conn->dirptr)));
2122 /* We don't need to check for VOL here as this is returned by
2123 a different TRANS2 call. */
2125 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2126 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2127 dont_descend = True;
2129 p = pdata;
2130 space_remaining = max_data_bytes;
2131 out_of_space = False;
2134 * Seek to the correct position. We no longer use the resume key but
2135 * depend on the last file name instead.
2138 if(*resume_name && !continue_bit) {
2139 SMB_STRUCT_STAT st;
2141 long current_pos = 0;
2143 * Remember, mangle_map is called by
2144 * get_lanman2_dir_entry(), so the resume name
2145 * could be mangled. Ensure we check the unmangled name.
2148 if (mangle_is_mangled(resume_name, conn->params)) {
2149 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2150 conn->params);
2154 * Fix for NT redirector problem triggered by resume key indexes
2155 * changing between directory scans. We now return a resume key of 0
2156 * and instead look for the filename to continue from (also given
2157 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2158 * findfirst/findnext (as is usual) then the directory pointer
2159 * should already be at the correct place.
2162 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2163 } /* end if resume_name && !continue_bit */
2165 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2166 BOOL got_exact_match = False;
2168 /* this is a heuristic to avoid seeking the dirptr except when
2169 absolutely necessary. It allows for a filename of about 40 chars */
2170 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2171 out_of_space = True;
2172 finished = False;
2173 } else {
2174 finished = !get_lanman2_dir_entry(conn,
2175 inbuf, outbuf,
2176 mask,dirtype,info_level,
2177 requires_resume_key,dont_descend,
2178 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2179 &last_entry_off, ea_list, ea_ctx);
2182 if (finished && out_of_space)
2183 finished = False;
2185 if (!finished && !out_of_space)
2186 numentries++;
2189 * As an optimisation if we know we aren't looking
2190 * for a wildcard name (ie. the name matches the wildcard exactly)
2191 * then we can finish on any (first) match.
2192 * This speeds up large directory searches. JRA.
2195 if(got_exact_match)
2196 finished = True;
2198 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2201 talloc_destroy(ea_ctx);
2203 /* Check if we can close the dirptr */
2204 if(close_after_request || (finished && close_if_end)) {
2205 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2206 dptr_close(&dptr_num); /* This frees up the saved mask */
2209 /* Set up the return parameter block */
2210 SSVAL(params,0,numentries);
2211 SSVAL(params,2,finished);
2212 SSVAL(params,4,0); /* Never an EA error */
2213 SSVAL(params,6,last_entry_off);
2215 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2217 if ((! *directory) && dptr_path(dptr_num))
2218 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2220 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2221 smb_fn_name(CVAL(inbuf,smb_com)),
2222 mask, directory, dirtype, numentries ) );
2224 return(-1);
2227 /****************************************************************************
2228 Reply to a TRANS2_QFSINFO (query filesystem info).
2229 ****************************************************************************/
2231 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2232 char **pparams, int total_params, char **ppdata, int total_data,
2233 unsigned int max_data_bytes)
2235 char *pdata = *ppdata;
2236 char *params = *pparams;
2237 uint16 info_level;
2238 int data_len, len;
2239 SMB_STRUCT_STAT st;
2240 char *vname = volume_label(SNUM(conn));
2241 int snum = SNUM(conn);
2242 char *fstype = lp_fstype(SNUM(conn));
2243 int quota_flag = 0;
2245 if (total_params < 2) {
2246 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2249 info_level = SVAL(params,0);
2251 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2253 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2254 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2255 return ERROR_DOS(ERRSRV,ERRinvdevice);
2258 *ppdata = (char *)SMB_REALLOC(
2259 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2260 if (*ppdata == NULL ) {
2261 return ERROR_NT(NT_STATUS_NO_MEMORY);
2264 pdata = *ppdata;
2265 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2267 switch (info_level) {
2268 case SMB_INFO_ALLOCATION:
2270 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2271 data_len = 18;
2272 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2273 return(UNIXERROR(ERRHRD,ERRgeneral));
2276 block_size = lp_block_size(snum);
2277 if (bsize < block_size) {
2278 SMB_BIG_UINT factor = block_size/bsize;
2279 bsize = block_size;
2280 dsize /= factor;
2281 dfree /= factor;
2283 if (bsize > block_size) {
2284 SMB_BIG_UINT factor = bsize/block_size;
2285 bsize = block_size;
2286 dsize *= factor;
2287 dfree *= factor;
2289 bytes_per_sector = 512;
2290 sectors_per_unit = bsize/bytes_per_sector;
2292 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2293 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2294 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2296 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2297 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2298 SIVAL(pdata,l1_cUnit,dsize);
2299 SIVAL(pdata,l1_cUnitAvail,dfree);
2300 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2301 break;
2304 case SMB_INFO_VOLUME:
2305 /* Return volume name */
2307 * Add volume serial number - hash of a combination of
2308 * the called hostname and the service name.
2310 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2312 * Win2k3 and previous mess this up by sending a name length
2313 * one byte short. I believe only older clients (OS/2 Win9x) use
2314 * this call so try fixing this by adding a terminating null to
2315 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2317 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2318 SCVAL(pdata,l2_vol_cch,len);
2319 data_len = l2_vol_szVolLabel + len;
2320 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2321 (unsigned)st.st_ctime, len, vname));
2322 break;
2324 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2325 case SMB_FS_ATTRIBUTE_INFORMATION:
2328 #if defined(HAVE_SYS_QUOTAS)
2329 quota_flag = FILE_VOLUME_QUOTAS;
2330 #endif
2332 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2333 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2334 quota_flag); /* FS ATTRIBUTES */
2336 SIVAL(pdata,4,255); /* Max filename component length */
2337 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2338 and will think we can't do long filenames */
2339 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2340 SIVAL(pdata,8,len);
2341 data_len = 12 + len;
2342 break;
2344 case SMB_QUERY_FS_LABEL_INFO:
2345 case SMB_FS_LABEL_INFORMATION:
2346 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2347 data_len = 4 + len;
2348 SIVAL(pdata,0,len);
2349 break;
2351 case SMB_QUERY_FS_VOLUME_INFO:
2352 case SMB_FS_VOLUME_INFORMATION:
2355 * Add volume serial number - hash of a combination of
2356 * the called hostname and the service name.
2358 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2359 (str_checksum(get_local_machine_name())<<16));
2361 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2362 SIVAL(pdata,12,len);
2363 data_len = 18+len;
2364 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2365 (int)strlen(vname),vname, lp_servicename(snum)));
2366 break;
2368 case SMB_QUERY_FS_SIZE_INFO:
2369 case SMB_FS_SIZE_INFORMATION:
2371 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2372 data_len = 24;
2373 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2374 return(UNIXERROR(ERRHRD,ERRgeneral));
2376 block_size = lp_block_size(snum);
2377 if (bsize < block_size) {
2378 SMB_BIG_UINT factor = block_size/bsize;
2379 bsize = block_size;
2380 dsize /= factor;
2381 dfree /= factor;
2383 if (bsize > block_size) {
2384 SMB_BIG_UINT factor = bsize/block_size;
2385 bsize = block_size;
2386 dsize *= factor;
2387 dfree *= factor;
2389 bytes_per_sector = 512;
2390 sectors_per_unit = bsize/bytes_per_sector;
2391 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2392 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2393 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2394 SBIG_UINT(pdata,0,dsize);
2395 SBIG_UINT(pdata,8,dfree);
2396 SIVAL(pdata,16,sectors_per_unit);
2397 SIVAL(pdata,20,bytes_per_sector);
2398 break;
2401 case SMB_FS_FULL_SIZE_INFORMATION:
2403 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2404 data_len = 32;
2405 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2406 return(UNIXERROR(ERRHRD,ERRgeneral));
2408 block_size = lp_block_size(snum);
2409 if (bsize < block_size) {
2410 SMB_BIG_UINT factor = block_size/bsize;
2411 bsize = block_size;
2412 dsize /= factor;
2413 dfree /= factor;
2415 if (bsize > block_size) {
2416 SMB_BIG_UINT factor = bsize/block_size;
2417 bsize = block_size;
2418 dsize *= factor;
2419 dfree *= factor;
2421 bytes_per_sector = 512;
2422 sectors_per_unit = bsize/bytes_per_sector;
2423 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2424 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2425 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2426 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2427 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2428 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2429 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2430 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2431 break;
2434 case SMB_QUERY_FS_DEVICE_INFO:
2435 case SMB_FS_DEVICE_INFORMATION:
2436 data_len = 8;
2437 SIVAL(pdata,0,0); /* dev type */
2438 SIVAL(pdata,4,0); /* characteristics */
2439 break;
2441 #ifdef HAVE_SYS_QUOTAS
2442 case SMB_FS_QUOTA_INFORMATION:
2444 * what we have to send --metze:
2446 * Unknown1: 24 NULL bytes
2447 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2448 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2449 * Quota Flags: 2 byte :
2450 * Unknown3: 6 NULL bytes
2452 * 48 bytes total
2454 * details for Quota Flags:
2456 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2457 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2458 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2459 * 0x0001 Enable Quotas: enable quota for this fs
2463 /* we need to fake up a fsp here,
2464 * because its not send in this call
2466 files_struct fsp;
2467 SMB_NTQUOTA_STRUCT quotas;
2469 ZERO_STRUCT(fsp);
2470 ZERO_STRUCT(quotas);
2472 fsp.conn = conn;
2473 fsp.fnum = -1;
2475 /* access check */
2476 if (current_user.ut.uid != 0) {
2477 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2478 lp_servicename(SNUM(conn)),conn->user));
2479 return ERROR_DOS(ERRDOS,ERRnoaccess);
2482 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2483 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2484 return ERROR_DOS(ERRSRV,ERRerror);
2487 data_len = 48;
2489 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2491 /* Unknown1 24 NULL bytes*/
2492 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2493 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2494 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2496 /* Default Soft Quota 8 bytes */
2497 SBIG_UINT(pdata,24,quotas.softlim);
2499 /* Default Hard Quota 8 bytes */
2500 SBIG_UINT(pdata,32,quotas.hardlim);
2502 /* Quota flag 2 bytes */
2503 SSVAL(pdata,40,quotas.qflags);
2505 /* Unknown3 6 NULL bytes */
2506 SSVAL(pdata,42,0);
2507 SIVAL(pdata,44,0);
2509 break;
2511 #endif /* HAVE_SYS_QUOTAS */
2512 case SMB_FS_OBJECTID_INFORMATION:
2513 data_len = 64;
2514 break;
2517 * Query the version and capabilities of the CIFS UNIX extensions
2518 * in use.
2521 case SMB_QUERY_CIFS_UNIX_INFO:
2522 if (!lp_unix_extensions()) {
2523 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2525 data_len = 12;
2526 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2527 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2528 /* We have POSIX ACLs, pathname and locking capability. */
2529 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2530 CIFS_UNIX_POSIX_ACLS_CAP|
2531 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2532 CIFS_UNIX_FCNTL_LOCKS_CAP|
2533 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2534 break;
2536 case SMB_QUERY_POSIX_FS_INFO:
2538 int rc;
2539 vfs_statvfs_struct svfs;
2541 if (!lp_unix_extensions()) {
2542 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2545 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2547 if (!rc) {
2548 data_len = 56;
2549 SIVAL(pdata,0,svfs.OptimalTransferSize);
2550 SIVAL(pdata,4,svfs.BlockSize);
2551 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2552 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2553 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2554 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2555 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2556 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2557 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2558 #ifdef EOPNOTSUPP
2559 } else if (rc == EOPNOTSUPP) {
2560 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2561 #endif /* EOPNOTSUPP */
2562 } else {
2563 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2564 return ERROR_DOS(ERRSRV,ERRerror);
2566 break;
2569 case SMB_MAC_QUERY_FS_INFO:
2571 * Thursby MAC extension... ONLY on NTFS filesystems
2572 * once we do streams then we don't need this
2574 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2575 data_len = 88;
2576 SIVAL(pdata,84,0x100); /* Don't support mac... */
2577 break;
2579 /* drop through */
2580 default:
2581 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2585 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2587 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2589 return -1;
2592 /****************************************************************************
2593 Reply to a TRANS2_SETFSINFO (set filesystem info).
2594 ****************************************************************************/
2596 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2597 char **pparams, int total_params, char **ppdata, int total_data,
2598 unsigned int max_data_bytes)
2600 char *pdata = *ppdata;
2601 char *params = *pparams;
2602 uint16 info_level;
2603 int outsize;
2605 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2607 /* */
2608 if (total_params < 4) {
2609 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2610 total_params));
2611 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2614 info_level = SVAL(params,2);
2616 switch(info_level) {
2617 case SMB_SET_CIFS_UNIX_INFO:
2619 uint16 client_unix_major;
2620 uint16 client_unix_minor;
2621 uint32 client_unix_cap_low;
2622 uint32 client_unix_cap_high;
2624 if (!lp_unix_extensions()) {
2625 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2628 /* There should be 12 bytes of capabilities set. */
2629 if (total_data < 8) {
2630 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2632 client_unix_major = SVAL(pdata,0);
2633 client_unix_minor = SVAL(pdata,2);
2634 client_unix_cap_low = IVAL(pdata,4);
2635 client_unix_cap_high = IVAL(pdata,8);
2636 /* Just print these values for now. */
2637 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2638 cap_low = 0x%x, cap_high = 0x%x\n",
2639 (unsigned int)client_unix_major,
2640 (unsigned int)client_unix_minor,
2641 (unsigned int)client_unix_cap_low,
2642 (unsigned int)client_unix_cap_high ));
2644 /* Here is where we must switch to posix pathname processing... */
2645 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2646 lp_set_posix_pathnames();
2647 mangle_change_to_posix();
2650 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2651 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2652 /* Client that knows how to do posix locks,
2653 * but not posix open/mkdir operations. Set a
2654 * default type for read/write checks. */
2656 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2659 break;
2661 case SMB_FS_QUOTA_INFORMATION:
2663 files_struct *fsp = NULL;
2664 SMB_NTQUOTA_STRUCT quotas;
2666 ZERO_STRUCT(quotas);
2668 /* access check */
2669 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2670 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2671 lp_servicename(SNUM(conn)),conn->user));
2672 return ERROR_DOS(ERRSRV,ERRaccess);
2675 /* note: normaly there're 48 bytes,
2676 * but we didn't use the last 6 bytes for now
2677 * --metze
2679 fsp = file_fsp(params,0);
2680 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2681 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2682 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2685 if (total_data < 42) {
2686 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2687 total_data));
2688 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2691 /* unknown_1 24 NULL bytes in pdata*/
2693 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2694 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2695 #ifdef LARGE_SMB_OFF_T
2696 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2697 #else /* LARGE_SMB_OFF_T */
2698 if ((IVAL(pdata,28) != 0)&&
2699 ((quotas.softlim != 0xFFFFFFFF)||
2700 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2701 /* more than 32 bits? */
2702 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2704 #endif /* LARGE_SMB_OFF_T */
2706 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2707 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2708 #ifdef LARGE_SMB_OFF_T
2709 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2710 #else /* LARGE_SMB_OFF_T */
2711 if ((IVAL(pdata,36) != 0)&&
2712 ((quotas.hardlim != 0xFFFFFFFF)||
2713 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2714 /* more than 32 bits? */
2715 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2717 #endif /* LARGE_SMB_OFF_T */
2719 /* quota_flags 2 bytes **/
2720 quotas.qflags = SVAL(pdata,40);
2722 /* unknown_2 6 NULL bytes follow*/
2724 /* now set the quotas */
2725 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2726 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2727 return ERROR_DOS(ERRSRV,ERRerror);
2730 break;
2732 default:
2733 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2734 info_level));
2735 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2736 break;
2740 * sending this reply works fine,
2741 * but I'm not sure it's the same
2742 * like windows do...
2743 * --metze
2745 outsize = set_message(outbuf,10,0,True);
2747 return outsize;
2750 #if defined(HAVE_POSIX_ACLS)
2751 /****************************************************************************
2752 Utility function to count the number of entries in a POSIX acl.
2753 ****************************************************************************/
2755 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2757 unsigned int ace_count = 0;
2758 int entry_id = SMB_ACL_FIRST_ENTRY;
2759 SMB_ACL_ENTRY_T entry;
2761 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2762 /* get_next... */
2763 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2764 entry_id = SMB_ACL_NEXT_ENTRY;
2766 ace_count++;
2768 return ace_count;
2771 /****************************************************************************
2772 Utility function to marshall a POSIX acl into wire format.
2773 ****************************************************************************/
2775 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2777 int entry_id = SMB_ACL_FIRST_ENTRY;
2778 SMB_ACL_ENTRY_T entry;
2780 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2781 SMB_ACL_TAG_T tagtype;
2782 SMB_ACL_PERMSET_T permset;
2783 unsigned char perms = 0;
2784 unsigned int own_grp;
2786 /* get_next... */
2787 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2788 entry_id = SMB_ACL_NEXT_ENTRY;
2791 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2792 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2793 return False;
2796 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2797 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2798 return False;
2801 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2802 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2803 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2805 SCVAL(pdata,1,perms);
2807 switch (tagtype) {
2808 case SMB_ACL_USER_OBJ:
2809 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2810 own_grp = (unsigned int)pst->st_uid;
2811 SIVAL(pdata,2,own_grp);
2812 SIVAL(pdata,6,0);
2813 break;
2814 case SMB_ACL_USER:
2816 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2817 if (!puid) {
2818 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2820 own_grp = (unsigned int)*puid;
2821 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2822 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2823 SIVAL(pdata,2,own_grp);
2824 SIVAL(pdata,6,0);
2825 break;
2827 case SMB_ACL_GROUP_OBJ:
2828 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2829 own_grp = (unsigned int)pst->st_gid;
2830 SIVAL(pdata,2,own_grp);
2831 SIVAL(pdata,6,0);
2832 break;
2833 case SMB_ACL_GROUP:
2835 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2836 if (!pgid) {
2837 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2839 own_grp = (unsigned int)*pgid;
2840 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2841 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2842 SIVAL(pdata,2,own_grp);
2843 SIVAL(pdata,6,0);
2844 break;
2846 case SMB_ACL_MASK:
2847 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2848 SIVAL(pdata,2,0xFFFFFFFF);
2849 SIVAL(pdata,6,0xFFFFFFFF);
2850 break;
2851 case SMB_ACL_OTHER:
2852 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2853 SIVAL(pdata,2,0xFFFFFFFF);
2854 SIVAL(pdata,6,0xFFFFFFFF);
2855 break;
2856 default:
2857 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2858 return False;
2860 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2863 return True;
2865 #endif
2867 /****************************************************************************
2868 Store the FILE_UNIX_BASIC info.
2869 ****************************************************************************/
2871 static char *store_file_unix_basic(connection_struct *conn,
2872 char *pdata,
2873 files_struct *fsp,
2874 SMB_STRUCT_STAT *psbuf)
2876 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2877 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
2879 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
2880 pdata += 8;
2882 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2883 pdata += 8;
2885 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
2886 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
2887 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
2888 pdata += 24;
2890 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
2891 SIVAL(pdata,4,0);
2892 pdata += 8;
2894 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
2895 SIVAL(pdata,4,0);
2896 pdata += 8;
2898 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
2899 pdata += 4;
2901 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
2902 SIVAL(pdata,4,0);
2903 pdata += 8;
2905 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
2906 SIVAL(pdata,4,0);
2907 pdata += 8;
2909 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
2910 pdata += 8;
2912 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
2913 SIVAL(pdata,4,0);
2914 pdata += 8;
2916 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
2917 SIVAL(pdata,4,0);
2918 pdata += 8;
2920 return pdata;
2923 /****************************************************************************
2924 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2925 file name or file id).
2926 ****************************************************************************/
2928 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2929 unsigned int tran_call,
2930 char **pparams, int total_params, char **ppdata, int total_data,
2931 unsigned int max_data_bytes)
2933 char *params = *pparams;
2934 char *pdata = *ppdata;
2935 uint16 info_level;
2936 int mode=0;
2937 int nlink;
2938 SMB_OFF_T file_size=0;
2939 SMB_BIG_UINT allocation_size=0;
2940 unsigned int data_size = 0;
2941 unsigned int param_size = 2;
2942 SMB_STRUCT_STAT sbuf;
2943 pstring fname, dos_fname;
2944 char *fullpathname;
2945 char *base_name;
2946 char *p;
2947 SMB_OFF_T pos = 0;
2948 BOOL delete_pending = False;
2949 int len;
2950 time_t create_time, mtime, atime;
2951 struct timespec create_time_ts, mtime_ts, atime_ts;
2952 files_struct *fsp = NULL;
2953 TALLOC_CTX *data_ctx = NULL;
2954 struct ea_list *ea_list = NULL;
2955 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2956 char *lock_data = NULL;
2958 if (!params)
2959 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2961 ZERO_STRUCT(sbuf);
2963 if (tran_call == TRANSACT2_QFILEINFO) {
2964 if (total_params < 4) {
2965 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2968 fsp = file_fsp(params,0);
2969 info_level = SVAL(params,2);
2971 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2973 if(fsp && (fsp->fake_file_handle)) {
2975 * This is actually for the QUOTA_FAKE_FILE --metze
2978 pstrcpy(fname, fsp->fsp_name);
2979 /* We know this name is ok, it's already passed the checks. */
2981 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2983 * This is actually a QFILEINFO on a directory
2984 * handle (returned from an NT SMB). NT5.0 seems
2985 * to do this call. JRA.
2987 /* We know this name is ok, it's already passed the checks. */
2988 pstrcpy(fname, fsp->fsp_name);
2990 if (INFO_LEVEL_IS_UNIX(info_level)) {
2991 /* Always do lstat for UNIX calls. */
2992 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2993 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2994 return UNIXERROR(ERRDOS,ERRbadpath);
2996 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2997 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2998 return UNIXERROR(ERRDOS,ERRbadpath);
3001 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3002 } else {
3004 * Original code - this is an open file.
3006 CHECK_FSP(fsp,conn);
3008 pstrcpy(fname, fsp->fsp_name);
3009 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3010 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3011 return(UNIXERROR(ERRDOS,ERRbadfid));
3013 pos = fsp->fh->position_information;
3014 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3015 access_mask = fsp->access_mask;
3017 } else {
3018 NTSTATUS status = NT_STATUS_OK;
3020 /* qpathinfo */
3021 if (total_params < 7) {
3022 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3025 info_level = SVAL(params,0);
3027 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3029 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3030 if (!NT_STATUS_IS_OK(status)) {
3031 return ERROR_NT(status);
3034 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
3036 status = unix_convert(conn, fname, False, NULL, &sbuf);
3037 if (!NT_STATUS_IS_OK(status)) {
3038 return ERROR_NT(status);
3040 status = check_name(conn, fname);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3043 return ERROR_NT(status);
3046 if (INFO_LEVEL_IS_UNIX(info_level)) {
3047 /* Always do lstat for UNIX calls. */
3048 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3049 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3050 return UNIXERROR(ERRDOS,ERRbadpath);
3052 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3053 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3054 return UNIXERROR(ERRDOS,ERRbadpath);
3057 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3058 if (delete_pending) {
3059 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3063 nlink = sbuf.st_nlink;
3065 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3066 /* NTFS does not seem to count ".." */
3067 nlink -= 1;
3070 if ((nlink > 0) && delete_pending) {
3071 nlink -= 1;
3074 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3075 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3078 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3079 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3081 p = strrchr_m(fname,'/');
3082 if (!p)
3083 base_name = fname;
3084 else
3085 base_name = p+1;
3087 mode = dos_mode(conn,fname,&sbuf);
3088 if (!mode)
3089 mode = FILE_ATTRIBUTE_NORMAL;
3091 fullpathname = fname;
3092 if (!(mode & aDIR))
3093 file_size = get_file_size(sbuf);
3095 /* Pull out any data sent here before we realloc. */
3096 switch (info_level) {
3097 case SMB_INFO_QUERY_EAS_FROM_LIST:
3099 /* Pull any EA list from the data portion. */
3100 uint32 ea_size;
3102 if (total_data < 4) {
3103 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3105 ea_size = IVAL(pdata,0);
3107 if (total_data > 0 && ea_size != total_data) {
3108 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3109 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3110 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3113 if (!lp_ea_support(SNUM(conn))) {
3114 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3117 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3118 return ERROR_NT(NT_STATUS_NO_MEMORY);
3121 /* Pull out the list of names. */
3122 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3123 if (!ea_list) {
3124 talloc_destroy(data_ctx);
3125 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3127 break;
3130 case SMB_QUERY_POSIX_LOCK:
3132 if (fsp == NULL || fsp->fh->fd == -1) {
3133 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3136 if (total_data != POSIX_LOCK_DATA_SIZE) {
3137 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3140 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3141 return ERROR_NT(NT_STATUS_NO_MEMORY);
3144 /* Copy the lock range data. */
3145 lock_data = (char *)talloc_memdup(
3146 data_ctx, pdata, total_data);
3147 if (!lock_data) {
3148 talloc_destroy(data_ctx);
3149 return ERROR_NT(NT_STATUS_NO_MEMORY);
3152 default:
3153 break;
3156 *pparams = (char *)SMB_REALLOC(*pparams,2);
3157 if (*pparams == NULL) {
3158 talloc_destroy(data_ctx);
3159 return ERROR_NT(NT_STATUS_NO_MEMORY);
3161 params = *pparams;
3162 SSVAL(params,0,0);
3163 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3164 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3165 if (*ppdata == NULL ) {
3166 talloc_destroy(data_ctx);
3167 return ERROR_NT(NT_STATUS_NO_MEMORY);
3169 pdata = *ppdata;
3171 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3172 mtime_ts = get_mtimespec(&sbuf);
3173 atime_ts = get_atimespec(&sbuf);
3175 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3177 if (fsp) {
3178 if (fsp->pending_modtime) {
3179 /* the pending modtime overrides the current modtime */
3180 mtime_ts.tv_sec = fsp->pending_modtime;
3181 mtime_ts.tv_nsec = 0;
3183 } else {
3184 /* Do we have this path open ? */
3185 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3186 if (fsp1 && fsp1->pending_modtime) {
3187 /* the pending modtime overrides the current modtime */
3188 mtime_ts.tv_sec = fsp1->pending_modtime;
3189 mtime_ts.tv_nsec = 0;
3191 if (fsp1 && fsp1->initial_allocation_size) {
3192 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3196 if (lp_dos_filetime_resolution(SNUM(conn))) {
3197 dos_filetime_timespec(&create_time_ts);
3198 dos_filetime_timespec(&mtime_ts);
3199 dos_filetime_timespec(&atime_ts);
3202 create_time = convert_timespec_to_time_t(create_time_ts);
3203 mtime = convert_timespec_to_time_t(mtime_ts);
3204 atime = convert_timespec_to_time_t(atime_ts);
3206 /* NT expects the name to be in an exact form of the *full*
3207 filename. See the trans2 torture test */
3208 if (strequal(base_name,".")) {
3209 pstrcpy(dos_fname, "\\");
3210 } else {
3211 pstr_sprintf(dos_fname, "\\%s", fname);
3212 string_replace(dos_fname, '/', '\\');
3215 switch (info_level) {
3216 case SMB_INFO_STANDARD:
3217 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3218 data_size = 22;
3219 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3220 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3221 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3222 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3223 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3224 SSVAL(pdata,l1_attrFile,mode);
3225 break;
3227 case SMB_INFO_QUERY_EA_SIZE:
3229 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3230 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3231 data_size = 26;
3232 srv_put_dos_date2(pdata,0,create_time);
3233 srv_put_dos_date2(pdata,4,atime);
3234 srv_put_dos_date2(pdata,8,mtime); /* write time */
3235 SIVAL(pdata,12,(uint32)file_size);
3236 SIVAL(pdata,16,(uint32)allocation_size);
3237 SSVAL(pdata,20,mode);
3238 SIVAL(pdata,22,ea_size);
3239 break;
3242 case SMB_INFO_IS_NAME_VALID:
3243 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3244 if (tran_call == TRANSACT2_QFILEINFO) {
3245 /* os/2 needs this ? really ?*/
3246 return ERROR_DOS(ERRDOS,ERRbadfunc);
3248 data_size = 0;
3249 param_size = 0;
3250 break;
3252 case SMB_INFO_QUERY_EAS_FROM_LIST:
3254 size_t total_ea_len = 0;
3255 struct ea_list *ea_file_list = NULL;
3257 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3259 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3260 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3262 if (!ea_list || (total_ea_len > data_size)) {
3263 talloc_destroy(data_ctx);
3264 data_size = 4;
3265 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3266 break;
3269 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3270 talloc_destroy(data_ctx);
3271 break;
3274 case SMB_INFO_QUERY_ALL_EAS:
3276 /* We have data_size bytes to put EA's into. */
3277 size_t total_ea_len = 0;
3279 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3281 data_ctx = talloc_init("ea_ctx");
3282 if (!data_ctx) {
3283 return ERROR_NT(NT_STATUS_NO_MEMORY);
3286 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3287 if (!ea_list || (total_ea_len > data_size)) {
3288 talloc_destroy(data_ctx);
3289 data_size = 4;
3290 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3291 break;
3294 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3295 talloc_destroy(data_ctx);
3296 break;
3299 case SMB_FILE_BASIC_INFORMATION:
3300 case SMB_QUERY_FILE_BASIC_INFO:
3302 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3303 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3304 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3305 } else {
3306 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3307 data_size = 40;
3308 SIVAL(pdata,36,0);
3310 put_long_date_timespec(pdata,create_time_ts);
3311 put_long_date_timespec(pdata+8,atime_ts);
3312 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3313 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3314 SIVAL(pdata,32,mode);
3316 DEBUG(5,("SMB_QFBI - "));
3317 DEBUG(5,("create: %s ", ctime(&create_time)));
3318 DEBUG(5,("access: %s ", ctime(&atime)));
3319 DEBUG(5,("write: %s ", ctime(&mtime)));
3320 DEBUG(5,("change: %s ", ctime(&mtime)));
3321 DEBUG(5,("mode: %x\n", mode));
3322 break;
3324 case SMB_FILE_STANDARD_INFORMATION:
3325 case SMB_QUERY_FILE_STANDARD_INFO:
3327 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3328 data_size = 24;
3329 SOFF_T(pdata,0,allocation_size);
3330 SOFF_T(pdata,8,file_size);
3331 SIVAL(pdata,16,nlink);
3332 SCVAL(pdata,20,delete_pending?1:0);
3333 SCVAL(pdata,21,(mode&aDIR)?1:0);
3334 SSVAL(pdata,22,0); /* Padding. */
3335 break;
3337 case SMB_FILE_EA_INFORMATION:
3338 case SMB_QUERY_FILE_EA_INFO:
3340 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3341 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3342 data_size = 4;
3343 SIVAL(pdata,0,ea_size);
3344 break;
3347 /* Get the 8.3 name - used if NT SMB was negotiated. */
3348 case SMB_QUERY_FILE_ALT_NAME_INFO:
3349 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3351 pstring short_name;
3353 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3354 pstrcpy(short_name,base_name);
3355 /* Mangle if not already 8.3 */
3356 if(!mangle_is_8_3(short_name, True, conn->params)) {
3357 mangle_map(short_name,True,True,conn->params);
3359 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3360 data_size = 4 + len;
3361 SIVAL(pdata,0,len);
3362 break;
3365 case SMB_QUERY_FILE_NAME_INFO:
3367 this must be *exactly* right for ACLs on mapped drives to work
3369 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3370 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3371 data_size = 4 + len;
3372 SIVAL(pdata,0,len);
3373 break;
3375 case SMB_FILE_ALLOCATION_INFORMATION:
3376 case SMB_QUERY_FILE_ALLOCATION_INFO:
3377 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3378 data_size = 8;
3379 SOFF_T(pdata,0,allocation_size);
3380 break;
3382 case SMB_FILE_END_OF_FILE_INFORMATION:
3383 case SMB_QUERY_FILE_END_OF_FILEINFO:
3384 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3385 data_size = 8;
3386 SOFF_T(pdata,0,file_size);
3387 break;
3389 case SMB_QUERY_FILE_ALL_INFO:
3390 case SMB_FILE_ALL_INFORMATION:
3392 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3393 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3394 put_long_date_timespec(pdata,create_time_ts);
3395 put_long_date_timespec(pdata+8,atime_ts);
3396 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3397 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3398 SIVAL(pdata,32,mode);
3399 SIVAL(pdata,36,0); /* padding. */
3400 pdata += 40;
3401 SOFF_T(pdata,0,allocation_size);
3402 SOFF_T(pdata,8,file_size);
3403 SIVAL(pdata,16,nlink);
3404 SCVAL(pdata,20,delete_pending);
3405 SCVAL(pdata,21,(mode&aDIR)?1:0);
3406 SSVAL(pdata,22,0);
3407 pdata += 24;
3408 SIVAL(pdata,0,ea_size);
3409 pdata += 4; /* EA info */
3410 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3411 SIVAL(pdata,0,len);
3412 pdata += 4 + len;
3413 data_size = PTR_DIFF(pdata,(*ppdata));
3414 break;
3416 case SMB_FILE_INTERNAL_INFORMATION:
3417 /* This should be an index number - looks like
3418 dev/ino to me :-)
3420 I think this causes us to fail the IFSKIT
3421 BasicFileInformationTest. -tpot */
3423 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3424 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3425 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3426 data_size = 8;
3427 break;
3429 case SMB_FILE_ACCESS_INFORMATION:
3430 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3431 SIVAL(pdata,0,access_mask);
3432 data_size = 4;
3433 break;
3435 case SMB_FILE_NAME_INFORMATION:
3436 /* Pathname with leading '\'. */
3438 size_t byte_len;
3439 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3440 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3441 SIVAL(pdata,0,byte_len);
3442 data_size = 4 + byte_len;
3443 break;
3446 case SMB_FILE_DISPOSITION_INFORMATION:
3447 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3448 data_size = 1;
3449 SCVAL(pdata,0,delete_pending);
3450 break;
3452 case SMB_FILE_POSITION_INFORMATION:
3453 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3454 data_size = 8;
3455 SOFF_T(pdata,0,pos);
3456 break;
3458 case SMB_FILE_MODE_INFORMATION:
3459 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3460 SIVAL(pdata,0,mode);
3461 data_size = 4;
3462 break;
3464 case SMB_FILE_ALIGNMENT_INFORMATION:
3465 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3466 SIVAL(pdata,0,0); /* No alignment needed. */
3467 data_size = 4;
3468 break;
3470 #if 0
3472 * NT4 server just returns "invalid query" to this - if we try to answer
3473 * it then NTws gets a BSOD! (tridge).
3474 * W2K seems to want this. JRA.
3476 case SMB_QUERY_FILE_STREAM_INFO:
3477 #endif
3478 case SMB_FILE_STREAM_INFORMATION:
3479 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3480 if (mode & aDIR) {
3481 data_size = 0;
3482 } else {
3483 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3484 SIVAL(pdata,0,0); /* ??? */
3485 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3486 SOFF_T(pdata,8,file_size);
3487 SIVAL(pdata,16,allocation_size);
3488 SIVAL(pdata,20,0); /* ??? */
3489 data_size = 24 + byte_len;
3491 break;
3493 case SMB_QUERY_COMPRESSION_INFO:
3494 case SMB_FILE_COMPRESSION_INFORMATION:
3495 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3496 SOFF_T(pdata,0,file_size);
3497 SIVAL(pdata,8,0); /* ??? */
3498 SIVAL(pdata,12,0); /* ??? */
3499 data_size = 16;
3500 break;
3502 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3503 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3504 put_long_date_timespec(pdata,create_time_ts);
3505 put_long_date_timespec(pdata+8,atime_ts);
3506 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3507 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3508 SIVAL(pdata,32,allocation_size);
3509 SOFF_T(pdata,40,file_size);
3510 SIVAL(pdata,48,mode);
3511 SIVAL(pdata,52,0); /* ??? */
3512 data_size = 56;
3513 break;
3515 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3516 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3517 SIVAL(pdata,0,mode);
3518 SIVAL(pdata,4,0);
3519 data_size = 8;
3520 break;
3523 * CIFS UNIX Extensions.
3526 case SMB_QUERY_FILE_UNIX_BASIC:
3528 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3529 data_size = PTR_DIFF(pdata,(*ppdata));
3532 int i;
3533 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3535 for (i=0; i<100; i++)
3536 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3537 DEBUG(4,("\n"));
3540 break;
3542 case SMB_QUERY_FILE_UNIX_LINK:
3544 pstring buffer;
3546 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3547 #ifdef S_ISLNK
3548 if(!S_ISLNK(sbuf.st_mode))
3549 return(UNIXERROR(ERRSRV,ERRbadlink));
3550 #else
3551 return(UNIXERROR(ERRDOS,ERRbadlink));
3552 #endif
3553 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3554 if (len == -1)
3555 return(UNIXERROR(ERRDOS,ERRnoaccess));
3556 buffer[len] = 0;
3557 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3558 pdata += len;
3559 data_size = PTR_DIFF(pdata,(*ppdata));
3561 break;
3564 #if defined(HAVE_POSIX_ACLS)
3565 case SMB_QUERY_POSIX_ACL:
3567 SMB_ACL_T file_acl = NULL;
3568 SMB_ACL_T def_acl = NULL;
3569 uint16 num_file_acls = 0;
3570 uint16 num_def_acls = 0;
3572 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3573 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3574 } else {
3575 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3578 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3579 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3580 fname ));
3581 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3584 if (S_ISDIR(sbuf.st_mode)) {
3585 if (fsp && fsp->is_directory) {
3586 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3587 } else {
3588 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3590 def_acl = free_empty_sys_acl(conn, def_acl);
3593 num_file_acls = count_acl_entries(conn, file_acl);
3594 num_def_acls = count_acl_entries(conn, def_acl);
3596 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3597 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3598 data_size,
3599 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3600 SMB_POSIX_ACL_HEADER_SIZE) ));
3601 if (file_acl) {
3602 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3604 if (def_acl) {
3605 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3607 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3610 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3611 SSVAL(pdata,2,num_file_acls);
3612 SSVAL(pdata,4,num_def_acls);
3613 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3614 if (file_acl) {
3615 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3617 if (def_acl) {
3618 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3620 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3622 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3623 if (file_acl) {
3624 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3626 if (def_acl) {
3627 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3629 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3632 if (file_acl) {
3633 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3635 if (def_acl) {
3636 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3638 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3639 break;
3641 #endif
3644 case SMB_QUERY_POSIX_LOCK:
3646 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3647 SMB_BIG_UINT count;
3648 SMB_BIG_UINT offset;
3649 uint32 lock_pid;
3650 enum brl_type lock_type;
3652 if (total_data != POSIX_LOCK_DATA_SIZE) {
3653 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3656 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3657 case POSIX_LOCK_TYPE_READ:
3658 lock_type = READ_LOCK;
3659 break;
3660 case POSIX_LOCK_TYPE_WRITE:
3661 lock_type = WRITE_LOCK;
3662 break;
3663 case POSIX_LOCK_TYPE_UNLOCK:
3664 default:
3665 /* There's no point in asking for an unlock... */
3666 talloc_destroy(data_ctx);
3667 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3670 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3671 #if defined(HAVE_LONGLONG)
3672 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3673 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3674 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3675 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3676 #else /* HAVE_LONGLONG */
3677 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3678 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3679 #endif /* HAVE_LONGLONG */
3681 status = query_lock(fsp,
3682 &lock_pid,
3683 &count,
3684 &offset,
3685 &lock_type,
3686 POSIX_LOCK);
3688 if (ERROR_WAS_LOCK_DENIED(status)) {
3689 /* Here we need to report who has it locked... */
3690 data_size = POSIX_LOCK_DATA_SIZE;
3692 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3693 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3694 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3695 #if defined(HAVE_LONGLONG)
3696 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3697 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3698 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3699 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3700 #else /* HAVE_LONGLONG */
3701 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3702 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3703 #endif /* HAVE_LONGLONG */
3705 } else if (NT_STATUS_IS_OK(status)) {
3706 /* For success we just return a copy of what we sent
3707 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3708 data_size = POSIX_LOCK_DATA_SIZE;
3709 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3710 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3711 } else {
3712 return ERROR_NT(status);
3714 break;
3717 default:
3718 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3721 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3723 return(-1);
3726 /****************************************************************************
3727 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3728 code.
3729 ****************************************************************************/
3731 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3733 SMB_STRUCT_STAT sbuf1, sbuf2;
3734 pstring last_component_oldname;
3735 pstring last_component_newname;
3736 NTSTATUS status = NT_STATUS_OK;
3738 ZERO_STRUCT(sbuf1);
3739 ZERO_STRUCT(sbuf2);
3741 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3742 if (!NT_STATUS_IS_OK(status)) {
3743 return status;
3746 /* source must already exist. */
3747 if (!VALID_STAT(sbuf1)) {
3748 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3751 status = check_name(conn, oldname);
3752 if (!NT_STATUS_IS_OK(status)) {
3753 return NT_STATUS_ACCESS_DENIED;
3756 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
3757 if (!NT_STATUS_IS_OK(status)) {
3758 return status;
3761 /* Disallow if newname already exists. */
3762 if (VALID_STAT(sbuf2)) {
3763 return NT_STATUS_OBJECT_NAME_COLLISION;
3766 status = check_name(conn, newname);
3767 if (!NT_STATUS_IS_OK(status)) {
3768 return NT_STATUS_ACCESS_DENIED;
3771 /* No links from a directory. */
3772 if (S_ISDIR(sbuf1.st_mode)) {
3773 return NT_STATUS_FILE_IS_A_DIRECTORY;
3776 /* Ensure this is within the share. */
3777 status = reduce_name(conn, oldname);
3778 if (!NT_STATUS_IS_OK(status)) {
3779 return status;
3782 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3784 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3785 status = map_nt_error_from_unix(errno);
3786 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3787 nt_errstr(status), newname, oldname));
3790 return status;
3793 /****************************************************************************
3794 Deal with setting the time from any of the setfilepathinfo functions.
3795 ****************************************************************************/
3797 static NTSTATUS smb_set_file_time(connection_struct *conn,
3798 files_struct *fsp,
3799 const char *fname,
3800 const SMB_STRUCT_STAT *psbuf,
3801 struct utimbuf tvs)
3803 uint32 action =
3804 FILE_NOTIFY_CHANGE_LAST_ACCESS
3805 |FILE_NOTIFY_CHANGE_LAST_WRITE;
3808 if (!VALID_STAT(*psbuf)) {
3809 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3812 /* get some defaults (no modifications) if any info is zero or -1. */
3813 if (null_mtime(tvs.actime)) {
3814 tvs.actime = psbuf->st_atime;
3815 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3818 if (null_mtime(tvs.modtime)) {
3819 tvs.modtime = psbuf->st_mtime;
3820 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3823 DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime)));
3824 DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime)));
3827 * Try and set the times of this file if
3828 * they are different from the current values.
3831 if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) {
3832 return NT_STATUS_OK;
3835 if(fsp != NULL) {
3837 * This was a setfileinfo on an open file.
3838 * NT does this a lot. We also need to
3839 * set the time here, as it can be read by
3840 * FindFirst/FindNext and with the patch for bug #2045
3841 * in smbd/fileio.c it ensures that this timestamp is
3842 * kept sticky even after a write. We save the request
3843 * away and will set it on file close and after a write. JRA.
3846 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3847 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3848 fsp_set_pending_modtime(fsp, tvs.modtime);
3852 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3854 if(file_utime(conn, fname, &tvs)!=0) {
3855 return map_nt_error_from_unix(errno);
3857 if (action != 0) {
3858 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
3860 return NT_STATUS_OK;
3863 /****************************************************************************
3864 Deal with setting the dosmode from any of the setfilepathinfo functions.
3865 ****************************************************************************/
3867 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3868 const char *fname,
3869 SMB_STRUCT_STAT *psbuf,
3870 uint32 dosmode)
3872 if (!VALID_STAT(*psbuf)) {
3873 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3876 if (dosmode) {
3877 if (S_ISDIR(psbuf->st_mode)) {
3878 dosmode |= aDIR;
3879 } else {
3880 dosmode &= ~aDIR;
3884 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
3886 /* check the mode isn't different, before changing it */
3887 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
3889 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
3890 fname, (unsigned int)dosmode ));
3892 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
3893 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
3894 fname, strerror(errno)));
3895 return map_nt_error_from_unix(errno);
3898 return NT_STATUS_OK;
3901 /****************************************************************************
3902 Deal with setting the size from any of the setfilepathinfo functions.
3903 ****************************************************************************/
3905 static NTSTATUS smb_set_file_size(connection_struct *conn,
3906 files_struct *fsp,
3907 const char *fname,
3908 SMB_STRUCT_STAT *psbuf,
3909 SMB_OFF_T size)
3911 NTSTATUS status = NT_STATUS_OK;
3912 files_struct *new_fsp = NULL;
3914 if (!VALID_STAT(*psbuf)) {
3915 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3918 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
3920 if (size == get_file_size(*psbuf)) {
3921 return NT_STATUS_OK;
3924 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
3925 fname, (double)size ));
3927 if (fsp && fsp->fh->fd != -1) {
3928 /* Handle based call. */
3929 if (vfs_set_filelen(fsp, size) == -1) {
3930 return map_nt_error_from_unix(errno);
3932 return NT_STATUS_OK;
3935 status = open_file_ntcreate(conn, fname, psbuf,
3936 FILE_WRITE_DATA,
3937 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3938 FILE_OPEN,
3940 FILE_ATTRIBUTE_NORMAL,
3941 FORCE_OPLOCK_BREAK_TO_NONE,
3942 NULL, &new_fsp);
3944 if (!NT_STATUS_IS_OK(status)) {
3945 /* NB. We check for open_was_deferred in the caller. */
3946 return status;
3949 if (vfs_set_filelen(new_fsp, size) == -1) {
3950 status = map_nt_error_from_unix(errno);
3951 close_file(new_fsp,NORMAL_CLOSE);
3952 return status;
3955 close_file(new_fsp,NORMAL_CLOSE);
3956 return NT_STATUS_OK;
3959 /****************************************************************************
3960 Deal with SMB_INFO_SET_EA.
3961 ****************************************************************************/
3963 static NTSTATUS smb_info_set_ea(connection_struct *conn,
3964 const char *pdata,
3965 int total_data,
3966 files_struct *fsp,
3967 const char *fname)
3969 struct ea_list *ea_list = NULL;
3970 TALLOC_CTX *ctx = NULL;
3971 NTSTATUS status = NT_STATUS_OK;
3973 if (total_data < 10) {
3975 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3976 length. They seem to have no effect. Bug #3212. JRA */
3978 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3979 /* We're done. We only get EA info in this call. */
3980 return NT_STATUS_OK;
3983 return NT_STATUS_INVALID_PARAMETER;
3986 if (IVAL(pdata,0) > total_data) {
3987 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
3988 IVAL(pdata,0), (unsigned int)total_data));
3989 return NT_STATUS_INVALID_PARAMETER;
3992 ctx = talloc_init("SMB_INFO_SET_EA");
3993 if (!ctx) {
3994 return NT_STATUS_NO_MEMORY;
3996 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3997 if (!ea_list) {
3998 talloc_destroy(ctx);
3999 return NT_STATUS_INVALID_PARAMETER;
4001 status = set_ea(conn, fsp, fname, ea_list);
4002 talloc_destroy(ctx);
4004 return status;
4007 /****************************************************************************
4008 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4009 ****************************************************************************/
4011 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4012 const char *pdata,
4013 int total_data,
4014 files_struct *fsp,
4015 const char *fname,
4016 SMB_STRUCT_STAT *psbuf)
4018 NTSTATUS status = NT_STATUS_OK;
4019 BOOL delete_on_close;
4020 uint32 dosmode = 0;
4022 if (total_data < 1) {
4023 return NT_STATUS_INVALID_PARAMETER;
4026 if (fsp == NULL) {
4027 return NT_STATUS_INVALID_HANDLE;
4030 delete_on_close = (CVAL(pdata,0) ? True : False);
4031 dosmode = dos_mode(conn, fname, psbuf);
4033 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 return status;
4039 /* The set is across all open files on this dev/inode pair. */
4040 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4041 return NT_STATUS_ACCESS_DENIED;
4043 return NT_STATUS_OK;
4046 /****************************************************************************
4047 Deal with SMB_FILE_POSITION_INFORMATION.
4048 ****************************************************************************/
4050 static NTSTATUS smb_file_position_information(connection_struct *conn,
4051 const char *pdata,
4052 int total_data,
4053 files_struct *fsp)
4055 SMB_BIG_UINT position_information;
4057 if (total_data < 8) {
4058 return NT_STATUS_INVALID_PARAMETER;
4061 if (fsp == NULL) {
4062 /* Ignore on pathname based set. */
4063 return NT_STATUS_OK;
4066 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4067 #ifdef LARGE_SMB_OFF_T
4068 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4069 #else /* LARGE_SMB_OFF_T */
4070 if (IVAL(pdata,4) != 0) {
4071 /* more than 32 bits? */
4072 return NT_STATUS_INVALID_PARAMETER;
4074 #endif /* LARGE_SMB_OFF_T */
4076 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4077 fsp->fsp_name, (double)position_information ));
4078 fsp->fh->position_information = position_information;
4079 return NT_STATUS_OK;
4082 /****************************************************************************
4083 Deal with SMB_FILE_MODE_INFORMATION.
4084 ****************************************************************************/
4086 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4087 const char *pdata,
4088 int total_data)
4090 uint32 mode;
4092 if (total_data < 4) {
4093 return NT_STATUS_INVALID_PARAMETER;
4095 mode = IVAL(pdata,0);
4096 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4097 return NT_STATUS_INVALID_PARAMETER;
4099 return NT_STATUS_OK;
4102 /****************************************************************************
4103 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4104 ****************************************************************************/
4106 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4107 char *inbuf,
4108 const char *pdata,
4109 int total_data,
4110 const char *fname)
4112 pstring link_target;
4113 const char *newname = fname;
4114 NTSTATUS status = NT_STATUS_OK;
4116 /* Set a symbolic link. */
4117 /* Don't allow this if follow links is false. */
4119 if (total_data == 0) {
4120 return NT_STATUS_INVALID_PARAMETER;
4123 if (!lp_symlinks(SNUM(conn))) {
4124 return NT_STATUS_ACCESS_DENIED;
4127 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4129 /* !widelinks forces the target path to be within the share. */
4130 /* This means we can interpret the target as a pathname. */
4131 if (!lp_widelinks(SNUM(conn))) {
4132 pstring rel_name;
4133 char *last_dirp = NULL;
4135 unix_format(link_target);
4136 if (*link_target == '/') {
4137 /* No absolute paths allowed. */
4138 return NT_STATUS_ACCESS_DENIED;
4140 pstrcpy(rel_name, newname);
4141 last_dirp = strrchr_m(rel_name, '/');
4142 if (last_dirp) {
4143 last_dirp[1] = '\0';
4144 } else {
4145 pstrcpy(rel_name, "./");
4147 pstrcat(rel_name, link_target);
4149 status = check_name(conn, rel_name);
4150 if (!NT_STATUS_IS_OK(status)) {
4151 return status;
4155 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4156 newname, link_target ));
4158 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4159 return map_nt_error_from_unix(errno);
4162 return NT_STATUS_OK;
4165 /****************************************************************************
4166 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4167 ****************************************************************************/
4169 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4170 char *inbuf,
4171 char *outbuf,
4172 const char *pdata,
4173 int total_data,
4174 pstring fname)
4176 pstring oldname;
4177 NTSTATUS status = NT_STATUS_OK;
4179 /* Set a hard link. */
4180 if (total_data == 0) {
4181 return NT_STATUS_INVALID_PARAMETER;
4184 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4185 if (!NT_STATUS_IS_OK(status)) {
4186 return status;
4189 RESOLVE_DFSPATH_STATUS(oldname, conn, inbuf, outbuf);
4191 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4192 fname, oldname));
4194 return hardlink_internals(conn, oldname, fname);
4197 /****************************************************************************
4198 Deal with SMB_FILE_RENAME_INFORMATION.
4199 ****************************************************************************/
4201 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4202 char *inbuf,
4203 char *outbuf,
4204 const char *pdata,
4205 int total_data,
4206 files_struct *fsp,
4207 pstring fname)
4209 BOOL overwrite;
4210 /* uint32 root_fid; */ /* Not used */
4211 uint32 len;
4212 pstring newname;
4213 pstring base_name;
4214 NTSTATUS status = NT_STATUS_OK;
4215 char *p;
4217 if (total_data < 13) {
4218 return NT_STATUS_INVALID_PARAMETER;
4221 overwrite = (CVAL(pdata,0) ? True : False);
4222 /* root_fid = IVAL(pdata,4); */
4223 len = IVAL(pdata,8);
4225 if (len > (total_data - 12) || (len == 0)) {
4226 return NT_STATUS_INVALID_PARAMETER;
4229 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4230 if (!NT_STATUS_IS_OK(status)) {
4231 return status;
4234 RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf);
4236 /* Check the new name has no '/' characters. */
4237 if (strchr_m(newname, '/')) {
4238 return NT_STATUS_NOT_SUPPORTED;
4241 /* Create the base directory. */
4242 pstrcpy(base_name, fname);
4243 p = strrchr_m(base_name, '/');
4244 if (p) {
4245 *p = '\0';
4247 /* Append the new name. */
4248 pstrcat(base_name, "/");
4249 pstrcat(base_name, newname);
4251 if (fsp) {
4252 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4253 fsp->fnum, fsp->fsp_name, base_name ));
4254 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4255 } else {
4256 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4257 fname, newname ));
4258 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4261 return status;
4264 /****************************************************************************
4265 Deal with SMB_SET_POSIX_ACL.
4266 ****************************************************************************/
4268 #if defined(HAVE_POSIX_ACLS)
4269 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4270 const char *pdata,
4271 int total_data,
4272 files_struct *fsp,
4273 const char *fname,
4274 SMB_STRUCT_STAT *psbuf)
4276 uint16 posix_acl_version;
4277 uint16 num_file_acls;
4278 uint16 num_def_acls;
4279 BOOL valid_file_acls = True;
4280 BOOL valid_def_acls = True;
4282 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4283 return NT_STATUS_INVALID_PARAMETER;
4285 posix_acl_version = SVAL(pdata,0);
4286 num_file_acls = SVAL(pdata,2);
4287 num_def_acls = SVAL(pdata,4);
4289 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4290 valid_file_acls = False;
4291 num_file_acls = 0;
4294 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4295 valid_def_acls = False;
4296 num_def_acls = 0;
4299 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4300 return NT_STATUS_INVALID_PARAMETER;
4303 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4304 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4305 return NT_STATUS_INVALID_PARAMETER;
4308 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4309 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4310 return map_nt_error_from_unix(errno);
4313 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4314 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4315 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4316 return map_nt_error_from_unix(errno);
4318 return NT_STATUS_OK;
4320 #endif
4322 /****************************************************************************
4323 Deal with SMB_SET_POSIX_LOCK.
4324 ****************************************************************************/
4326 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4327 char *inbuf,
4328 int length,
4329 const char *pdata,
4330 int total_data,
4331 files_struct *fsp)
4333 SMB_BIG_UINT count;
4334 SMB_BIG_UINT offset;
4335 uint32 lock_pid;
4336 BOOL blocking_lock = False;
4337 enum brl_type lock_type;
4338 NTSTATUS status = NT_STATUS_OK;
4340 if (fsp == NULL || fsp->fh->fd == -1) {
4341 return NT_STATUS_INVALID_HANDLE;
4344 if (total_data != POSIX_LOCK_DATA_SIZE) {
4345 return NT_STATUS_INVALID_PARAMETER;
4348 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4349 case POSIX_LOCK_TYPE_READ:
4350 lock_type = READ_LOCK;
4351 break;
4352 case POSIX_LOCK_TYPE_WRITE:
4353 /* Return the right POSIX-mappable error code for files opened read-only. */
4354 if (!fsp->can_write) {
4355 return NT_STATUS_INVALID_HANDLE;
4357 lock_type = WRITE_LOCK;
4358 break;
4359 case POSIX_LOCK_TYPE_UNLOCK:
4360 lock_type = UNLOCK_LOCK;
4361 break;
4362 default:
4363 return NT_STATUS_INVALID_PARAMETER;
4366 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4367 blocking_lock = False;
4368 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4369 blocking_lock = True;
4370 } else {
4371 return NT_STATUS_INVALID_PARAMETER;
4374 if (!lp_blocking_locks(SNUM(conn))) {
4375 blocking_lock = False;
4378 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4379 #if defined(HAVE_LONGLONG)
4380 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4381 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4382 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4383 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4384 #else /* HAVE_LONGLONG */
4385 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4386 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4387 #endif /* HAVE_LONGLONG */
4389 if (lock_type == UNLOCK_LOCK) {
4390 status = do_unlock(fsp,
4391 lock_pid,
4392 count,
4393 offset,
4394 POSIX_LOCK);
4395 } else {
4396 struct byte_range_lock *br_lck = do_lock(fsp,
4397 lock_pid,
4398 count,
4399 offset,
4400 lock_type,
4401 POSIX_LOCK,
4402 blocking_lock,
4403 &status);
4405 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4407 * A blocking lock was requested. Package up
4408 * this smb into a queued request and push it
4409 * onto the blocking lock queue.
4411 if(push_blocking_lock_request(br_lck,
4412 inbuf, length,
4413 fsp,
4414 -1, /* infinite timeout. */
4416 lock_pid,
4417 lock_type,
4418 POSIX_LOCK,
4419 offset,
4420 count)) {
4421 TALLOC_FREE(br_lck);
4422 return status;
4425 TALLOC_FREE(br_lck);
4428 return status;
4431 /****************************************************************************
4432 Deal with SMB_INFO_STANDARD.
4433 ****************************************************************************/
4435 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4436 const char *pdata,
4437 int total_data,
4438 files_struct *fsp,
4439 const char *fname,
4440 const SMB_STRUCT_STAT *psbuf)
4442 struct utimbuf tvs;
4444 if (total_data < 12) {
4445 return NT_STATUS_INVALID_PARAMETER;
4448 /* access time */
4449 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
4450 /* write time */
4451 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
4453 return smb_set_file_time(conn,
4454 fsp,
4455 fname,
4456 psbuf,
4457 tvs);
4460 /****************************************************************************
4461 Deal with SMB_SET_FILE_BASIC_INFO.
4462 ****************************************************************************/
4464 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4465 const char *pdata,
4466 int total_data,
4467 files_struct *fsp,
4468 const char *fname,
4469 SMB_STRUCT_STAT *psbuf)
4471 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4472 time_t write_time;
4473 time_t changed_time;
4474 uint32 dosmode = 0;
4475 struct utimbuf tvs;
4476 NTSTATUS status = NT_STATUS_OK;
4478 if (total_data < 36) {
4479 return NT_STATUS_INVALID_PARAMETER;
4482 /* Set the attributes */
4483 dosmode = IVAL(pdata,32);
4484 status = smb_set_file_dosmode(conn,
4485 fname,
4486 psbuf,
4487 dosmode);
4488 if (!NT_STATUS_IS_OK(status)) {
4489 return status;
4492 /* Ignore create time at offset pdata. */
4494 /* access time */
4495 tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
4497 write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
4498 changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
4500 tvs.modtime = MIN(write_time, changed_time);
4502 if (write_time > tvs.modtime && write_time != (time_t)-1) {
4503 tvs.modtime = write_time;
4505 /* Prefer a defined time to an undefined one. */
4506 if (null_mtime(tvs.modtime)) {
4507 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
4510 return smb_set_file_time(conn,
4511 fsp,
4512 fname,
4513 psbuf,
4514 tvs);
4517 /****************************************************************************
4518 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4519 ****************************************************************************/
4521 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4522 const char *pdata,
4523 int total_data,
4524 files_struct *fsp,
4525 const char *fname,
4526 SMB_STRUCT_STAT *psbuf)
4528 SMB_BIG_UINT allocation_size = 0;
4529 NTSTATUS status = NT_STATUS_OK;
4530 files_struct *new_fsp = NULL;
4532 if (!VALID_STAT(*psbuf)) {
4533 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4536 if (total_data < 8) {
4537 return NT_STATUS_INVALID_PARAMETER;
4540 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4541 #ifdef LARGE_SMB_OFF_T
4542 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4543 #else /* LARGE_SMB_OFF_T */
4544 if (IVAL(pdata,4) != 0) {
4545 /* more than 32 bits? */
4546 return NT_STATUS_INVALID_PARAMETER;
4548 #endif /* LARGE_SMB_OFF_T */
4550 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4551 fname, (double)allocation_size ));
4553 if (allocation_size) {
4554 allocation_size = smb_roundup(conn, allocation_size);
4557 if(allocation_size == get_file_size(*psbuf)) {
4558 return NT_STATUS_OK;
4561 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4562 fname, (double)allocation_size ));
4564 if (fsp && fsp->fh->fd != -1) {
4565 /* Open file handle. */
4566 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4567 return map_nt_error_from_unix(errno);
4569 return NT_STATUS_OK;
4572 /* Pathname or stat or directory file. */
4574 status = open_file_ntcreate(conn, fname, psbuf,
4575 FILE_WRITE_DATA,
4576 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4577 FILE_OPEN,
4579 FILE_ATTRIBUTE_NORMAL,
4580 FORCE_OPLOCK_BREAK_TO_NONE,
4581 NULL, &new_fsp);
4583 if (!NT_STATUS_IS_OK(status)) {
4584 /* NB. We check for open_was_deferred in the caller. */
4585 return status;
4587 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4588 status = map_nt_error_from_unix(errno);
4589 close_file(new_fsp,NORMAL_CLOSE);
4590 return status;
4593 close_file(new_fsp,NORMAL_CLOSE);
4594 return NT_STATUS_OK;
4597 /****************************************************************************
4598 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4599 ****************************************************************************/
4601 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4602 const char *pdata,
4603 int total_data,
4604 files_struct *fsp,
4605 const char *fname,
4606 SMB_STRUCT_STAT *psbuf)
4608 SMB_OFF_T size;
4610 if (total_data < 8) {
4611 return NT_STATUS_INVALID_PARAMETER;
4614 size = IVAL(pdata,0);
4615 #ifdef LARGE_SMB_OFF_T
4616 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4617 #else /* LARGE_SMB_OFF_T */
4618 if (IVAL(pdata,4) != 0) {
4619 /* more than 32 bits? */
4620 return NT_STATUS_INVALID_PARAMETER;
4622 #endif /* LARGE_SMB_OFF_T */
4623 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4624 "file %s to %.0f\n", fname, (double)size ));
4626 return smb_set_file_size(conn,
4627 fsp,
4628 fname,
4629 psbuf,
4630 size);
4633 /****************************************************************************
4634 Allow a UNIX info mknod.
4635 ****************************************************************************/
4637 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4638 const char *pdata,
4639 int total_data,
4640 const char *fname,
4641 SMB_STRUCT_STAT *psbuf)
4643 uint32 file_type = IVAL(pdata,56);
4644 #if defined(HAVE_MAKEDEV)
4645 uint32 dev_major = IVAL(pdata,60);
4646 uint32 dev_minor = IVAL(pdata,68);
4647 #endif
4648 SMB_DEV_T dev = (SMB_DEV_T)0;
4649 uint32 raw_unixmode = IVAL(pdata,84);
4650 NTSTATUS status;
4651 mode_t unixmode;
4653 if (total_data < 100) {
4654 return NT_STATUS_INVALID_PARAMETER;
4657 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4658 if (!NT_STATUS_IS_OK(status)) {
4659 return status;
4662 #if defined(HAVE_MAKEDEV)
4663 dev = makedev(dev_major, dev_minor);
4664 #endif
4666 switch (file_type) {
4667 #if defined(S_IFIFO)
4668 case UNIX_TYPE_FIFO:
4669 unixmode |= S_IFIFO;
4670 break;
4671 #endif
4672 #if defined(S_IFSOCK)
4673 case UNIX_TYPE_SOCKET:
4674 unixmode |= S_IFSOCK;
4675 break;
4676 #endif
4677 #if defined(S_IFCHR)
4678 case UNIX_TYPE_CHARDEV:
4679 unixmode |= S_IFCHR;
4680 break;
4681 #endif
4682 #if defined(S_IFBLK)
4683 case UNIX_TYPE_BLKDEV:
4684 unixmode |= S_IFBLK;
4685 break;
4686 #endif
4687 default:
4688 return NT_STATUS_INVALID_PARAMETER;
4691 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4692 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
4694 /* Ok - do the mknod. */
4695 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
4696 return map_nt_error_from_unix(errno);
4699 /* If any of the other "set" calls fail we
4700 * don't want to end up with a half-constructed mknod.
4703 if (lp_inherit_perms(SNUM(conn))) {
4704 inherit_access_acl(
4705 conn, parent_dirname(fname),
4706 fname, unixmode);
4709 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
4710 status = map_nt_error_from_unix(errno);
4711 SMB_VFS_UNLINK(conn,fname);
4712 return status;
4714 return NT_STATUS_OK;
4717 /****************************************************************************
4718 Deal with SMB_SET_FILE_UNIX_BASIC.
4719 ****************************************************************************/
4721 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
4722 const char *pdata,
4723 int total_data,
4724 files_struct *fsp,
4725 const char *fname,
4726 SMB_STRUCT_STAT *psbuf)
4728 struct utimbuf tvs;
4729 uint32 raw_unixmode;
4730 mode_t unixmode;
4731 SMB_OFF_T size = 0;
4732 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4733 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4734 NTSTATUS status = NT_STATUS_OK;
4735 BOOL delete_on_fail = False;
4736 enum perm_type ptype;
4738 if (total_data < 100) {
4739 return NT_STATUS_INVALID_PARAMETER;
4742 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4743 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4744 size=IVAL(pdata,0); /* first 8 Bytes are size */
4745 #ifdef LARGE_SMB_OFF_T
4746 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4747 #else /* LARGE_SMB_OFF_T */
4748 if (IVAL(pdata,4) != 0) {
4749 /* more than 32 bits? */
4750 return NT_STATUS_INVALID_PARAMETER;
4752 #endif /* LARGE_SMB_OFF_T */
4755 tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */
4756 tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */
4757 set_owner = (uid_t)IVAL(pdata,40);
4758 set_grp = (gid_t)IVAL(pdata,48);
4759 raw_unixmode = IVAL(pdata,84);
4761 if (VALID_STAT(*psbuf)) {
4762 if (S_ISDIR(psbuf->st_mode)) {
4763 ptype = PERM_EXISTING_DIR;
4764 } else {
4765 ptype = PERM_EXISTING_FILE;
4767 } else {
4768 ptype = PERM_NEW_FILE;
4771 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
4772 if (!NT_STATUS_IS_OK(status)) {
4773 return status;
4776 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
4777 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4778 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4780 if (!VALID_STAT(*psbuf)) {
4782 * The only valid use of this is to create character and block
4783 * devices, and named pipes. This is deprecated (IMHO) and
4784 * a new info level should be used for mknod. JRA.
4787 status = smb_unix_mknod(conn,
4788 pdata,
4789 total_data,
4790 fname,
4791 psbuf);
4792 if (!NT_STATUS_IS_OK(status)) {
4793 return status;
4796 /* Ensure we don't try and change anything else. */
4797 raw_unixmode = SMB_MODE_NO_CHANGE;
4798 size = get_file_size(*psbuf);
4799 tvs.modtime = psbuf->st_mtime;
4800 tvs.actime = psbuf->st_atime;
4802 * We continue here as we might want to change the
4803 * owner uid/gid.
4805 delete_on_fail = True;
4808 #if 1
4809 /* Horrible backwards compatibility hack as an old server bug
4810 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
4811 * */
4813 if (!size) {
4814 size = get_file_size(*psbuf);
4816 #endif
4819 * Deal with the UNIX specific mode set.
4822 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4823 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4824 (unsigned int)unixmode, fname ));
4825 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
4826 return map_nt_error_from_unix(errno);
4831 * Deal with the UNIX specific uid set.
4834 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
4835 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4836 (unsigned int)set_owner, fname ));
4837 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
4838 status = map_nt_error_from_unix(errno);
4839 if (delete_on_fail) {
4840 SMB_VFS_UNLINK(conn,fname);
4842 return status;
4847 * Deal with the UNIX specific gid set.
4850 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
4851 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4852 (unsigned int)set_owner, fname ));
4853 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
4854 status = map_nt_error_from_unix(errno);
4855 if (delete_on_fail) {
4856 SMB_VFS_UNLINK(conn,fname);
4858 return status;
4862 /* Deal with any size changes. */
4864 status = smb_set_file_size(conn,
4865 fsp,
4866 fname,
4867 psbuf,
4868 size);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 return status;
4873 /* Deal with any time changes. */
4875 return smb_set_file_time(conn,
4876 fsp,
4877 fname,
4878 psbuf,
4879 tvs);
4882 /****************************************************************************
4883 Create a directory with POSIX semantics.
4884 ****************************************************************************/
4886 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
4887 char **ppdata,
4888 int total_data,
4889 const char *fname,
4890 SMB_STRUCT_STAT *psbuf,
4891 int *pdata_return_size)
4893 NTSTATUS status = NT_STATUS_OK;
4894 uint32 raw_unixmode = 0;
4895 uint32 mod_unixmode = 0;
4896 mode_t unixmode = (mode_t)0;
4897 files_struct *fsp = NULL;
4898 uint16 info_level_return = 0;
4899 char *pdata = *ppdata;
4901 if (total_data < 10) {
4902 return NT_STATUS_INVALID_PARAMETER;
4905 raw_unixmode = IVAL(pdata,8);
4906 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
4907 if (!NT_STATUS_IS_OK(status)) {
4908 return status;
4911 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
4913 status = open_directory(conn,
4914 fname,
4915 psbuf,
4916 FILE_READ_ATTRIBUTES, /* Just a stat open */
4917 FILE_SHARE_NONE, /* Ignored for stat opens */
4918 FILE_CREATE,
4920 mod_unixmode,
4921 NULL,
4922 &fsp);
4924 if (NT_STATUS_IS_OK(status)) {
4925 close_file(fsp, NORMAL_CLOSE);
4928 info_level_return = SVAL(pdata,12);
4930 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
4931 *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
4932 } else {
4933 *pdata_return_size = 8;
4936 /* Realloc the data size */
4937 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
4938 if (*ppdata == NULL) {
4939 *pdata_return_size = 0;
4940 return NT_STATUS_NO_MEMORY;
4943 SSVAL(pdata,0,NO_OPLOCK_RETURN);
4944 SSVAL(pdata,2,0);
4946 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
4947 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
4948 SSVAL(pdata,6,0); /* Padding. */
4949 store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
4950 } else {
4951 SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
4952 SSVAL(pdata,6,0); /* Padding. */
4955 return status;
4958 /****************************************************************************
4959 Open/Create a file with POSIX semantics.
4960 ****************************************************************************/
4962 static NTSTATUS smb_posix_open(connection_struct *conn,
4963 char **ppdata,
4964 int total_data,
4965 const char *fname,
4966 SMB_STRUCT_STAT *psbuf,
4967 int *pdata_return_size)
4969 BOOL extended_oplock_granted = False;
4970 char *pdata = *ppdata;
4971 uint32 flags = 0;
4972 uint32 wire_open_mode = 0;
4973 uint32 raw_unixmode = 0;
4974 uint32 mod_unixmode = 0;
4975 uint32 create_disp = 0;
4976 uint32 access_mask = 0;
4977 uint32 create_options = 0;
4978 NTSTATUS status = NT_STATUS_OK;
4979 mode_t unixmode = (mode_t)0;
4980 files_struct *fsp = NULL;
4981 int oplock_request = 0;
4982 int info = 0;
4983 uint16 info_level_return = 0;
4985 if (total_data < 14) {
4986 return NT_STATUS_INVALID_PARAMETER;
4989 flags = IVAL(pdata,0);
4990 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
4991 if (oplock_request) {
4992 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
4995 wire_open_mode = IVAL(pdata,4);
4997 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
4998 return smb_posix_mkdir(conn,
4999 ppdata,
5000 total_data,
5001 fname,
5002 psbuf,
5003 pdata_return_size);
5006 switch (wire_open_mode & SMB_ACCMODE) {
5007 case SMB_O_RDONLY:
5008 access_mask = FILE_READ_DATA;
5009 break;
5010 case SMB_O_WRONLY:
5011 access_mask = FILE_WRITE_DATA;
5012 break;
5013 case SMB_O_RDWR:
5014 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5015 break;
5016 default:
5017 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5018 (unsigned int)wire_open_mode ));
5019 return NT_STATUS_INVALID_PARAMETER;
5022 wire_open_mode &= ~SMB_ACCMODE;
5024 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5025 create_disp = FILE_CREATE;
5026 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5027 create_disp = FILE_OVERWRITE_IF;
5028 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5029 create_disp = FILE_OPEN_IF;
5030 } else {
5031 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5032 (unsigned int)wire_open_mode ));
5033 return NT_STATUS_INVALID_PARAMETER;
5036 raw_unixmode = IVAL(pdata,8);
5037 status = unix_perms_from_wire(conn,
5038 psbuf,
5039 raw_unixmode,
5040 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5041 &unixmode);
5043 if (!NT_STATUS_IS_OK(status)) {
5044 return status;
5047 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5049 if (wire_open_mode & SMB_O_SYNC) {
5050 create_options |= FILE_WRITE_THROUGH;
5052 if (wire_open_mode & SMB_O_APPEND) {
5053 access_mask |= FILE_APPEND_DATA;
5055 if (wire_open_mode & SMB_O_DIRECT) {
5056 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5059 status = open_file_ntcreate(conn,
5060 fname,
5061 psbuf,
5062 access_mask,
5063 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5064 create_disp,
5065 0, /* no create options yet. */
5066 mod_unixmode,
5067 oplock_request,
5068 &info,
5069 &fsp);
5071 if (!NT_STATUS_IS_OK(status)) {
5072 return status;
5075 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5076 extended_oplock_granted = True;
5079 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5080 extended_oplock_granted = True;
5083 info_level_return = SVAL(pdata,12);
5085 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5086 *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
5087 } else {
5088 *pdata_return_size = 8;
5091 /* Realloc the data size */
5092 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5093 if (*ppdata == NULL) {
5094 close_file(fsp,ERROR_CLOSE);
5095 *pdata_return_size = 0;
5096 return NT_STATUS_NO_MEMORY;
5099 if (extended_oplock_granted) {
5100 if (flags & REQUEST_BATCH_OPLOCK) {
5101 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5102 } else {
5103 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5105 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5106 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5107 } else {
5108 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5111 SSVAL(pdata,2,fsp->fnum);
5112 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5113 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
5114 SSVAL(pdata,6,0); /* padding. */
5115 store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
5116 } else {
5117 SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
5118 SSVAL(pdata,6,0); /* padding. */
5120 return NT_STATUS_OK;
5123 /****************************************************************************
5124 Delete a file with POSIX semantics.
5125 ****************************************************************************/
5127 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5128 const char *pdata,
5129 int total_data,
5130 const char *fname,
5131 SMB_STRUCT_STAT *psbuf)
5133 NTSTATUS status = NT_STATUS_OK;
5134 files_struct *fsp = NULL;
5135 int info = 0;
5137 if (!VALID_STAT(*psbuf)) {
5138 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5141 if (VALID_STAT_OF_DIR(*psbuf)) {
5142 status = open_directory(conn,
5143 fname,
5144 psbuf,
5145 DELETE_ACCESS,
5146 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5147 FILE_OPEN,
5148 FILE_DELETE_ON_CLOSE,
5149 FILE_FLAG_POSIX_SEMANTICS|0777,
5150 &info,
5151 &fsp);
5152 } else {
5153 status = open_file_ntcreate(conn,
5154 fname,
5155 psbuf,
5156 DELETE_ACCESS,
5157 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5158 FILE_OPEN,
5159 FILE_DELETE_ON_CLOSE,
5160 FILE_FLAG_POSIX_SEMANTICS|0777,
5161 INTERNAL_OPEN_ONLY,
5162 &info,
5163 &fsp);
5166 if (!NT_STATUS_IS_OK(status)) {
5167 return status;
5169 return close_file(fsp, NORMAL_CLOSE);
5172 /****************************************************************************
5173 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5174 ****************************************************************************/
5176 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5177 unsigned int tran_call,
5178 char **pparams, int total_params, char **ppdata, int total_data,
5179 unsigned int max_data_bytes)
5181 char *params = *pparams;
5182 char *pdata = *ppdata;
5183 uint16 info_level;
5184 SMB_STRUCT_STAT sbuf;
5185 pstring fname;
5186 files_struct *fsp = NULL;
5187 NTSTATUS status = NT_STATUS_OK;
5188 int data_return_size = 0;
5190 if (!params) {
5191 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5194 ZERO_STRUCT(sbuf);
5196 if (tran_call == TRANSACT2_SETFILEINFO) {
5197 if (total_params < 4) {
5198 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5201 fsp = file_fsp(params,0);
5202 info_level = SVAL(params,2);
5204 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5206 * This is actually a SETFILEINFO on a directory
5207 * handle (returned from an NT SMB). NT5.0 seems
5208 * to do this call. JRA.
5210 pstrcpy(fname, fsp->fsp_name);
5211 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5212 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5213 return UNIXERROR(ERRDOS,ERRbadpath);
5215 } else if (fsp && fsp->print_file) {
5217 * Doing a DELETE_ON_CLOSE should cancel a print job.
5219 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5220 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5222 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5224 SSVAL(params,0,0);
5225 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5226 return(-1);
5227 } else
5228 return (UNIXERROR(ERRDOS,ERRbadpath));
5229 } else {
5231 * Original code - this is an open file.
5233 CHECK_FSP(fsp,conn);
5235 pstrcpy(fname, fsp->fsp_name);
5237 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5238 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5239 return(UNIXERROR(ERRDOS,ERRbadfid));
5242 } else {
5243 /* set path info */
5244 if (total_params < 7) {
5245 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5248 info_level = SVAL(params,0);
5249 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5250 if (!NT_STATUS_IS_OK(status)) {
5251 return ERROR_NT(status);
5254 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
5256 status = unix_convert(conn, fname, False, NULL, &sbuf);
5257 if (!NT_STATUS_IS_OK(status)) {
5258 return ERROR_NT(status);
5262 * For CIFS UNIX extensions the target name may not exist.
5265 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5266 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5267 return UNIXERROR(ERRDOS,ERRbadpath);
5270 status = check_name(conn, fname);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 return ERROR_NT(status);
5277 if (!CAN_WRITE(conn)) {
5278 return ERROR_DOS(ERRSRV,ERRaccess);
5281 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5282 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5285 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5286 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5288 /* Realloc the parameter size */
5289 *pparams = (char *)SMB_REALLOC(*pparams,2);
5290 if (*pparams == NULL) {
5291 return ERROR_NT(NT_STATUS_NO_MEMORY);
5293 params = *pparams;
5295 SSVAL(params,0,0);
5297 if (fsp && fsp->pending_modtime) {
5298 /* the pending modtime overrides the current modtime */
5299 sbuf.st_mtime = fsp->pending_modtime;
5302 switch (info_level) {
5304 case SMB_INFO_STANDARD:
5306 status = smb_set_info_standard(conn,
5307 pdata,
5308 total_data,
5309 fsp,
5310 fname,
5311 &sbuf);
5312 break;
5315 case SMB_INFO_SET_EA:
5317 status = smb_info_set_ea(conn,
5318 pdata,
5319 total_data,
5320 fsp,
5321 fname);
5322 break;
5325 case SMB_SET_FILE_BASIC_INFO:
5326 case SMB_FILE_BASIC_INFORMATION:
5328 status = smb_set_file_basic_info(conn,
5329 pdata,
5330 total_data,
5331 fsp,
5332 fname,
5333 &sbuf);
5334 break;
5337 case SMB_FILE_ALLOCATION_INFORMATION:
5338 case SMB_SET_FILE_ALLOCATION_INFO:
5340 status = smb_set_file_allocation_info(conn,
5341 pdata,
5342 total_data,
5343 fsp,
5344 fname,
5345 &sbuf);
5346 break;
5349 case SMB_FILE_END_OF_FILE_INFORMATION:
5350 case SMB_SET_FILE_END_OF_FILE_INFO:
5352 status = smb_set_file_end_of_file_info(conn,
5353 pdata,
5354 total_data,
5355 fsp,
5356 fname,
5357 &sbuf);
5358 break;
5361 case SMB_FILE_DISPOSITION_INFORMATION:
5362 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5364 #if 0
5365 /* JRA - We used to just ignore this on a path ?
5366 * Shouldn't this be invalid level on a pathname
5367 * based call ?
5369 if (tran_call != TRANSACT2_SETFILEINFO) {
5370 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5372 #endif
5373 status = smb_set_file_disposition_info(conn,
5374 pdata,
5375 total_data,
5376 fsp,
5377 fname,
5378 &sbuf);
5379 break;
5382 case SMB_FILE_POSITION_INFORMATION:
5384 status = smb_file_position_information(conn,
5385 pdata,
5386 total_data,
5387 fsp);
5388 break;
5391 /* From tridge Samba4 :
5392 * MODE_INFORMATION in setfileinfo (I have no
5393 * idea what "mode information" on a file is - it takes a value of 0,
5394 * 2, 4 or 6. What could it be?).
5397 case SMB_FILE_MODE_INFORMATION:
5399 status = smb_file_mode_information(conn,
5400 pdata,
5401 total_data);
5402 break;
5406 * CIFS UNIX extensions.
5409 case SMB_SET_FILE_UNIX_BASIC:
5411 status = smb_set_file_unix_basic(conn,
5412 pdata,
5413 total_data,
5414 fsp,
5415 fname,
5416 &sbuf);
5417 break;
5420 case SMB_SET_FILE_UNIX_LINK:
5422 if (tran_call != TRANSACT2_SETPATHINFO) {
5423 /* We must have a pathname for this. */
5424 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5426 status = smb_set_file_unix_link(conn,
5427 inbuf,
5428 pdata,
5429 total_data,
5430 fname);
5431 break;
5434 case SMB_SET_FILE_UNIX_HLINK:
5436 if (tran_call != TRANSACT2_SETPATHINFO) {
5437 /* We must have a pathname for this. */
5438 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5440 status = smb_set_file_unix_hlink(conn,
5441 inbuf,
5442 outbuf,
5443 pdata,
5444 total_data,
5445 fname);
5446 break;
5449 case SMB_FILE_RENAME_INFORMATION:
5451 status = smb_file_rename_information(conn,
5452 inbuf,
5453 outbuf,
5454 pdata,
5455 total_data,
5456 fsp,
5457 fname);
5458 break;
5461 #if defined(HAVE_POSIX_ACLS)
5462 case SMB_SET_POSIX_ACL:
5464 status = smb_set_posix_acl(conn,
5465 pdata,
5466 total_data,
5467 fsp,
5468 fname,
5469 &sbuf);
5470 break;
5472 #endif
5474 case SMB_SET_POSIX_LOCK:
5476 if (tran_call != TRANSACT2_SETFILEINFO) {
5477 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5479 status = smb_set_posix_lock(conn,
5480 inbuf,
5481 length,
5482 pdata,
5483 total_data,
5484 fsp);
5485 break;
5488 case SMB_POSIX_PATH_OPEN:
5490 if (tran_call != TRANSACT2_SETPATHINFO) {
5491 /* We must have a pathname for this. */
5492 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5495 status = smb_posix_open(conn,
5496 ppdata,
5497 total_data,
5498 fname,
5499 &sbuf,
5500 &data_return_size);
5501 break;
5504 case SMB_POSIX_PATH_UNLINK:
5506 if (tran_call != TRANSACT2_SETPATHINFO) {
5507 /* We must have a pathname for this. */
5508 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5511 status = smb_posix_unlink(conn,
5512 pdata,
5513 total_data,
5514 fname,
5515 &sbuf);
5516 break;
5519 default:
5520 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5524 if (!NT_STATUS_IS_OK(status)) {
5525 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5526 /* We have re-scheduled this call. */
5527 return -1;
5529 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5530 /* We have re-scheduled this call. */
5531 return -1;
5533 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5534 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5536 return ERROR_NT(status);
5539 SSVAL(params,0,0);
5540 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
5542 return -1;
5545 /****************************************************************************
5546 Reply to a TRANS2_MKDIR (make directory with extended attributes).
5547 ****************************************************************************/
5549 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5550 char **pparams, int total_params, char **ppdata, int total_data,
5551 unsigned int max_data_bytes)
5553 char *params = *pparams;
5554 char *pdata = *ppdata;
5555 pstring directory;
5556 SMB_STRUCT_STAT sbuf;
5557 NTSTATUS status = NT_STATUS_OK;
5558 struct ea_list *ea_list = NULL;
5560 if (!CAN_WRITE(conn))
5561 return ERROR_DOS(ERRSRV,ERRaccess);
5563 if (total_params < 5) {
5564 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5567 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
5568 if (!NT_STATUS_IS_OK(status)) {
5569 return ERROR_NT(status);
5572 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
5574 status = unix_convert(conn, directory, False, NULL, &sbuf);
5575 if (!NT_STATUS_IS_OK(status)) {
5576 return ERROR_NT(status);
5579 /* Any data in this call is an EA list. */
5580 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5581 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5585 * OS/2 workplace shell seems to send SET_EA requests of "null"
5586 * length (4 bytes containing IVAL 4).
5587 * They seem to have no effect. Bug #3212. JRA.
5590 if (total_data != 4) {
5591 if (total_data < 10) {
5592 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5595 if (IVAL(pdata,0) > total_data) {
5596 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
5597 IVAL(pdata,0), (unsigned int)total_data));
5598 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5601 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
5602 total_data - 4);
5603 if (!ea_list) {
5604 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5606 } else if (IVAL(pdata,0) != 4) {
5607 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5610 status = check_name(conn, directory);
5611 if (!NT_STATUS_IS_OK(status)) {
5612 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5613 return ERROR_NT(status);
5616 status = create_directory(conn, directory);
5618 if (!NT_STATUS_IS_OK(status)) {
5619 return ERROR_NT(status);
5622 /* Try and set any given EA. */
5623 if (ea_list) {
5624 status = set_ea(conn, NULL, directory, ea_list);
5625 if (!NT_STATUS_IS_OK(status)) {
5626 return ERROR_NT(status);
5630 /* Realloc the parameter and data sizes */
5631 *pparams = (char *)SMB_REALLOC(*pparams,2);
5632 if(*pparams == NULL) {
5633 return ERROR_NT(NT_STATUS_NO_MEMORY);
5635 params = *pparams;
5637 SSVAL(params,0,0);
5639 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5641 return(-1);
5644 /****************************************************************************
5645 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5646 We don't actually do this - we just send a null response.
5647 ****************************************************************************/
5649 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5650 char **pparams, int total_params, char **ppdata, int total_data,
5651 unsigned int max_data_bytes)
5653 static uint16 fnf_handle = 257;
5654 char *params = *pparams;
5655 uint16 info_level;
5657 if (total_params < 6) {
5658 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5661 info_level = SVAL(params,4);
5662 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5664 switch (info_level) {
5665 case 1:
5666 case 2:
5667 break;
5668 default:
5669 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5672 /* Realloc the parameter and data sizes */
5673 *pparams = (char *)SMB_REALLOC(*pparams,6);
5674 if (*pparams == NULL) {
5675 return ERROR_NT(NT_STATUS_NO_MEMORY);
5677 params = *pparams;
5679 SSVAL(params,0,fnf_handle);
5680 SSVAL(params,2,0); /* No changes */
5681 SSVAL(params,4,0); /* No EA errors */
5683 fnf_handle++;
5685 if(fnf_handle == 0)
5686 fnf_handle = 257;
5688 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
5690 return(-1);
5693 /****************************************************************************
5694 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5695 changes). Currently this does nothing.
5696 ****************************************************************************/
5698 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5699 char **pparams, int total_params, char **ppdata, int total_data,
5700 unsigned int max_data_bytes)
5702 char *params = *pparams;
5704 DEBUG(3,("call_trans2findnotifynext\n"));
5706 /* Realloc the parameter and data sizes */
5707 *pparams = (char *)SMB_REALLOC(*pparams,4);
5708 if (*pparams == NULL) {
5709 return ERROR_NT(NT_STATUS_NO_MEMORY);
5711 params = *pparams;
5713 SSVAL(params,0,0); /* No changes */
5714 SSVAL(params,2,0); /* No EA errors */
5716 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
5718 return(-1);
5721 /****************************************************************************
5722 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5723 ****************************************************************************/
5725 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5726 char **pparams, int total_params, char **ppdata, int total_data,
5727 unsigned int max_data_bytes)
5729 char *params = *pparams;
5730 pstring pathname;
5731 int reply_size = 0;
5732 int max_referral_level;
5734 DEBUG(10,("call_trans2getdfsreferral\n"));
5736 if (total_params < 3) {
5737 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5740 max_referral_level = SVAL(params,0);
5742 if(!lp_host_msdfs())
5743 return ERROR_DOS(ERRDOS,ERRbadfunc);
5745 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
5746 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
5747 return UNIXERROR(ERRDOS,ERRbadfile);
5749 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5750 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
5752 return(-1);
5755 #define LMCAT_SPL 0x53
5756 #define LMFUNC_GETJOBID 0x60
5758 /****************************************************************************
5759 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5760 ****************************************************************************/
5762 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5763 char **pparams, int total_params, char **ppdata, int total_data,
5764 unsigned int max_data_bytes)
5766 char *pdata = *ppdata;
5767 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
5769 /* check for an invalid fid before proceeding */
5771 if (!fsp)
5772 return(ERROR_DOS(ERRDOS,ERRbadfid));
5774 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5775 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5776 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5777 if (*ppdata == NULL) {
5778 return ERROR_NT(NT_STATUS_NO_MEMORY);
5780 pdata = *ppdata;
5782 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5783 CAN ACCEPT THIS IN UNICODE. JRA. */
5785 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
5786 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5787 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5788 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5789 return(-1);
5790 } else {
5791 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5792 return ERROR_DOS(ERRSRV,ERRerror);
5796 /****************************************************************************
5797 Reply to a SMBfindclose (stop trans2 directory search).
5798 ****************************************************************************/
5800 int reply_findclose(connection_struct *conn,
5801 char *inbuf,char *outbuf,int length,int bufsize)
5803 int outsize = 0;
5804 int dptr_num=SVALS(inbuf,smb_vwv0);
5805 START_PROFILE(SMBfindclose);
5807 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5809 dptr_close(&dptr_num);
5811 outsize = set_message(outbuf,0,0,False);
5813 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5815 END_PROFILE(SMBfindclose);
5816 return(outsize);
5819 /****************************************************************************
5820 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5821 ****************************************************************************/
5823 int reply_findnclose(connection_struct *conn,
5824 char *inbuf,char *outbuf,int length,int bufsize)
5826 int outsize = 0;
5827 int dptr_num= -1;
5828 START_PROFILE(SMBfindnclose);
5830 dptr_num = SVAL(inbuf,smb_vwv0);
5832 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5834 /* We never give out valid handles for a
5835 findnotifyfirst - so any dptr_num is ok here.
5836 Just ignore it. */
5838 outsize = set_message(outbuf,0,0,False);
5840 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5842 END_PROFILE(SMBfindnclose);
5843 return(outsize);
5846 int handle_trans2(connection_struct *conn,
5847 struct trans_state *state,
5848 char *inbuf, char *outbuf, int size, int bufsize)
5850 int outsize;
5852 if (Protocol >= PROTOCOL_NT1) {
5853 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5856 /* Now we must call the relevant TRANS2 function */
5857 switch(state->call) {
5858 case TRANSACT2_OPEN:
5860 START_PROFILE(Trans2_open);
5861 outsize = call_trans2open(
5862 conn, inbuf, outbuf, bufsize,
5863 &state->param, state->total_param,
5864 &state->data, state->total_data,
5865 state->max_data_return);
5866 END_PROFILE(Trans2_open);
5867 break;
5870 case TRANSACT2_FINDFIRST:
5872 START_PROFILE(Trans2_findfirst);
5873 outsize = call_trans2findfirst(
5874 conn, inbuf, outbuf, bufsize,
5875 &state->param, state->total_param,
5876 &state->data, state->total_data,
5877 state->max_data_return);
5878 END_PROFILE(Trans2_findfirst);
5879 break;
5882 case TRANSACT2_FINDNEXT:
5884 START_PROFILE(Trans2_findnext);
5885 outsize = call_trans2findnext(
5886 conn, inbuf, outbuf, size, bufsize,
5887 &state->param, state->total_param,
5888 &state->data, state->total_data,
5889 state->max_data_return);
5890 END_PROFILE(Trans2_findnext);
5891 break;
5894 case TRANSACT2_QFSINFO:
5896 START_PROFILE(Trans2_qfsinfo);
5897 outsize = call_trans2qfsinfo(
5898 conn, inbuf, outbuf, size, bufsize,
5899 &state->param, state->total_param,
5900 &state->data, state->total_data,
5901 state->max_data_return);
5902 END_PROFILE(Trans2_qfsinfo);
5903 break;
5906 case TRANSACT2_SETFSINFO:
5908 START_PROFILE(Trans2_setfsinfo);
5909 outsize = call_trans2setfsinfo(
5910 conn, inbuf, outbuf, size, bufsize,
5911 &state->param, state->total_param,
5912 &state->data, state->total_data,
5913 state->max_data_return);
5914 END_PROFILE(Trans2_setfsinfo);
5915 break;
5918 case TRANSACT2_QPATHINFO:
5919 case TRANSACT2_QFILEINFO:
5921 START_PROFILE(Trans2_qpathinfo);
5922 outsize = call_trans2qfilepathinfo(
5923 conn, inbuf, outbuf, size, bufsize, state->call,
5924 &state->param, state->total_param,
5925 &state->data, state->total_data,
5926 state->max_data_return);
5927 END_PROFILE(Trans2_qpathinfo);
5928 break;
5931 case TRANSACT2_SETPATHINFO:
5932 case TRANSACT2_SETFILEINFO:
5934 START_PROFILE(Trans2_setpathinfo);
5935 outsize = call_trans2setfilepathinfo(
5936 conn, inbuf, outbuf, size, bufsize, state->call,
5937 &state->param, state->total_param,
5938 &state->data, state->total_data,
5939 state->max_data_return);
5940 END_PROFILE(Trans2_setpathinfo);
5941 break;
5944 case TRANSACT2_FINDNOTIFYFIRST:
5946 START_PROFILE(Trans2_findnotifyfirst);
5947 outsize = call_trans2findnotifyfirst(
5948 conn, inbuf, outbuf, size, bufsize,
5949 &state->param, state->total_param,
5950 &state->data, state->total_data,
5951 state->max_data_return);
5952 END_PROFILE(Trans2_findnotifyfirst);
5953 break;
5956 case TRANSACT2_FINDNOTIFYNEXT:
5958 START_PROFILE(Trans2_findnotifynext);
5959 outsize = call_trans2findnotifynext(
5960 conn, inbuf, outbuf, size, bufsize,
5961 &state->param, state->total_param,
5962 &state->data, state->total_data,
5963 state->max_data_return);
5964 END_PROFILE(Trans2_findnotifynext);
5965 break;
5968 case TRANSACT2_MKDIR:
5970 START_PROFILE(Trans2_mkdir);
5971 outsize = call_trans2mkdir(
5972 conn, inbuf, outbuf, size, bufsize,
5973 &state->param, state->total_param,
5974 &state->data, state->total_data,
5975 state->max_data_return);
5976 END_PROFILE(Trans2_mkdir);
5977 break;
5980 case TRANSACT2_GET_DFS_REFERRAL:
5982 START_PROFILE(Trans2_get_dfs_referral);
5983 outsize = call_trans2getdfsreferral(
5984 conn, inbuf, outbuf, size, bufsize,
5985 &state->param, state->total_param,
5986 &state->data, state->total_data,
5987 state->max_data_return);
5988 END_PROFILE(Trans2_get_dfs_referral);
5989 break;
5992 case TRANSACT2_IOCTL:
5994 START_PROFILE(Trans2_ioctl);
5995 outsize = call_trans2ioctl(
5996 conn, inbuf, outbuf, size, bufsize,
5997 &state->param, state->total_param,
5998 &state->data, state->total_data,
5999 state->max_data_return);
6000 END_PROFILE(Trans2_ioctl);
6001 break;
6004 default:
6005 /* Error in request */
6006 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6007 outsize = ERROR_DOS(ERRSRV,ERRerror);
6010 return outsize;
6013 /****************************************************************************
6014 Reply to a SMBtrans2.
6015 ****************************************************************************/
6017 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6018 int size, int bufsize)
6020 int outsize = 0;
6021 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6022 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6023 unsigned int psoff = SVAL(inbuf, smb_psoff);
6024 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6025 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6026 struct trans_state *state;
6027 NTSTATUS result;
6029 START_PROFILE(SMBtrans2);
6031 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6032 if (!NT_STATUS_IS_OK(result)) {
6033 DEBUG(2, ("Got invalid trans2 request: %s\n",
6034 nt_errstr(result)));
6035 END_PROFILE(SMBtrans2);
6036 return ERROR_NT(result);
6039 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6040 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6041 END_PROFILE(SMBtrans2);
6042 return ERROR_DOS(ERRSRV,ERRaccess);
6045 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6046 DEBUG(0, ("talloc failed\n"));
6047 END_PROFILE(SMBtrans2);
6048 return ERROR_NT(NT_STATUS_NO_MEMORY);
6051 state->cmd = SMBtrans2;
6053 state->mid = SVAL(inbuf, smb_mid);
6054 state->vuid = SVAL(inbuf, smb_uid);
6055 state->setup_count = SVAL(inbuf, smb_suwcnt);
6056 state->setup = NULL;
6057 state->total_param = SVAL(inbuf, smb_tpscnt);
6058 state->param = NULL;
6059 state->total_data = SVAL(inbuf, smb_tdscnt);
6060 state->data = NULL;
6061 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6062 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6063 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6064 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6065 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6067 state->call = tran_call;
6069 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6070 is so as a sanity check */
6071 if (state->setup_count != 1) {
6073 * Need to have rc=0 for ioctl to get job id for OS/2.
6074 * Network printing will fail if function is not successful.
6075 * Similar function in reply.c will be used if protocol
6076 * is LANMAN1.0 instead of LM1.2X002.
6077 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6078 * outbuf doesn't have to be set(only job id is used).
6080 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6081 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6082 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6083 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6084 } else {
6085 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6086 DEBUG(2,("Transaction is %d\n",tran_call));
6087 TALLOC_FREE(state);
6088 END_PROFILE(SMBtrans2);
6089 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6093 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6094 goto bad_param;
6096 if (state->total_data) {
6097 /* Can't use talloc here, the core routines do realloc on the
6098 * params and data. */
6099 state->data = (char *)SMB_MALLOC(state->total_data);
6100 if (state->data == NULL) {
6101 DEBUG(0,("reply_trans2: data malloc fail for %u "
6102 "bytes !\n", (unsigned int)state->total_data));
6103 TALLOC_FREE(state);
6104 END_PROFILE(SMBtrans2);
6105 return(ERROR_DOS(ERRDOS,ERRnomem));
6107 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6108 goto bad_param;
6109 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6110 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6111 goto bad_param;
6113 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6116 if (state->total_param) {
6117 /* Can't use talloc here, the core routines do realloc on the
6118 * params and data. */
6119 state->param = (char *)SMB_MALLOC(state->total_param);
6120 if (state->param == NULL) {
6121 DEBUG(0,("reply_trans: param malloc fail for %u "
6122 "bytes !\n", (unsigned int)state->total_param));
6123 SAFE_FREE(state->data);
6124 TALLOC_FREE(state);
6125 END_PROFILE(SMBtrans2);
6126 return(ERROR_DOS(ERRDOS,ERRnomem));
6128 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6129 goto bad_param;
6130 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6131 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6132 goto bad_param;
6134 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6137 state->received_data = dscnt;
6138 state->received_param = pscnt;
6140 if ((state->received_param == state->total_param) &&
6141 (state->received_data == state->total_data)) {
6143 outsize = handle_trans2(conn, state, inbuf, outbuf,
6144 size, bufsize);
6145 SAFE_FREE(state->data);
6146 SAFE_FREE(state->param);
6147 TALLOC_FREE(state);
6148 END_PROFILE(SMBtrans2);
6149 return outsize;
6152 DLIST_ADD(conn->pending_trans, state);
6154 /* We need to send an interim response then receive the rest
6155 of the parameter/data bytes */
6156 outsize = set_message(outbuf,0,0,False);
6157 show_msg(outbuf);
6158 END_PROFILE(SMBtrans2);
6159 return outsize;
6161 bad_param:
6163 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6164 SAFE_FREE(state->data);
6165 SAFE_FREE(state->param);
6166 TALLOC_FREE(state);
6167 END_PROFILE(SMBtrans2);
6168 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6172 /****************************************************************************
6173 Reply to a SMBtranss2
6174 ****************************************************************************/
6176 int reply_transs2(connection_struct *conn,
6177 char *inbuf,char *outbuf,int size,int bufsize)
6179 int outsize = 0;
6180 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6181 struct trans_state *state;
6183 START_PROFILE(SMBtranss2);
6185 show_msg(inbuf);
6187 for (state = conn->pending_trans; state != NULL;
6188 state = state->next) {
6189 if (state->mid == SVAL(inbuf,smb_mid)) {
6190 break;
6194 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6195 END_PROFILE(SMBtranss2);
6196 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6199 /* Revise state->total_param and state->total_data in case they have
6200 changed downwards */
6202 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6203 state->total_param = SVAL(inbuf, smb_tpscnt);
6204 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6205 state->total_data = SVAL(inbuf, smb_tdscnt);
6207 pcnt = SVAL(inbuf, smb_spscnt);
6208 poff = SVAL(inbuf, smb_spsoff);
6209 pdisp = SVAL(inbuf, smb_spsdisp);
6211 dcnt = SVAL(inbuf, smb_sdscnt);
6212 doff = SVAL(inbuf, smb_sdsoff);
6213 ddisp = SVAL(inbuf, smb_sdsdisp);
6215 state->received_param += pcnt;
6216 state->received_data += dcnt;
6218 if ((state->received_data > state->total_data) ||
6219 (state->received_param > state->total_param))
6220 goto bad_param;
6222 if (pcnt) {
6223 if (pdisp+pcnt > state->total_param)
6224 goto bad_param;
6225 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6226 goto bad_param;
6227 if (pdisp > state->total_param)
6228 goto bad_param;
6229 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6230 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6231 goto bad_param;
6232 if (state->param + pdisp < state->param)
6233 goto bad_param;
6235 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6236 pcnt);
6239 if (dcnt) {
6240 if (ddisp+dcnt > state->total_data)
6241 goto bad_param;
6242 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6243 goto bad_param;
6244 if (ddisp > state->total_data)
6245 goto bad_param;
6246 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6247 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6248 goto bad_param;
6249 if (state->data + ddisp < state->data)
6250 goto bad_param;
6252 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6253 dcnt);
6256 if ((state->received_param < state->total_param) ||
6257 (state->received_data < state->total_data)) {
6258 END_PROFILE(SMBtranss2);
6259 return -1;
6262 /* construct_reply_common has done us the favor to pre-fill the
6263 * command field with SMBtranss2 which is wrong :-)
6265 SCVAL(outbuf,smb_com,SMBtrans2);
6267 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6269 DLIST_REMOVE(conn->pending_trans, state);
6270 SAFE_FREE(state->data);
6271 SAFE_FREE(state->param);
6272 TALLOC_FREE(state);
6274 if (outsize == 0) {
6275 END_PROFILE(SMBtranss2);
6276 return(ERROR_DOS(ERRSRV,ERRnosupport));
6279 END_PROFILE(SMBtranss2);
6280 return(outsize);
6282 bad_param:
6284 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6285 DLIST_REMOVE(conn->pending_trans, state);
6286 SAFE_FREE(state->data);
6287 SAFE_FREE(state->param);
6288 TALLOC_FREE(state);
6289 END_PROFILE(SMBtranss2);
6290 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);