r21058: Finish the easy refactoring - split out all the case
[Samba.git] / source3 / smbd / trans2.c
blob1a48a7b6f28bf53a6a824fcf9e1393ccca2195d9
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
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 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
1010 mode_t ret = 0;
1012 if (perms == SMB_MODE_NO_CHANGE)
1013 return pst->st_mode;
1015 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1016 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1017 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1018 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1019 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1020 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1021 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1022 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1023 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1024 #ifdef S_ISVTX
1025 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1026 #endif
1027 #ifdef S_ISGID
1028 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1029 #endif
1030 #ifdef S_ISUID
1031 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1032 #endif
1034 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
1035 ret &= lp_dir_mask(SNUM(conn));
1036 /* Add in force bits */
1037 ret |= lp_force_dir_mode(SNUM(conn));
1038 } else {
1039 /* Apply mode mask */
1040 ret &= lp_create_mask(SNUM(conn));
1041 /* Add in force bits */
1042 ret |= lp_force_create_mode(SNUM(conn));
1045 return ret;
1048 /****************************************************************************
1049 Get a level dependent lanman2 dir entry.
1050 ****************************************************************************/
1052 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1053 void *inbuf, char *outbuf,
1054 char *path_mask,uint32 dirtype,int info_level,
1055 int requires_resume_key,
1056 BOOL dont_descend,char **ppdata,
1057 char *base_data, int space_remaining,
1058 BOOL *out_of_space, BOOL *got_exact_match,
1059 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1061 const char *dname;
1062 BOOL found = False;
1063 SMB_STRUCT_STAT sbuf;
1064 pstring mask;
1065 pstring pathreal;
1066 pstring fname;
1067 char *p, *q, *pdata = *ppdata;
1068 uint32 reskey=0;
1069 long prev_dirpos=0;
1070 uint32 mode=0;
1071 SMB_OFF_T file_size = 0;
1072 SMB_BIG_UINT allocation_size = 0;
1073 uint32 len;
1074 struct timespec mdate_ts, adate_ts, create_date_ts;
1075 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1076 char *nameptr;
1077 char *last_entry_ptr;
1078 BOOL was_8_3;
1079 uint32 nt_extmode; /* Used for NT connections instead of mode */
1080 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1081 BOOL check_mangled_names = lp_manglednames(conn->params);
1083 *fname = 0;
1084 *out_of_space = False;
1085 *got_exact_match = False;
1087 ZERO_STRUCT(mdate_ts);
1088 ZERO_STRUCT(adate_ts);
1089 ZERO_STRUCT(create_date_ts);
1091 if (!conn->dirptr)
1092 return(False);
1094 p = strrchr_m(path_mask,'/');
1095 if(p != NULL) {
1096 if(p[1] == '\0')
1097 pstrcpy(mask,"*.*");
1098 else
1099 pstrcpy(mask, p+1);
1100 } else
1101 pstrcpy(mask, path_mask);
1104 while (!found) {
1105 BOOL got_match;
1106 BOOL ms_dfs_link = False;
1108 /* Needed if we run out of space */
1109 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1110 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1113 * Due to bugs in NT client redirectors we are not using
1114 * resume keys any more - set them to zero.
1115 * Check out the related comments in findfirst/findnext.
1116 * JRA.
1119 reskey = 0;
1121 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1122 (long)conn->dirptr,curr_dirpos));
1124 if (!dname)
1125 return(False);
1127 pstrcpy(fname,dname);
1129 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1130 got_match = mask_match(fname, mask, conn->case_sensitive);
1132 if(!got_match && check_mangled_names &&
1133 !mangle_is_8_3(fname, False, conn->params)) {
1136 * It turns out that NT matches wildcards against
1137 * both long *and* short names. This may explain some
1138 * of the wildcard wierdness from old DOS clients
1139 * that some people have been seeing.... JRA.
1142 pstring newname;
1143 pstrcpy( newname, fname);
1144 mangle_map( newname, True, False, conn->params);
1145 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1146 got_match = mask_match(newname, mask, conn->case_sensitive);
1149 if(got_match) {
1150 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1151 if (dont_descend && !isdots)
1152 continue;
1154 pstrcpy(pathreal,conn->dirpath);
1155 if(needslash)
1156 pstrcat(pathreal,"/");
1157 pstrcat(pathreal,dname);
1159 if (INFO_LEVEL_IS_UNIX(info_level)) {
1160 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1161 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1162 pathreal,strerror(errno)));
1163 continue;
1165 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1167 /* Needed to show the msdfs symlinks as
1168 * directories */
1170 if(lp_host_msdfs() &&
1171 lp_msdfs_root(SNUM(conn)) &&
1172 ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1174 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1175 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1177 } else {
1179 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1180 pathreal,strerror(errno)));
1181 continue;
1185 if (ms_dfs_link) {
1186 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1187 } else {
1188 mode = dos_mode(conn,pathreal,&sbuf);
1191 if (!dir_check_ftype(conn,mode,dirtype)) {
1192 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1193 continue;
1196 if (!(mode & aDIR))
1197 file_size = get_file_size(sbuf);
1198 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1200 mdate_ts = get_mtimespec(&sbuf);
1201 adate_ts = get_atimespec(&sbuf);
1202 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1204 if (lp_dos_filetime_resolution(SNUM(conn))) {
1205 dos_filetime_timespec(&create_date_ts);
1206 dos_filetime_timespec(&mdate_ts);
1207 dos_filetime_timespec(&adate_ts);
1210 create_date = convert_timespec_to_time_t(create_date_ts);
1211 mdate = convert_timespec_to_time_t(mdate_ts);
1212 adate = convert_timespec_to_time_t(adate_ts);
1214 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1216 found = True;
1218 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1222 mangle_map(fname,False,True,conn->params);
1224 p = pdata;
1225 last_entry_ptr = p;
1227 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1229 switch (info_level) {
1230 case SMB_FIND_INFO_STANDARD:
1231 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1232 if(requires_resume_key) {
1233 SIVAL(p,0,reskey);
1234 p += 4;
1236 srv_put_dos_date2(p,0,create_date);
1237 srv_put_dos_date2(p,4,adate);
1238 srv_put_dos_date2(p,8,mdate);
1239 SIVAL(p,12,(uint32)file_size);
1240 SIVAL(p,16,(uint32)allocation_size);
1241 SSVAL(p,20,mode);
1242 p += 23;
1243 nameptr = p;
1244 p += align_string(outbuf, p, 0);
1245 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1246 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1247 if (len > 2) {
1248 SCVAL(nameptr, -1, len - 2);
1249 } else {
1250 SCVAL(nameptr, -1, 0);
1252 } else {
1253 if (len > 1) {
1254 SCVAL(nameptr, -1, len - 1);
1255 } else {
1256 SCVAL(nameptr, -1, 0);
1259 p += len;
1260 break;
1262 case SMB_FIND_EA_SIZE:
1263 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1264 if(requires_resume_key) {
1265 SIVAL(p,0,reskey);
1266 p += 4;
1268 srv_put_dos_date2(p,0,create_date);
1269 srv_put_dos_date2(p,4,adate);
1270 srv_put_dos_date2(p,8,mdate);
1271 SIVAL(p,12,(uint32)file_size);
1272 SIVAL(p,16,(uint32)allocation_size);
1273 SSVAL(p,20,mode);
1275 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1276 SIVAL(p,22,ea_size); /* Extended attributes */
1278 p += 27;
1279 nameptr = p - 1;
1280 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1281 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1282 if (len > 2) {
1283 len -= 2;
1284 } else {
1285 len = 0;
1287 } else {
1288 if (len > 1) {
1289 len -= 1;
1290 } else {
1291 len = 0;
1294 SCVAL(nameptr,0,len);
1295 p += len;
1296 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1297 break;
1299 case SMB_FIND_EA_LIST:
1301 struct ea_list *file_list = NULL;
1302 size_t ea_len = 0;
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1305 if (!name_list) {
1306 return False;
1308 if(requires_resume_key) {
1309 SIVAL(p,0,reskey);
1310 p += 4;
1312 srv_put_dos_date2(p,0,create_date);
1313 srv_put_dos_date2(p,4,adate);
1314 srv_put_dos_date2(p,8,mdate);
1315 SIVAL(p,12,(uint32)file_size);
1316 SIVAL(p,16,(uint32)allocation_size);
1317 SSVAL(p,20,mode);
1318 p += 22; /* p now points to the EA area. */
1320 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1321 name_list = ea_list_union(name_list, file_list, &ea_len);
1323 /* We need to determine if this entry will fit in the space available. */
1324 /* Max string size is 255 bytes. */
1325 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1326 /* Move the dirptr back to prev_dirpos */
1327 dptr_SeekDir(conn->dirptr, prev_dirpos);
1328 *out_of_space = True;
1329 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1330 return False; /* Not finished - just out of space */
1333 /* Push the ea_data followed by the name. */
1334 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1335 nameptr = p;
1336 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1337 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1338 if (len > 2) {
1339 len -= 2;
1340 } else {
1341 len = 0;
1343 } else {
1344 if (len > 1) {
1345 len -= 1;
1346 } else {
1347 len = 0;
1350 SCVAL(nameptr,0,len);
1351 p += len + 1;
1352 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1353 break;
1356 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1357 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1358 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1359 p += 4;
1360 SIVAL(p,0,reskey); p += 4;
1361 put_long_date_timespec(p,create_date_ts); p += 8;
1362 put_long_date_timespec(p,adate_ts); p += 8;
1363 put_long_date_timespec(p,mdate_ts); p += 8;
1364 put_long_date_timespec(p,mdate_ts); p += 8;
1365 SOFF_T(p,0,file_size); p += 8;
1366 SOFF_T(p,0,allocation_size); p += 8;
1367 SIVAL(p,0,nt_extmode); p += 4;
1368 q = p; p += 4; /* q is placeholder for name length. */
1370 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1371 SIVAL(p,0,ea_size); /* Extended attributes */
1372 p += 4;
1374 /* Clear the short name buffer. This is
1375 * IMPORTANT as not doing so will trigger
1376 * a Win2k client bug. JRA.
1378 if (!was_8_3 && check_mangled_names) {
1379 pstring mangled_name;
1380 pstrcpy(mangled_name, fname);
1381 mangle_map(mangled_name,True,True,
1382 conn->params);
1383 mangled_name[12] = 0;
1384 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1385 if (len < 24) {
1386 memset(p + 2 + len,'\0',24 - len);
1388 SSVAL(p, 0, len);
1389 } else {
1390 memset(p,'\0',26);
1392 p += 2 + 24;
1393 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1394 SIVAL(q,0,len);
1395 p += len;
1396 SIVAL(p,0,0); /* Ensure any padding is null. */
1397 len = PTR_DIFF(p, pdata);
1398 len = (len + 3) & ~3;
1399 SIVAL(pdata,0,len);
1400 p = pdata + len;
1401 break;
1403 case SMB_FIND_FILE_DIRECTORY_INFO:
1404 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1405 p += 4;
1406 SIVAL(p,0,reskey); p += 4;
1407 put_long_date_timespec(p,create_date_ts); p += 8;
1408 put_long_date_timespec(p,adate_ts); p += 8;
1409 put_long_date_timespec(p,mdate_ts); p += 8;
1410 put_long_date_timespec(p,mdate_ts); p += 8;
1411 SOFF_T(p,0,file_size); p += 8;
1412 SOFF_T(p,0,allocation_size); p += 8;
1413 SIVAL(p,0,nt_extmode); p += 4;
1414 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1415 SIVAL(p,0,len);
1416 p += 4 + len;
1417 SIVAL(p,0,0); /* Ensure any padding is null. */
1418 len = PTR_DIFF(p, pdata);
1419 len = (len + 3) & ~3;
1420 SIVAL(pdata,0,len);
1421 p = pdata + len;
1422 break;
1424 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1425 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1426 p += 4;
1427 SIVAL(p,0,reskey); p += 4;
1428 put_long_date_timespec(p,create_date_ts); p += 8;
1429 put_long_date_timespec(p,adate_ts); p += 8;
1430 put_long_date_timespec(p,mdate_ts); p += 8;
1431 put_long_date_timespec(p,mdate_ts); p += 8;
1432 SOFF_T(p,0,file_size); p += 8;
1433 SOFF_T(p,0,allocation_size); p += 8;
1434 SIVAL(p,0,nt_extmode); p += 4;
1435 q = p; p += 4; /* q is placeholder for name length. */
1437 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1438 SIVAL(p,0,ea_size); /* Extended attributes */
1439 p +=4;
1441 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1442 SIVAL(q, 0, len);
1443 p += 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_NAMES_INFO:
1453 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1454 p += 4;
1455 SIVAL(p,0,reskey); p += 4;
1456 p += 4;
1457 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1458 acl on a dir (tridge) */
1459 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1460 SIVAL(p, -4, len);
1461 p += len;
1462 SIVAL(p,0,0); /* Ensure any padding is null. */
1463 len = PTR_DIFF(p, pdata);
1464 len = (len + 3) & ~3;
1465 SIVAL(pdata,0,len);
1466 p = pdata + len;
1467 break;
1469 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1470 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1471 p += 4;
1472 SIVAL(p,0,reskey); p += 4;
1473 put_long_date_timespec(p,create_date_ts); p += 8;
1474 put_long_date_timespec(p,adate_ts); p += 8;
1475 put_long_date_timespec(p,mdate_ts); p += 8;
1476 put_long_date_timespec(p,mdate_ts); p += 8;
1477 SOFF_T(p,0,file_size); p += 8;
1478 SOFF_T(p,0,allocation_size); p += 8;
1479 SIVAL(p,0,nt_extmode); p += 4;
1480 q = p; p += 4; /* q is placeholder for name length. */
1482 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1483 SIVAL(p,0,ea_size); /* Extended attributes */
1484 p +=4;
1486 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1487 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1488 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1489 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1490 SIVAL(q, 0, len);
1491 p += len;
1492 SIVAL(p,0,0); /* Ensure any padding is null. */
1493 len = PTR_DIFF(p, pdata);
1494 len = (len + 3) & ~3;
1495 SIVAL(pdata,0,len);
1496 p = pdata + len;
1497 break;
1499 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1500 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1501 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1502 p += 4;
1503 SIVAL(p,0,reskey); p += 4;
1504 put_long_date_timespec(p,create_date_ts); p += 8;
1505 put_long_date_timespec(p,adate_ts); p += 8;
1506 put_long_date_timespec(p,mdate_ts); p += 8;
1507 put_long_date_timespec(p,mdate_ts); p += 8;
1508 SOFF_T(p,0,file_size); p += 8;
1509 SOFF_T(p,0,allocation_size); p += 8;
1510 SIVAL(p,0,nt_extmode); p += 4;
1511 q = p; p += 4; /* q is placeholder for name length */
1513 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1514 SIVAL(p,0,ea_size); /* Extended attributes */
1515 p +=4;
1517 /* Clear the short name buffer. This is
1518 * IMPORTANT as not doing so will trigger
1519 * a Win2k client bug. JRA.
1521 if (!was_8_3 && check_mangled_names) {
1522 pstring mangled_name;
1523 pstrcpy(mangled_name, fname);
1524 mangle_map(mangled_name,True,True,
1525 conn->params);
1526 mangled_name[12] = 0;
1527 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1528 SSVAL(p, 0, len);
1529 if (len < 24) {
1530 memset(p + 2 + len,'\0',24 - len);
1532 SSVAL(p, 0, len);
1533 } else {
1534 memset(p,'\0',26);
1536 p += 26;
1537 SSVAL(p,0,0); p += 2; /* Reserved ? */
1538 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1539 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1540 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1541 SIVAL(q,0,len);
1542 p += len;
1543 SIVAL(p,0,0); /* Ensure any padding is null. */
1544 len = PTR_DIFF(p, pdata);
1545 len = (len + 3) & ~3;
1546 SIVAL(pdata,0,len);
1547 p = pdata + len;
1548 break;
1550 /* CIFS UNIX Extension. */
1552 case SMB_FIND_FILE_UNIX:
1553 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1554 p+= 4;
1555 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1557 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1558 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1559 p+= 8;
1561 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1562 p+= 8;
1564 put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */
1565 put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
1566 put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
1567 p+= 24;
1569 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1570 SIVAL(p,4,0);
1571 p+= 8;
1573 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1574 SIVAL(p,4,0);
1575 p+= 8;
1577 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1578 p+= 4;
1580 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1581 SIVAL(p,4,0);
1582 p+= 8;
1584 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1585 SIVAL(p,4,0);
1586 p+= 8;
1588 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1589 p+= 8;
1591 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1592 SIVAL(p,4,0);
1593 p+= 8;
1595 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1596 SIVAL(p,4,0);
1597 p+= 8;
1599 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1600 p += len;
1601 SIVAL(p,0,0); /* Ensure any padding is null. */
1603 len = PTR_DIFF(p, pdata);
1604 len = (len + 3) & ~3;
1605 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1606 p = pdata + len;
1607 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1609 break;
1611 default:
1612 return(False);
1616 if (PTR_DIFF(p,pdata) > space_remaining) {
1617 /* Move the dirptr back to prev_dirpos */
1618 dptr_SeekDir(conn->dirptr, prev_dirpos);
1619 *out_of_space = True;
1620 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1621 return False; /* Not finished - just out of space */
1624 /* Setup the last entry pointer, as an offset from base_data */
1625 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1626 /* Advance the data pointer to the next slot */
1627 *ppdata = p;
1629 return(found);
1632 /****************************************************************************
1633 Reply to a TRANS2_FINDFIRST.
1634 ****************************************************************************/
1636 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1637 char **pparams, int total_params, char **ppdata, int total_data,
1638 unsigned int max_data_bytes)
1640 /* We must be careful here that we don't return more than the
1641 allowed number of data bytes. If this means returning fewer than
1642 maxentries then so be it. We assume that the redirector has
1643 enough room for the fixed number of parameter bytes it has
1644 requested. */
1645 char *params = *pparams;
1646 char *pdata = *ppdata;
1647 uint32 dirtype;
1648 int maxentries;
1649 uint16 findfirst_flags;
1650 BOOL close_after_first;
1651 BOOL close_if_end;
1652 BOOL requires_resume_key;
1653 int info_level;
1654 pstring directory;
1655 pstring mask;
1656 char *p;
1657 int last_entry_off=0;
1658 int dptr_num = -1;
1659 int numentries = 0;
1660 int i;
1661 BOOL finished = False;
1662 BOOL dont_descend = False;
1663 BOOL out_of_space = False;
1664 int space_remaining;
1665 BOOL mask_contains_wcard = False;
1666 SMB_STRUCT_STAT sbuf;
1667 TALLOC_CTX *ea_ctx = NULL;
1668 struct ea_list *ea_list = NULL;
1669 NTSTATUS ntstatus = NT_STATUS_OK;
1671 if (total_params < 13) {
1672 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1675 dirtype = SVAL(params,0);
1676 maxentries = SVAL(params,2);
1677 findfirst_flags = SVAL(params,4);
1678 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1679 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1680 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1681 info_level = SVAL(params,6);
1683 *directory = *mask = 0;
1685 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1686 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1687 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1688 info_level, max_data_bytes));
1690 if (!maxentries) {
1691 /* W2K3 seems to treat zero as 1. */
1692 maxentries = 1;
1695 switch (info_level) {
1696 case SMB_FIND_INFO_STANDARD:
1697 case SMB_FIND_EA_SIZE:
1698 case SMB_FIND_EA_LIST:
1699 case SMB_FIND_FILE_DIRECTORY_INFO:
1700 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1701 case SMB_FIND_FILE_NAMES_INFO:
1702 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1703 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1704 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1705 break;
1706 case SMB_FIND_FILE_UNIX:
1707 if (!lp_unix_extensions()) {
1708 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1710 break;
1711 default:
1712 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1715 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1716 if (!NT_STATUS_IS_OK(ntstatus)) {
1717 return ERROR_NT(ntstatus);
1720 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1722 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1723 if (!NT_STATUS_IS_OK(ntstatus)) {
1724 return ERROR_NT(ntstatus);
1726 ntstatus = check_name(conn, directory);
1727 if (!NT_STATUS_IS_OK(ntstatus)) {
1728 return ERROR_NT(ntstatus);
1731 p = strrchr_m(directory,'/');
1732 if(p == NULL) {
1733 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1734 if((directory[0] == '.') && (directory[1] == '\0')) {
1735 pstrcpy(mask,"*");
1736 mask_contains_wcard = True;
1737 } else {
1738 pstrcpy(mask,directory);
1740 pstrcpy(directory,"./");
1741 } else {
1742 pstrcpy(mask,p+1);
1743 *p = 0;
1746 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1748 if (info_level == SMB_FIND_EA_LIST) {
1749 uint32 ea_size;
1751 if (total_data < 4) {
1752 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1755 ea_size = IVAL(pdata,0);
1756 if (ea_size != total_data) {
1757 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1758 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1759 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1762 if (!lp_ea_support(SNUM(conn))) {
1763 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1766 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1767 return ERROR_NT(NT_STATUS_NO_MEMORY);
1770 /* Pull out the list of names. */
1771 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1772 if (!ea_list) {
1773 talloc_destroy(ea_ctx);
1774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1778 *ppdata = (char *)SMB_REALLOC(
1779 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1780 if(*ppdata == NULL ) {
1781 talloc_destroy(ea_ctx);
1782 return ERROR_NT(NT_STATUS_NO_MEMORY);
1784 pdata = *ppdata;
1786 /* Realloc the params space */
1787 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1788 if (*pparams == NULL) {
1789 talloc_destroy(ea_ctx);
1790 return ERROR_NT(NT_STATUS_NO_MEMORY);
1792 params = *pparams;
1794 /* Save the wildcard match and attribs we are using on this directory -
1795 needed as lanman2 assumes these are being saved between calls */
1797 ntstatus = dptr_create(conn,
1798 directory,
1799 False,
1800 True,
1801 SVAL(inbuf,smb_pid),
1802 mask,
1803 mask_contains_wcard,
1804 dirtype,
1805 &conn->dirptr);
1807 if (!NT_STATUS_IS_OK(ntstatus)) {
1808 talloc_destroy(ea_ctx);
1809 return ERROR_NT(ntstatus);
1812 dptr_num = dptr_dnum(conn->dirptr);
1813 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1815 /* We don't need to check for VOL here as this is returned by
1816 a different TRANS2 call. */
1818 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1819 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1820 dont_descend = True;
1822 p = pdata;
1823 space_remaining = max_data_bytes;
1824 out_of_space = False;
1826 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1827 BOOL got_exact_match = False;
1829 /* this is a heuristic to avoid seeking the dirptr except when
1830 absolutely necessary. It allows for a filename of about 40 chars */
1831 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1832 out_of_space = True;
1833 finished = False;
1834 } else {
1835 finished = !get_lanman2_dir_entry(conn,
1836 inbuf, outbuf,
1837 mask,dirtype,info_level,
1838 requires_resume_key,dont_descend,
1839 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1840 &last_entry_off, ea_list, ea_ctx);
1843 if (finished && out_of_space)
1844 finished = False;
1846 if (!finished && !out_of_space)
1847 numentries++;
1850 * As an optimisation if we know we aren't looking
1851 * for a wildcard name (ie. the name matches the wildcard exactly)
1852 * then we can finish on any (first) match.
1853 * This speeds up large directory searches. JRA.
1856 if(got_exact_match)
1857 finished = True;
1859 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1862 talloc_destroy(ea_ctx);
1864 /* Check if we can close the dirptr */
1865 if(close_after_first || (finished && close_if_end)) {
1866 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1867 dptr_close(&dptr_num);
1871 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1872 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1873 * the protocol level is less than NT1. Tested with smbclient. JRA.
1874 * This should fix the OS/2 client bug #2335.
1877 if(numentries == 0) {
1878 dptr_close(&dptr_num);
1879 if (Protocol < PROTOCOL_NT1) {
1880 return ERROR_DOS(ERRDOS,ERRnofiles);
1881 } else {
1882 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1886 /* At this point pdata points to numentries directory entries. */
1888 /* Set up the return parameter block */
1889 SSVAL(params,0,dptr_num);
1890 SSVAL(params,2,numentries);
1891 SSVAL(params,4,finished);
1892 SSVAL(params,6,0); /* Never an EA error */
1893 SSVAL(params,8,last_entry_off);
1895 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1897 if ((! *directory) && dptr_path(dptr_num))
1898 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1900 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1901 smb_fn_name(CVAL(inbuf,smb_com)),
1902 mask, directory, dirtype, numentries ) );
1905 * Force a name mangle here to ensure that the
1906 * mask as an 8.3 name is top of the mangled cache.
1907 * The reasons for this are subtle. Don't remove
1908 * this code unless you know what you are doing
1909 * (see PR#13758). JRA.
1912 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1913 mangle_map(mask, True, True, conn->params);
1915 return(-1);
1918 /****************************************************************************
1919 Reply to a TRANS2_FINDNEXT.
1920 ****************************************************************************/
1922 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1923 char **pparams, int total_params, char **ppdata, int total_data,
1924 unsigned int max_data_bytes)
1926 /* We must be careful here that we don't return more than the
1927 allowed number of data bytes. If this means returning fewer than
1928 maxentries then so be it. We assume that the redirector has
1929 enough room for the fixed number of parameter bytes it has
1930 requested. */
1931 char *params = *pparams;
1932 char *pdata = *ppdata;
1933 int dptr_num;
1934 int maxentries;
1935 uint16 info_level;
1936 uint32 resume_key;
1937 uint16 findnext_flags;
1938 BOOL close_after_request;
1939 BOOL close_if_end;
1940 BOOL requires_resume_key;
1941 BOOL continue_bit;
1942 BOOL mask_contains_wcard = False;
1943 pstring resume_name;
1944 pstring mask;
1945 pstring directory;
1946 char *p;
1947 uint16 dirtype;
1948 int numentries = 0;
1949 int i, last_entry_off=0;
1950 BOOL finished = False;
1951 BOOL dont_descend = False;
1952 BOOL out_of_space = False;
1953 int space_remaining;
1954 TALLOC_CTX *ea_ctx = NULL;
1955 struct ea_list *ea_list = NULL;
1956 NTSTATUS ntstatus = NT_STATUS_OK;
1958 if (total_params < 13) {
1959 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1962 dptr_num = SVAL(params,0);
1963 maxentries = SVAL(params,2);
1964 info_level = SVAL(params,4);
1965 resume_key = IVAL(params,6);
1966 findnext_flags = SVAL(params,10);
1967 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1968 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1969 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1970 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1972 *mask = *directory = *resume_name = 0;
1974 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1975 if (!NT_STATUS_IS_OK(ntstatus)) {
1976 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1977 complain (it thinks we're asking for the directory above the shared
1978 path or an invalid name). Catch this as the resume name is only compared, never used in
1979 a file access. JRA. */
1980 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1981 pstrcpy(resume_name, "..");
1982 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1983 pstrcpy(resume_name, ".");
1984 } else {
1985 return ERROR_NT(ntstatus);
1989 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1990 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1991 resume_key = %d resume name = %s continue=%d level = %d\n",
1992 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1993 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1995 if (!maxentries) {
1996 /* W2K3 seems to treat zero as 1. */
1997 maxentries = 1;
2000 switch (info_level) {
2001 case SMB_FIND_INFO_STANDARD:
2002 case SMB_FIND_EA_SIZE:
2003 case SMB_FIND_EA_LIST:
2004 case SMB_FIND_FILE_DIRECTORY_INFO:
2005 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2006 case SMB_FIND_FILE_NAMES_INFO:
2007 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2008 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2009 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2010 break;
2011 case SMB_FIND_FILE_UNIX:
2012 if (!lp_unix_extensions()) {
2013 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2015 break;
2016 default:
2017 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2020 if (info_level == SMB_FIND_EA_LIST) {
2021 uint32 ea_size;
2023 if (total_data < 4) {
2024 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2027 ea_size = IVAL(pdata,0);
2028 if (ea_size != total_data) {
2029 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2030 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2031 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2034 if (!lp_ea_support(SNUM(conn))) {
2035 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2038 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2039 return ERROR_NT(NT_STATUS_NO_MEMORY);
2042 /* Pull out the list of names. */
2043 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2044 if (!ea_list) {
2045 talloc_destroy(ea_ctx);
2046 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2050 *ppdata = (char *)SMB_REALLOC(
2051 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2052 if(*ppdata == NULL) {
2053 talloc_destroy(ea_ctx);
2054 return ERROR_NT(NT_STATUS_NO_MEMORY);
2057 pdata = *ppdata;
2059 /* Realloc the params space */
2060 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2061 if(*pparams == NULL ) {
2062 talloc_destroy(ea_ctx);
2063 return ERROR_NT(NT_STATUS_NO_MEMORY);
2066 params = *pparams;
2068 /* Check that the dptr is valid */
2069 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2070 talloc_destroy(ea_ctx);
2071 return ERROR_DOS(ERRDOS,ERRnofiles);
2074 string_set(&conn->dirpath,dptr_path(dptr_num));
2076 /* Get the wildcard mask from the dptr */
2077 if((p = dptr_wcard(dptr_num))== NULL) {
2078 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2079 talloc_destroy(ea_ctx);
2080 return ERROR_DOS(ERRDOS,ERRnofiles);
2083 pstrcpy(mask, p);
2084 pstrcpy(directory,conn->dirpath);
2086 /* Get the attr mask from the dptr */
2087 dirtype = dptr_attr(dptr_num);
2089 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2090 dptr_num, mask, dirtype,
2091 (long)conn->dirptr,
2092 dptr_TellDir(conn->dirptr)));
2094 /* We don't need to check for VOL here as this is returned by
2095 a different TRANS2 call. */
2097 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2098 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2099 dont_descend = True;
2101 p = pdata;
2102 space_remaining = max_data_bytes;
2103 out_of_space = False;
2106 * Seek to the correct position. We no longer use the resume key but
2107 * depend on the last file name instead.
2110 if(*resume_name && !continue_bit) {
2111 SMB_STRUCT_STAT st;
2113 long current_pos = 0;
2115 * Remember, mangle_map is called by
2116 * get_lanman2_dir_entry(), so the resume name
2117 * could be mangled. Ensure we check the unmangled name.
2120 if (mangle_is_mangled(resume_name, conn->params)) {
2121 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2122 conn->params);
2126 * Fix for NT redirector problem triggered by resume key indexes
2127 * changing between directory scans. We now return a resume key of 0
2128 * and instead look for the filename to continue from (also given
2129 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2130 * findfirst/findnext (as is usual) then the directory pointer
2131 * should already be at the correct place.
2134 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2135 } /* end if resume_name && !continue_bit */
2137 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2138 BOOL got_exact_match = False;
2140 /* this is a heuristic to avoid seeking the dirptr except when
2141 absolutely necessary. It allows for a filename of about 40 chars */
2142 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2143 out_of_space = True;
2144 finished = False;
2145 } else {
2146 finished = !get_lanman2_dir_entry(conn,
2147 inbuf, outbuf,
2148 mask,dirtype,info_level,
2149 requires_resume_key,dont_descend,
2150 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2151 &last_entry_off, ea_list, ea_ctx);
2154 if (finished && out_of_space)
2155 finished = False;
2157 if (!finished && !out_of_space)
2158 numentries++;
2161 * As an optimisation if we know we aren't looking
2162 * for a wildcard name (ie. the name matches the wildcard exactly)
2163 * then we can finish on any (first) match.
2164 * This speeds up large directory searches. JRA.
2167 if(got_exact_match)
2168 finished = True;
2170 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2173 talloc_destroy(ea_ctx);
2175 /* Check if we can close the dirptr */
2176 if(close_after_request || (finished && close_if_end)) {
2177 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2178 dptr_close(&dptr_num); /* This frees up the saved mask */
2181 /* Set up the return parameter block */
2182 SSVAL(params,0,numentries);
2183 SSVAL(params,2,finished);
2184 SSVAL(params,4,0); /* Never an EA error */
2185 SSVAL(params,6,last_entry_off);
2187 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2189 if ((! *directory) && dptr_path(dptr_num))
2190 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2192 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2193 smb_fn_name(CVAL(inbuf,smb_com)),
2194 mask, directory, dirtype, numentries ) );
2196 return(-1);
2199 /****************************************************************************
2200 Reply to a TRANS2_QFSINFO (query filesystem info).
2201 ****************************************************************************/
2203 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2204 char **pparams, int total_params, char **ppdata, int total_data,
2205 unsigned int max_data_bytes)
2207 char *pdata = *ppdata;
2208 char *params = *pparams;
2209 uint16 info_level;
2210 int data_len, len;
2211 SMB_STRUCT_STAT st;
2212 char *vname = volume_label(SNUM(conn));
2213 int snum = SNUM(conn);
2214 char *fstype = lp_fstype(SNUM(conn));
2215 int quota_flag = 0;
2217 if (total_params < 2) {
2218 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2221 info_level = SVAL(params,0);
2223 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2225 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2226 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2227 return ERROR_DOS(ERRSRV,ERRinvdevice);
2230 *ppdata = (char *)SMB_REALLOC(
2231 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2232 if (*ppdata == NULL ) {
2233 return ERROR_NT(NT_STATUS_NO_MEMORY);
2236 pdata = *ppdata;
2237 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2239 switch (info_level) {
2240 case SMB_INFO_ALLOCATION:
2242 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2243 data_len = 18;
2244 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2245 return(UNIXERROR(ERRHRD,ERRgeneral));
2248 block_size = lp_block_size(snum);
2249 if (bsize < block_size) {
2250 SMB_BIG_UINT factor = block_size/bsize;
2251 bsize = block_size;
2252 dsize /= factor;
2253 dfree /= factor;
2255 if (bsize > block_size) {
2256 SMB_BIG_UINT factor = bsize/block_size;
2257 bsize = block_size;
2258 dsize *= factor;
2259 dfree *= factor;
2261 bytes_per_sector = 512;
2262 sectors_per_unit = bsize/bytes_per_sector;
2264 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2265 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2266 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2268 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2269 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2270 SIVAL(pdata,l1_cUnit,dsize);
2271 SIVAL(pdata,l1_cUnitAvail,dfree);
2272 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2273 break;
2276 case SMB_INFO_VOLUME:
2277 /* Return volume name */
2279 * Add volume serial number - hash of a combination of
2280 * the called hostname and the service name.
2282 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2284 * Win2k3 and previous mess this up by sending a name length
2285 * one byte short. I believe only older clients (OS/2 Win9x) use
2286 * this call so try fixing this by adding a terminating null to
2287 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2289 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2290 SCVAL(pdata,l2_vol_cch,len);
2291 data_len = l2_vol_szVolLabel + len;
2292 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2293 (unsigned)st.st_ctime, len, vname));
2294 break;
2296 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2297 case SMB_FS_ATTRIBUTE_INFORMATION:
2300 #if defined(HAVE_SYS_QUOTAS)
2301 quota_flag = FILE_VOLUME_QUOTAS;
2302 #endif
2304 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2305 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2306 quota_flag); /* FS ATTRIBUTES */
2308 SIVAL(pdata,4,255); /* Max filename component length */
2309 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2310 and will think we can't do long filenames */
2311 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2312 SIVAL(pdata,8,len);
2313 data_len = 12 + len;
2314 break;
2316 case SMB_QUERY_FS_LABEL_INFO:
2317 case SMB_FS_LABEL_INFORMATION:
2318 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2319 data_len = 4 + len;
2320 SIVAL(pdata,0,len);
2321 break;
2323 case SMB_QUERY_FS_VOLUME_INFO:
2324 case SMB_FS_VOLUME_INFORMATION:
2327 * Add volume serial number - hash of a combination of
2328 * the called hostname and the service name.
2330 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2331 (str_checksum(get_local_machine_name())<<16));
2333 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2334 SIVAL(pdata,12,len);
2335 data_len = 18+len;
2336 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2337 (int)strlen(vname),vname, lp_servicename(snum)));
2338 break;
2340 case SMB_QUERY_FS_SIZE_INFO:
2341 case SMB_FS_SIZE_INFORMATION:
2343 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2344 data_len = 24;
2345 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2346 return(UNIXERROR(ERRHRD,ERRgeneral));
2348 block_size = lp_block_size(snum);
2349 if (bsize < block_size) {
2350 SMB_BIG_UINT factor = block_size/bsize;
2351 bsize = block_size;
2352 dsize /= factor;
2353 dfree /= factor;
2355 if (bsize > block_size) {
2356 SMB_BIG_UINT factor = bsize/block_size;
2357 bsize = block_size;
2358 dsize *= factor;
2359 dfree *= factor;
2361 bytes_per_sector = 512;
2362 sectors_per_unit = bsize/bytes_per_sector;
2363 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2364 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2365 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2366 SBIG_UINT(pdata,0,dsize);
2367 SBIG_UINT(pdata,8,dfree);
2368 SIVAL(pdata,16,sectors_per_unit);
2369 SIVAL(pdata,20,bytes_per_sector);
2370 break;
2373 case SMB_FS_FULL_SIZE_INFORMATION:
2375 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2376 data_len = 32;
2377 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2378 return(UNIXERROR(ERRHRD,ERRgeneral));
2380 block_size = lp_block_size(snum);
2381 if (bsize < block_size) {
2382 SMB_BIG_UINT factor = block_size/bsize;
2383 bsize = block_size;
2384 dsize /= factor;
2385 dfree /= factor;
2387 if (bsize > block_size) {
2388 SMB_BIG_UINT factor = bsize/block_size;
2389 bsize = block_size;
2390 dsize *= factor;
2391 dfree *= factor;
2393 bytes_per_sector = 512;
2394 sectors_per_unit = bsize/bytes_per_sector;
2395 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2396 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2397 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2398 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2399 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2400 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2401 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2402 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2403 break;
2406 case SMB_QUERY_FS_DEVICE_INFO:
2407 case SMB_FS_DEVICE_INFORMATION:
2408 data_len = 8;
2409 SIVAL(pdata,0,0); /* dev type */
2410 SIVAL(pdata,4,0); /* characteristics */
2411 break;
2413 #ifdef HAVE_SYS_QUOTAS
2414 case SMB_FS_QUOTA_INFORMATION:
2416 * what we have to send --metze:
2418 * Unknown1: 24 NULL bytes
2419 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2420 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2421 * Quota Flags: 2 byte :
2422 * Unknown3: 6 NULL bytes
2424 * 48 bytes total
2426 * details for Quota Flags:
2428 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2429 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2430 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2431 * 0x0001 Enable Quotas: enable quota for this fs
2435 /* we need to fake up a fsp here,
2436 * because its not send in this call
2438 files_struct fsp;
2439 SMB_NTQUOTA_STRUCT quotas;
2441 ZERO_STRUCT(fsp);
2442 ZERO_STRUCT(quotas);
2444 fsp.conn = conn;
2445 fsp.fnum = -1;
2447 /* access check */
2448 if (current_user.ut.uid != 0) {
2449 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2450 lp_servicename(SNUM(conn)),conn->user));
2451 return ERROR_DOS(ERRDOS,ERRnoaccess);
2454 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2455 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2456 return ERROR_DOS(ERRSRV,ERRerror);
2459 data_len = 48;
2461 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2463 /* Unknown1 24 NULL bytes*/
2464 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2465 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2466 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2468 /* Default Soft Quota 8 bytes */
2469 SBIG_UINT(pdata,24,quotas.softlim);
2471 /* Default Hard Quota 8 bytes */
2472 SBIG_UINT(pdata,32,quotas.hardlim);
2474 /* Quota flag 2 bytes */
2475 SSVAL(pdata,40,quotas.qflags);
2477 /* Unknown3 6 NULL bytes */
2478 SSVAL(pdata,42,0);
2479 SIVAL(pdata,44,0);
2481 break;
2483 #endif /* HAVE_SYS_QUOTAS */
2484 case SMB_FS_OBJECTID_INFORMATION:
2485 data_len = 64;
2486 break;
2489 * Query the version and capabilities of the CIFS UNIX extensions
2490 * in use.
2493 case SMB_QUERY_CIFS_UNIX_INFO:
2494 if (!lp_unix_extensions()) {
2495 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2497 data_len = 12;
2498 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2499 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2500 /* We have POSIX ACLs, pathname and locking capability. */
2501 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2502 CIFS_UNIX_POSIX_ACLS_CAP|
2503 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2504 CIFS_UNIX_FCNTL_LOCKS_CAP)));
2505 break;
2507 case SMB_QUERY_POSIX_FS_INFO:
2509 int rc;
2510 vfs_statvfs_struct svfs;
2512 if (!lp_unix_extensions()) {
2513 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2516 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2518 if (!rc) {
2519 data_len = 56;
2520 SIVAL(pdata,0,svfs.OptimalTransferSize);
2521 SIVAL(pdata,4,svfs.BlockSize);
2522 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2523 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2524 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2525 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2526 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2527 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2528 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2529 #ifdef EOPNOTSUPP
2530 } else if (rc == EOPNOTSUPP) {
2531 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2532 #endif /* EOPNOTSUPP */
2533 } else {
2534 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2535 return ERROR_DOS(ERRSRV,ERRerror);
2537 break;
2540 case SMB_MAC_QUERY_FS_INFO:
2542 * Thursby MAC extension... ONLY on NTFS filesystems
2543 * once we do streams then we don't need this
2545 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2546 data_len = 88;
2547 SIVAL(pdata,84,0x100); /* Don't support mac... */
2548 break;
2550 /* drop through */
2551 default:
2552 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2556 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2558 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2560 return -1;
2563 /****************************************************************************
2564 Reply to a TRANS2_SETFSINFO (set filesystem info).
2565 ****************************************************************************/
2567 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2568 char **pparams, int total_params, char **ppdata, int total_data,
2569 unsigned int max_data_bytes)
2571 char *pdata = *ppdata;
2572 char *params = *pparams;
2573 uint16 info_level;
2574 int outsize;
2576 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2578 /* */
2579 if (total_params < 4) {
2580 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2581 total_params));
2582 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2585 info_level = SVAL(params,2);
2587 switch(info_level) {
2588 case SMB_SET_CIFS_UNIX_INFO:
2590 uint16 client_unix_major;
2591 uint16 client_unix_minor;
2592 uint32 client_unix_cap_low;
2593 uint32 client_unix_cap_high;
2595 if (!lp_unix_extensions()) {
2596 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2599 /* There should be 12 bytes of capabilities set. */
2600 if (total_data < 8) {
2601 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2603 client_unix_major = SVAL(pdata,0);
2604 client_unix_minor = SVAL(pdata,2);
2605 client_unix_cap_low = IVAL(pdata,4);
2606 client_unix_cap_high = IVAL(pdata,8);
2607 /* Just print these values for now. */
2608 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2609 cap_low = 0x%x, cap_high = 0x%x\n",
2610 (unsigned int)client_unix_major,
2611 (unsigned int)client_unix_minor,
2612 (unsigned int)client_unix_cap_low,
2613 (unsigned int)client_unix_cap_high ));
2615 /* Here is where we must switch to posix pathname processing... */
2616 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2617 lp_set_posix_pathnames();
2618 mangle_change_to_posix();
2621 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2622 lp_set_posix_cifsx_locktype(POSIX_LOCK);
2624 break;
2626 case SMB_FS_QUOTA_INFORMATION:
2628 files_struct *fsp = NULL;
2629 SMB_NTQUOTA_STRUCT quotas;
2631 ZERO_STRUCT(quotas);
2633 /* access check */
2634 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2635 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2636 lp_servicename(SNUM(conn)),conn->user));
2637 return ERROR_DOS(ERRSRV,ERRaccess);
2640 /* note: normaly there're 48 bytes,
2641 * but we didn't use the last 6 bytes for now
2642 * --metze
2644 fsp = file_fsp(params,0);
2645 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2646 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2647 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2650 if (total_data < 42) {
2651 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2652 total_data));
2653 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2656 /* unknown_1 24 NULL bytes in pdata*/
2658 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2659 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2660 #ifdef LARGE_SMB_OFF_T
2661 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2662 #else /* LARGE_SMB_OFF_T */
2663 if ((IVAL(pdata,28) != 0)&&
2664 ((quotas.softlim != 0xFFFFFFFF)||
2665 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2666 /* more than 32 bits? */
2667 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2669 #endif /* LARGE_SMB_OFF_T */
2671 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2672 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2673 #ifdef LARGE_SMB_OFF_T
2674 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2675 #else /* LARGE_SMB_OFF_T */
2676 if ((IVAL(pdata,36) != 0)&&
2677 ((quotas.hardlim != 0xFFFFFFFF)||
2678 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2679 /* more than 32 bits? */
2680 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2682 #endif /* LARGE_SMB_OFF_T */
2684 /* quota_flags 2 bytes **/
2685 quotas.qflags = SVAL(pdata,40);
2687 /* unknown_2 6 NULL bytes follow*/
2689 /* now set the quotas */
2690 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2691 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2692 return ERROR_DOS(ERRSRV,ERRerror);
2695 break;
2697 default:
2698 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2699 info_level));
2700 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2701 break;
2705 * sending this reply works fine,
2706 * but I'm not sure it's the same
2707 * like windows do...
2708 * --metze
2710 outsize = set_message(outbuf,10,0,True);
2712 return outsize;
2715 #if defined(HAVE_POSIX_ACLS)
2716 /****************************************************************************
2717 Utility function to count the number of entries in a POSIX acl.
2718 ****************************************************************************/
2720 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2722 unsigned int ace_count = 0;
2723 int entry_id = SMB_ACL_FIRST_ENTRY;
2724 SMB_ACL_ENTRY_T entry;
2726 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2727 /* get_next... */
2728 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2729 entry_id = SMB_ACL_NEXT_ENTRY;
2731 ace_count++;
2733 return ace_count;
2736 /****************************************************************************
2737 Utility function to marshall a POSIX acl into wire format.
2738 ****************************************************************************/
2740 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2742 int entry_id = SMB_ACL_FIRST_ENTRY;
2743 SMB_ACL_ENTRY_T entry;
2745 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2746 SMB_ACL_TAG_T tagtype;
2747 SMB_ACL_PERMSET_T permset;
2748 unsigned char perms = 0;
2749 unsigned int own_grp;
2751 /* get_next... */
2752 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2753 entry_id = SMB_ACL_NEXT_ENTRY;
2756 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2757 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2758 return False;
2761 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2762 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2763 return False;
2766 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2767 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2768 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2770 SCVAL(pdata,1,perms);
2772 switch (tagtype) {
2773 case SMB_ACL_USER_OBJ:
2774 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2775 own_grp = (unsigned int)pst->st_uid;
2776 SIVAL(pdata,2,own_grp);
2777 SIVAL(pdata,6,0);
2778 break;
2779 case SMB_ACL_USER:
2781 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2782 if (!puid) {
2783 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2785 own_grp = (unsigned int)*puid;
2786 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2787 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2788 SIVAL(pdata,2,own_grp);
2789 SIVAL(pdata,6,0);
2790 break;
2792 case SMB_ACL_GROUP_OBJ:
2793 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2794 own_grp = (unsigned int)pst->st_gid;
2795 SIVAL(pdata,2,own_grp);
2796 SIVAL(pdata,6,0);
2797 break;
2798 case SMB_ACL_GROUP:
2800 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2801 if (!pgid) {
2802 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2804 own_grp = (unsigned int)*pgid;
2805 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2806 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2807 SIVAL(pdata,2,own_grp);
2808 SIVAL(pdata,6,0);
2809 break;
2811 case SMB_ACL_MASK:
2812 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2813 SIVAL(pdata,2,0xFFFFFFFF);
2814 SIVAL(pdata,6,0xFFFFFFFF);
2815 break;
2816 case SMB_ACL_OTHER:
2817 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2818 SIVAL(pdata,2,0xFFFFFFFF);
2819 SIVAL(pdata,6,0xFFFFFFFF);
2820 break;
2821 default:
2822 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2823 return False;
2825 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2828 return True;
2830 #endif
2832 /****************************************************************************
2833 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2834 file name or file id).
2835 ****************************************************************************/
2837 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2838 unsigned int tran_call,
2839 char **pparams, int total_params, char **ppdata, int total_data,
2840 unsigned int max_data_bytes)
2842 char *params = *pparams;
2843 char *pdata = *ppdata;
2844 uint16 info_level;
2845 int mode=0;
2846 int nlink;
2847 SMB_OFF_T file_size=0;
2848 SMB_BIG_UINT allocation_size=0;
2849 unsigned int data_size = 0;
2850 unsigned int param_size = 2;
2851 SMB_STRUCT_STAT sbuf;
2852 pstring fname, dos_fname;
2853 char *fullpathname;
2854 char *base_name;
2855 char *p;
2856 SMB_OFF_T pos = 0;
2857 BOOL delete_pending = False;
2858 int len;
2859 time_t create_time, mtime, atime;
2860 struct timespec create_time_ts, mtime_ts, atime_ts;
2861 files_struct *fsp = NULL;
2862 TALLOC_CTX *data_ctx = NULL;
2863 struct ea_list *ea_list = NULL;
2864 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2865 char *lock_data = NULL;
2867 if (!params)
2868 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2870 ZERO_STRUCT(sbuf);
2872 if (tran_call == TRANSACT2_QFILEINFO) {
2873 if (total_params < 4) {
2874 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2877 fsp = file_fsp(params,0);
2878 info_level = SVAL(params,2);
2880 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2882 if(fsp && (fsp->fake_file_handle)) {
2884 * This is actually for the QUOTA_FAKE_FILE --metze
2887 pstrcpy(fname, fsp->fsp_name);
2888 /* We know this name is ok, it's already passed the checks. */
2890 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2892 * This is actually a QFILEINFO on a directory
2893 * handle (returned from an NT SMB). NT5.0 seems
2894 * to do this call. JRA.
2896 /* We know this name is ok, it's already passed the checks. */
2897 pstrcpy(fname, fsp->fsp_name);
2899 if (INFO_LEVEL_IS_UNIX(info_level)) {
2900 /* Always do lstat for UNIX calls. */
2901 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2902 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2903 return UNIXERROR(ERRDOS,ERRbadpath);
2905 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2906 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2907 return UNIXERROR(ERRDOS,ERRbadpath);
2910 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2911 } else {
2913 * Original code - this is an open file.
2915 CHECK_FSP(fsp,conn);
2917 pstrcpy(fname, fsp->fsp_name);
2918 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2919 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2920 return(UNIXERROR(ERRDOS,ERRbadfid));
2922 pos = fsp->fh->position_information;
2923 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2924 access_mask = fsp->access_mask;
2926 } else {
2927 NTSTATUS status = NT_STATUS_OK;
2929 /* qpathinfo */
2930 if (total_params < 7) {
2931 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2934 info_level = SVAL(params,0);
2936 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2938 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
2939 if (!NT_STATUS_IS_OK(status)) {
2940 return ERROR_NT(status);
2943 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2945 status = unix_convert(conn, fname, False, NULL, &sbuf);
2946 if (!NT_STATUS_IS_OK(status)) {
2947 return ERROR_NT(status);
2949 status = check_name(conn, fname);
2950 if (!NT_STATUS_IS_OK(status)) {
2951 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
2952 return ERROR_NT(status);
2955 if (INFO_LEVEL_IS_UNIX(info_level)) {
2956 /* Always do lstat for UNIX calls. */
2957 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2958 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2959 return UNIXERROR(ERRDOS,ERRbadpath);
2961 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2962 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2963 return UNIXERROR(ERRDOS,ERRbadpath);
2966 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2967 if (delete_pending) {
2968 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2972 nlink = sbuf.st_nlink;
2974 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2975 /* NTFS does not seem to count ".." */
2976 nlink -= 1;
2979 if ((nlink > 0) && delete_pending) {
2980 nlink -= 1;
2983 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2984 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2987 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2988 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2990 p = strrchr_m(fname,'/');
2991 if (!p)
2992 base_name = fname;
2993 else
2994 base_name = p+1;
2996 mode = dos_mode(conn,fname,&sbuf);
2997 if (!mode)
2998 mode = FILE_ATTRIBUTE_NORMAL;
3000 fullpathname = fname;
3001 if (!(mode & aDIR))
3002 file_size = get_file_size(sbuf);
3004 /* Pull out any data sent here before we realloc. */
3005 switch (info_level) {
3006 case SMB_INFO_QUERY_EAS_FROM_LIST:
3008 /* Pull any EA list from the data portion. */
3009 uint32 ea_size;
3011 if (total_data < 4) {
3012 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3014 ea_size = IVAL(pdata,0);
3016 if (total_data > 0 && ea_size != total_data) {
3017 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3018 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3019 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3022 if (!lp_ea_support(SNUM(conn))) {
3023 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3026 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3027 return ERROR_NT(NT_STATUS_NO_MEMORY);
3030 /* Pull out the list of names. */
3031 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3032 if (!ea_list) {
3033 talloc_destroy(data_ctx);
3034 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3036 break;
3039 case SMB_QUERY_POSIX_LOCK:
3041 if (fsp == NULL || fsp->fh->fd == -1) {
3042 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3045 if (total_data != POSIX_LOCK_DATA_SIZE) {
3046 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3049 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3050 return ERROR_NT(NT_STATUS_NO_MEMORY);
3053 /* Copy the lock range data. */
3054 lock_data = (char *)talloc_memdup(
3055 data_ctx, pdata, total_data);
3056 if (!lock_data) {
3057 talloc_destroy(data_ctx);
3058 return ERROR_NT(NT_STATUS_NO_MEMORY);
3061 default:
3062 break;
3065 *pparams = (char *)SMB_REALLOC(*pparams,2);
3066 if (*pparams == NULL) {
3067 talloc_destroy(data_ctx);
3068 return ERROR_NT(NT_STATUS_NO_MEMORY);
3070 params = *pparams;
3071 SSVAL(params,0,0);
3072 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3073 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3074 if (*ppdata == NULL ) {
3075 talloc_destroy(data_ctx);
3076 return ERROR_NT(NT_STATUS_NO_MEMORY);
3078 pdata = *ppdata;
3080 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3081 mtime_ts = get_mtimespec(&sbuf);
3082 atime_ts = get_atimespec(&sbuf);
3084 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3086 if (fsp) {
3087 if (fsp->pending_modtime) {
3088 /* the pending modtime overrides the current modtime */
3089 mtime_ts.tv_sec = fsp->pending_modtime;
3090 mtime_ts.tv_nsec = 0;
3092 } else {
3093 /* Do we have this path open ? */
3094 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3095 if (fsp1 && fsp1->pending_modtime) {
3096 /* the pending modtime overrides the current modtime */
3097 mtime_ts.tv_sec = fsp1->pending_modtime;
3098 mtime_ts.tv_nsec = 0;
3100 if (fsp1 && fsp1->initial_allocation_size) {
3101 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3105 if (lp_dos_filetime_resolution(SNUM(conn))) {
3106 dos_filetime_timespec(&create_time_ts);
3107 dos_filetime_timespec(&mtime_ts);
3108 dos_filetime_timespec(&atime_ts);
3111 create_time = convert_timespec_to_time_t(create_time_ts);
3112 mtime = convert_timespec_to_time_t(mtime_ts);
3113 atime = convert_timespec_to_time_t(atime_ts);
3115 /* NT expects the name to be in an exact form of the *full*
3116 filename. See the trans2 torture test */
3117 if (strequal(base_name,".")) {
3118 pstrcpy(dos_fname, "\\");
3119 } else {
3120 pstr_sprintf(dos_fname, "\\%s", fname);
3121 string_replace(dos_fname, '/', '\\');
3124 switch (info_level) {
3125 case SMB_INFO_STANDARD:
3126 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3127 data_size = 22;
3128 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3129 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3130 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3131 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3132 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3133 SSVAL(pdata,l1_attrFile,mode);
3134 break;
3136 case SMB_INFO_QUERY_EA_SIZE:
3138 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3139 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3140 data_size = 26;
3141 srv_put_dos_date2(pdata,0,create_time);
3142 srv_put_dos_date2(pdata,4,atime);
3143 srv_put_dos_date2(pdata,8,mtime); /* write time */
3144 SIVAL(pdata,12,(uint32)file_size);
3145 SIVAL(pdata,16,(uint32)allocation_size);
3146 SSVAL(pdata,20,mode);
3147 SIVAL(pdata,22,ea_size);
3148 break;
3151 case SMB_INFO_IS_NAME_VALID:
3152 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3153 if (tran_call == TRANSACT2_QFILEINFO) {
3154 /* os/2 needs this ? really ?*/
3155 return ERROR_DOS(ERRDOS,ERRbadfunc);
3157 data_size = 0;
3158 param_size = 0;
3159 break;
3161 case SMB_INFO_QUERY_EAS_FROM_LIST:
3163 size_t total_ea_len = 0;
3164 struct ea_list *ea_file_list = NULL;
3166 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3168 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3169 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3171 if (!ea_list || (total_ea_len > data_size)) {
3172 talloc_destroy(data_ctx);
3173 data_size = 4;
3174 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3175 break;
3178 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3179 talloc_destroy(data_ctx);
3180 break;
3183 case SMB_INFO_QUERY_ALL_EAS:
3185 /* We have data_size bytes to put EA's into. */
3186 size_t total_ea_len = 0;
3188 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3190 data_ctx = talloc_init("ea_ctx");
3191 if (!data_ctx) {
3192 return ERROR_NT(NT_STATUS_NO_MEMORY);
3195 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3196 if (!ea_list || (total_ea_len > data_size)) {
3197 talloc_destroy(data_ctx);
3198 data_size = 4;
3199 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3200 break;
3203 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3204 talloc_destroy(data_ctx);
3205 break;
3208 case SMB_FILE_BASIC_INFORMATION:
3209 case SMB_QUERY_FILE_BASIC_INFO:
3211 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3212 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3213 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3214 } else {
3215 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3216 data_size = 40;
3217 SIVAL(pdata,36,0);
3219 put_long_date_timespec(pdata,create_time_ts);
3220 put_long_date_timespec(pdata+8,atime_ts);
3221 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3222 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3223 SIVAL(pdata,32,mode);
3225 DEBUG(5,("SMB_QFBI - "));
3226 DEBUG(5,("create: %s ", ctime(&create_time)));
3227 DEBUG(5,("access: %s ", ctime(&atime)));
3228 DEBUG(5,("write: %s ", ctime(&mtime)));
3229 DEBUG(5,("change: %s ", ctime(&mtime)));
3230 DEBUG(5,("mode: %x\n", mode));
3231 break;
3233 case SMB_FILE_STANDARD_INFORMATION:
3234 case SMB_QUERY_FILE_STANDARD_INFO:
3236 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3237 data_size = 24;
3238 SOFF_T(pdata,0,allocation_size);
3239 SOFF_T(pdata,8,file_size);
3240 SIVAL(pdata,16,nlink);
3241 SCVAL(pdata,20,delete_pending?1:0);
3242 SCVAL(pdata,21,(mode&aDIR)?1:0);
3243 SSVAL(pdata,22,0); /* Padding. */
3244 break;
3246 case SMB_FILE_EA_INFORMATION:
3247 case SMB_QUERY_FILE_EA_INFO:
3249 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3250 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3251 data_size = 4;
3252 SIVAL(pdata,0,ea_size);
3253 break;
3256 /* Get the 8.3 name - used if NT SMB was negotiated. */
3257 case SMB_QUERY_FILE_ALT_NAME_INFO:
3258 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3260 pstring short_name;
3262 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3263 pstrcpy(short_name,base_name);
3264 /* Mangle if not already 8.3 */
3265 if(!mangle_is_8_3(short_name, True, conn->params)) {
3266 mangle_map(short_name,True,True,conn->params);
3268 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3269 data_size = 4 + len;
3270 SIVAL(pdata,0,len);
3271 break;
3274 case SMB_QUERY_FILE_NAME_INFO:
3276 this must be *exactly* right for ACLs on mapped drives to work
3278 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3279 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3280 data_size = 4 + len;
3281 SIVAL(pdata,0,len);
3282 break;
3284 case SMB_FILE_ALLOCATION_INFORMATION:
3285 case SMB_QUERY_FILE_ALLOCATION_INFO:
3286 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3287 data_size = 8;
3288 SOFF_T(pdata,0,allocation_size);
3289 break;
3291 case SMB_FILE_END_OF_FILE_INFORMATION:
3292 case SMB_QUERY_FILE_END_OF_FILEINFO:
3293 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3294 data_size = 8;
3295 SOFF_T(pdata,0,file_size);
3296 break;
3298 case SMB_QUERY_FILE_ALL_INFO:
3299 case SMB_FILE_ALL_INFORMATION:
3301 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3302 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3303 put_long_date_timespec(pdata,create_time_ts);
3304 put_long_date_timespec(pdata+8,atime_ts);
3305 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3306 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3307 SIVAL(pdata,32,mode);
3308 SIVAL(pdata,36,0); /* padding. */
3309 pdata += 40;
3310 SOFF_T(pdata,0,allocation_size);
3311 SOFF_T(pdata,8,file_size);
3312 SIVAL(pdata,16,nlink);
3313 SCVAL(pdata,20,delete_pending);
3314 SCVAL(pdata,21,(mode&aDIR)?1:0);
3315 SSVAL(pdata,22,0);
3316 pdata += 24;
3317 SIVAL(pdata,0,ea_size);
3318 pdata += 4; /* EA info */
3319 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3320 SIVAL(pdata,0,len);
3321 pdata += 4 + len;
3322 data_size = PTR_DIFF(pdata,(*ppdata));
3323 break;
3325 case SMB_FILE_INTERNAL_INFORMATION:
3326 /* This should be an index number - looks like
3327 dev/ino to me :-)
3329 I think this causes us to fail the IFSKIT
3330 BasicFileInformationTest. -tpot */
3332 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3333 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3334 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3335 data_size = 8;
3336 break;
3338 case SMB_FILE_ACCESS_INFORMATION:
3339 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3340 SIVAL(pdata,0,access_mask);
3341 data_size = 4;
3342 break;
3344 case SMB_FILE_NAME_INFORMATION:
3345 /* Pathname with leading '\'. */
3347 size_t byte_len;
3348 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3349 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3350 SIVAL(pdata,0,byte_len);
3351 data_size = 4 + byte_len;
3352 break;
3355 case SMB_FILE_DISPOSITION_INFORMATION:
3356 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3357 data_size = 1;
3358 SCVAL(pdata,0,delete_pending);
3359 break;
3361 case SMB_FILE_POSITION_INFORMATION:
3362 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3363 data_size = 8;
3364 SOFF_T(pdata,0,pos);
3365 break;
3367 case SMB_FILE_MODE_INFORMATION:
3368 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3369 SIVAL(pdata,0,mode);
3370 data_size = 4;
3371 break;
3373 case SMB_FILE_ALIGNMENT_INFORMATION:
3374 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3375 SIVAL(pdata,0,0); /* No alignment needed. */
3376 data_size = 4;
3377 break;
3379 #if 0
3381 * NT4 server just returns "invalid query" to this - if we try to answer
3382 * it then NTws gets a BSOD! (tridge).
3383 * W2K seems to want this. JRA.
3385 case SMB_QUERY_FILE_STREAM_INFO:
3386 #endif
3387 case SMB_FILE_STREAM_INFORMATION:
3388 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3389 if (mode & aDIR) {
3390 data_size = 0;
3391 } else {
3392 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3393 SIVAL(pdata,0,0); /* ??? */
3394 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3395 SOFF_T(pdata,8,file_size);
3396 SIVAL(pdata,16,allocation_size);
3397 SIVAL(pdata,20,0); /* ??? */
3398 data_size = 24 + byte_len;
3400 break;
3402 case SMB_QUERY_COMPRESSION_INFO:
3403 case SMB_FILE_COMPRESSION_INFORMATION:
3404 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3405 SOFF_T(pdata,0,file_size);
3406 SIVAL(pdata,8,0); /* ??? */
3407 SIVAL(pdata,12,0); /* ??? */
3408 data_size = 16;
3409 break;
3411 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3412 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3413 put_long_date_timespec(pdata,create_time_ts);
3414 put_long_date_timespec(pdata+8,atime_ts);
3415 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3416 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3417 SIVAL(pdata,32,allocation_size);
3418 SOFF_T(pdata,40,file_size);
3419 SIVAL(pdata,48,mode);
3420 SIVAL(pdata,52,0); /* ??? */
3421 data_size = 56;
3422 break;
3424 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3425 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3426 SIVAL(pdata,0,mode);
3427 SIVAL(pdata,4,0);
3428 data_size = 8;
3429 break;
3432 * CIFS UNIX Extensions.
3435 case SMB_QUERY_FILE_UNIX_BASIC:
3437 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3438 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3440 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3441 pdata += 8;
3443 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3444 pdata += 8;
3446 put_long_date_timespec(pdata,get_ctimespec(&sbuf)); /* Creation Time 64 Bit */
3447 put_long_date_timespec(pdata+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
3448 put_long_date_timespec(pdata+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
3449 pdata += 24;
3451 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3452 SIVAL(pdata,4,0);
3453 pdata += 8;
3455 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3456 SIVAL(pdata,4,0);
3457 pdata += 8;
3459 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3460 pdata += 4;
3462 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3463 SIVAL(pdata,4,0);
3464 pdata += 8;
3466 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3467 SIVAL(pdata,4,0);
3468 pdata += 8;
3470 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3471 pdata += 8;
3473 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3474 SIVAL(pdata,4,0);
3475 pdata += 8;
3477 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3478 SIVAL(pdata,4,0);
3479 pdata += 8;
3480 data_size = PTR_DIFF(pdata,(*ppdata));
3483 int i;
3484 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3486 for (i=0; i<100; i++)
3487 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3488 DEBUG(4,("\n"));
3491 break;
3493 case SMB_QUERY_FILE_UNIX_LINK:
3495 pstring buffer;
3497 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3498 #ifdef S_ISLNK
3499 if(!S_ISLNK(sbuf.st_mode))
3500 return(UNIXERROR(ERRSRV,ERRbadlink));
3501 #else
3502 return(UNIXERROR(ERRDOS,ERRbadlink));
3503 #endif
3504 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3505 if (len == -1)
3506 return(UNIXERROR(ERRDOS,ERRnoaccess));
3507 buffer[len] = 0;
3508 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3509 pdata += len;
3510 data_size = PTR_DIFF(pdata,(*ppdata));
3512 break;
3515 #if defined(HAVE_POSIX_ACLS)
3516 case SMB_QUERY_POSIX_ACL:
3518 SMB_ACL_T file_acl = NULL;
3519 SMB_ACL_T def_acl = NULL;
3520 uint16 num_file_acls = 0;
3521 uint16 num_def_acls = 0;
3523 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3524 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3525 } else {
3526 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3529 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3530 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3531 fname ));
3532 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3535 if (S_ISDIR(sbuf.st_mode)) {
3536 if (fsp && fsp->is_directory) {
3537 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3538 } else {
3539 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3541 def_acl = free_empty_sys_acl(conn, def_acl);
3544 num_file_acls = count_acl_entries(conn, file_acl);
3545 num_def_acls = count_acl_entries(conn, def_acl);
3547 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3548 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3549 data_size,
3550 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3551 SMB_POSIX_ACL_HEADER_SIZE) ));
3552 if (file_acl) {
3553 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3555 if (def_acl) {
3556 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3558 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3561 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3562 SSVAL(pdata,2,num_file_acls);
3563 SSVAL(pdata,4,num_def_acls);
3564 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3565 if (file_acl) {
3566 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3568 if (def_acl) {
3569 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3571 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3573 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3574 if (file_acl) {
3575 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3577 if (def_acl) {
3578 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3580 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3583 if (file_acl) {
3584 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3586 if (def_acl) {
3587 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3589 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3590 break;
3592 #endif
3595 case SMB_QUERY_POSIX_LOCK:
3597 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3598 SMB_BIG_UINT count;
3599 SMB_BIG_UINT offset;
3600 uint32 lock_pid;
3601 enum brl_type lock_type;
3603 if (total_data != POSIX_LOCK_DATA_SIZE) {
3604 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3607 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3608 case POSIX_LOCK_TYPE_READ:
3609 lock_type = READ_LOCK;
3610 break;
3611 case POSIX_LOCK_TYPE_WRITE:
3612 lock_type = WRITE_LOCK;
3613 break;
3614 case POSIX_LOCK_TYPE_UNLOCK:
3615 default:
3616 /* There's no point in asking for an unlock... */
3617 talloc_destroy(data_ctx);
3618 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3621 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3622 #if defined(HAVE_LONGLONG)
3623 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3624 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3625 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3626 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3627 #else /* HAVE_LONGLONG */
3628 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3629 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3630 #endif /* HAVE_LONGLONG */
3632 status = query_lock(fsp,
3633 &lock_pid,
3634 &count,
3635 &offset,
3636 &lock_type,
3637 POSIX_LOCK);
3639 if (ERROR_WAS_LOCK_DENIED(status)) {
3640 /* Here we need to report who has it locked... */
3641 data_size = POSIX_LOCK_DATA_SIZE;
3643 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3644 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3645 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3646 #if defined(HAVE_LONGLONG)
3647 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3648 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3649 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3650 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3651 #else /* HAVE_LONGLONG */
3652 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3653 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3654 #endif /* HAVE_LONGLONG */
3656 } else if (NT_STATUS_IS_OK(status)) {
3657 /* For success we just return a copy of what we sent
3658 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3659 data_size = POSIX_LOCK_DATA_SIZE;
3660 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3661 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3662 } else {
3663 return ERROR_NT(status);
3665 break;
3668 default:
3669 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3672 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3674 return(-1);
3677 /****************************************************************************
3678 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3679 code.
3680 ****************************************************************************/
3682 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3684 SMB_STRUCT_STAT sbuf1, sbuf2;
3685 pstring last_component_oldname;
3686 pstring last_component_newname;
3687 NTSTATUS status = NT_STATUS_OK;
3689 ZERO_STRUCT(sbuf1);
3690 ZERO_STRUCT(sbuf2);
3692 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3693 if (!NT_STATUS_IS_OK(status)) {
3694 return status;
3697 /* source must already exist. */
3698 if (!VALID_STAT(sbuf1)) {
3699 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3702 status = check_name(conn, oldname);
3703 if (!NT_STATUS_IS_OK(status)) {
3704 return NT_STATUS_ACCESS_DENIED;
3707 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
3708 if (!NT_STATUS_IS_OK(status)) {
3709 return status;
3712 /* Disallow if newname already exists. */
3713 if (VALID_STAT(sbuf2)) {
3714 return NT_STATUS_OBJECT_NAME_COLLISION;
3717 status = check_name(conn, newname);
3718 if (!NT_STATUS_IS_OK(status)) {
3719 return NT_STATUS_ACCESS_DENIED;
3722 /* No links from a directory. */
3723 if (S_ISDIR(sbuf1.st_mode)) {
3724 return NT_STATUS_FILE_IS_A_DIRECTORY;
3727 /* Ensure this is within the share. */
3728 status = reduce_name(conn, oldname);
3729 if (!NT_STATUS_IS_OK(status)) {
3730 return status;
3733 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3735 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3736 status = map_nt_error_from_unix(errno);
3737 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3738 nt_errstr(status), newname, oldname));
3741 return status;
3744 /****************************************************************************
3745 Deal with SMB_INFO_SET_EA.
3746 ****************************************************************************/
3748 static int smb_info_set_ea(connection_struct *conn,
3749 char *outbuf,
3750 int bufsize,
3751 char *params,
3752 const char *pdata,
3753 int total_data,
3754 unsigned int max_data_bytes,
3755 files_struct *fsp,
3756 const char *fname)
3758 struct ea_list *ea_list = NULL;
3759 TALLOC_CTX *ctx = NULL;
3760 NTSTATUS status = NT_STATUS_OK;
3762 if (total_data < 10) {
3764 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3765 length. They seem to have no effect. Bug #3212. JRA */
3767 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3768 /* We're done. We only get EA info in this call. */
3769 SSVAL(params,0,0);
3770 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
3771 return -1;
3774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3777 if (IVAL(pdata,0) > total_data) {
3778 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
3779 IVAL(pdata,0), (unsigned int)total_data));
3780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3783 ctx = talloc_init("SMB_INFO_SET_EA");
3784 if (!ctx) {
3785 return ERROR_NT(NT_STATUS_NO_MEMORY);
3787 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3788 if (!ea_list) {
3789 talloc_destroy(ctx);
3790 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3792 status = set_ea(conn, fsp, fname, ea_list);
3793 talloc_destroy(ctx);
3795 if (!NT_STATUS_IS_OK(status)) {
3796 return ERROR_NT(status);
3799 /* We're done. We only get EA info in this call. */
3800 SSVAL(params,0,0);
3801 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
3802 return -1;
3805 /****************************************************************************
3806 Deal with SMB_SET_FILE_DISPOSITION_INFO.
3807 ****************************************************************************/
3809 static int smb_set_file_disposition_info(connection_struct *conn,
3810 char *outbuf,
3811 int bufsize,
3812 char *params,
3813 const char *pdata,
3814 int total_data,
3815 unsigned int max_data_bytes,
3816 files_struct *fsp,
3817 int dosmode)
3819 NTSTATUS status = NT_STATUS_OK;
3820 BOOL delete_on_close;
3822 if (total_data < 1) {
3823 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3826 if (fsp == NULL) {
3827 return(UNIXERROR(ERRDOS,ERRbadfid));
3830 delete_on_close = (CVAL(pdata,0) ? True : False);
3832 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
3834 if (!NT_STATUS_IS_OK(status)) {
3835 return ERROR_NT(status);
3838 /* The set is across all open files on this dev/inode pair. */
3839 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
3840 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3843 SSVAL(params,0,0);
3844 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
3845 return -1;
3848 /****************************************************************************
3849 Deal with SMB_FILE_POSITION_INFORMATION.
3850 ****************************************************************************/
3852 static int smb_file_position_information(connection_struct *conn,
3853 char *outbuf,
3854 int bufsize,
3855 char *params,
3856 const char *pdata,
3857 int total_data,
3858 unsigned int max_data_bytes,
3859 files_struct *fsp)
3861 SMB_BIG_UINT position_information;
3863 if (total_data < 8) {
3864 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3867 if (!fsp) {
3868 /* Ignore on pathname based set. */
3869 SSVAL(params,0,0);
3870 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
3871 return -1;
3874 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3875 #ifdef LARGE_SMB_OFF_T
3876 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3877 #else /* LARGE_SMB_OFF_T */
3878 if (IVAL(pdata,4) != 0) {
3879 /* more than 32 bits? */
3880 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3882 #endif /* LARGE_SMB_OFF_T */
3884 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
3885 fsp->fsp_name, (double)position_information ));
3886 fsp->fh->position_information = position_information;
3888 /* We're done. We only set position info in this call. */
3889 SSVAL(params,0,0);
3890 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
3891 return -1;
3894 /****************************************************************************
3895 Deal with SMB_FILE_MODE_INFORMATION.
3896 ****************************************************************************/
3898 static int smb_file_mode_information(connection_struct *conn,
3899 char *outbuf,
3900 int bufsize,
3901 char *params,
3902 const char *pdata,
3903 int total_data,
3904 unsigned int max_data_bytes)
3906 uint32 mode;
3908 if (total_data < 4) {
3909 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3911 mode = IVAL(pdata,0);
3912 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3913 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3916 /* We're done. We only set (?) mode info in this call. */
3917 SSVAL(params,0,0);
3918 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
3919 return -1;
3922 /****************************************************************************
3923 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3924 ****************************************************************************/
3926 static int smb_set_file_unix_link(connection_struct *conn,
3927 char *inbuf,
3928 char *outbuf,
3929 int bufsize,
3930 char *params,
3931 const char *pdata,
3932 int total_data,
3933 unsigned int max_data_bytes,
3934 const char *fname)
3936 pstring link_target;
3937 const char *newname = fname;
3938 NTSTATUS status = NT_STATUS_OK;
3940 /* Set a symbolic link. */
3941 /* Don't allow this if follow links is false. */
3943 if (total_data == 0) {
3944 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3947 if (!lp_symlinks(SNUM(conn))) {
3948 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3951 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
3953 /* !widelinks forces the target path to be within the share. */
3954 /* This means we can interpret the target as a pathname. */
3955 if (!lp_widelinks(SNUM(conn))) {
3956 pstring rel_name;
3957 char *last_dirp = NULL;
3959 unix_format(link_target);
3960 if (*link_target == '/') {
3961 /* No absolute paths allowed. */
3962 return(UNIXERROR(ERRDOS,ERRnoaccess));
3964 pstrcpy(rel_name, newname);
3965 last_dirp = strrchr_m(rel_name, '/');
3966 if (last_dirp) {
3967 last_dirp[1] = '\0';
3968 } else {
3969 pstrcpy(rel_name, "./");
3971 pstrcat(rel_name, link_target);
3973 status = check_name(conn, rel_name);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 return ERROR_NT(status);
3979 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3980 newname, link_target ));
3982 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
3983 return(UNIXERROR(ERRDOS,ERRnoaccess));
3986 SSVAL(params,0,0);
3987 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
3988 return -1;
3991 /****************************************************************************
3992 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3993 ****************************************************************************/
3995 static int smb_set_file_unix_hlink(connection_struct *conn,
3996 char *inbuf,
3997 char *outbuf,
3998 int bufsize,
3999 char *params,
4000 const char *pdata,
4001 int total_data,
4002 unsigned int max_data_bytes,
4003 pstring fname)
4005 pstring oldname;
4006 NTSTATUS status = NT_STATUS_OK;
4008 /* Set a hard link. */
4009 if (total_data == 0) {
4010 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4013 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4014 if (!NT_STATUS_IS_OK(status)) {
4015 return ERROR_NT(status);
4018 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4019 fname, oldname));
4021 status = hardlink_internals(conn, oldname, fname);
4022 if (!NT_STATUS_IS_OK(status)) {
4023 return ERROR_NT(status);
4026 SSVAL(params,0,0);
4027 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
4028 return -1;
4031 /****************************************************************************
4032 Deal with SMB_FILE_RENAME_INFORMATION.
4033 ****************************************************************************/
4035 static int smb_file_rename_information(connection_struct *conn,
4036 char *inbuf,
4037 char *outbuf,
4038 int bufsize,
4039 char *params,
4040 const char *pdata,
4041 int total_data,
4042 unsigned int max_data_bytes,
4043 files_struct *fsp,
4044 pstring fname)
4046 BOOL overwrite;
4047 /* uint32 root_fid; */ /* Not used */
4048 uint32 len;
4049 pstring newname;
4050 pstring base_name;
4051 NTSTATUS status = NT_STATUS_OK;
4052 char *p;
4054 if (total_data < 13) {
4055 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4058 overwrite = (CVAL(pdata,0) ? True : False);
4059 /* root_fid = IVAL(pdata,4); */
4060 len = IVAL(pdata,8);
4062 if (len > (total_data - 12) || (len == 0)) {
4063 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4066 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4067 if (!NT_STATUS_IS_OK(status)) {
4068 return ERROR_NT(status);
4071 /* Check the new name has no '/' characters. */
4072 if (strchr_m(newname, '/')) {
4073 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4076 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4078 /* Create the base directory. */
4079 pstrcpy(base_name, fname);
4080 p = strrchr_m(base_name, '/');
4081 if (p) {
4082 *p = '\0';
4084 /* Append the new name. */
4085 pstrcat(base_name, "/");
4086 pstrcat(base_name, newname);
4088 if (fsp) {
4089 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4090 fsp->fnum, fsp->fsp_name, base_name ));
4091 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4092 } else {
4093 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4094 fname, newname ));
4095 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4098 if (!NT_STATUS_IS_OK(status)) {
4099 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4100 /* We have re-scheduled this call. */
4101 return -1;
4103 return ERROR_NT(status);
4106 SSVAL(params,0,0);
4107 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
4108 return -1;
4111 /****************************************************************************
4112 Deal with SMB_SET_POSIX_ACL.
4113 ****************************************************************************/
4115 #if defined(HAVE_POSIX_ACLS)
4116 static int smb_set_posix_acl(connection_struct *conn,
4117 char *outbuf,
4118 int bufsize,
4119 char *params,
4120 const char *pdata,
4121 int total_data,
4122 unsigned int max_data_bytes,
4123 files_struct *fsp,
4124 const char *fname)
4126 uint16 posix_acl_version;
4127 uint16 num_file_acls;
4128 uint16 num_def_acls;
4129 BOOL valid_file_acls = True;
4130 BOOL valid_def_acls = True;
4132 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4133 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4135 posix_acl_version = SVAL(pdata,0);
4136 num_file_acls = SVAL(pdata,2);
4137 num_def_acls = SVAL(pdata,4);
4139 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4140 valid_file_acls = False;
4141 num_file_acls = 0;
4144 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4145 valid_def_acls = False;
4146 num_def_acls = 0;
4149 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4150 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4153 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4154 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4155 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4158 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4159 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4160 return(UNIXERROR(ERRDOS,ERRnoaccess));
4163 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4164 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4165 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4166 return(UNIXERROR(ERRDOS,ERRnoaccess));
4169 SSVAL(params,0,0);
4170 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
4171 return -1;
4173 #endif
4175 /****************************************************************************
4176 Deal with SMB_SET_POSIX_LOCK.
4177 ****************************************************************************/
4179 static int smb_set_posix_lock(connection_struct *conn,
4180 char *inbuf,
4181 char *outbuf,
4182 int length,
4183 int bufsize,
4184 char *params,
4185 const char *pdata,
4186 int total_data,
4187 unsigned int max_data_bytes,
4188 files_struct *fsp)
4190 SMB_BIG_UINT count;
4191 SMB_BIG_UINT offset;
4192 uint32 lock_pid;
4193 BOOL blocking_lock = False;
4194 enum brl_type lock_type;
4195 NTSTATUS status = NT_STATUS_OK;
4197 if (fsp == NULL || fsp->fh->fd == -1) {
4198 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4201 if (total_data != POSIX_LOCK_DATA_SIZE) {
4202 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4205 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4206 case POSIX_LOCK_TYPE_READ:
4207 lock_type = READ_LOCK;
4208 break;
4209 case POSIX_LOCK_TYPE_WRITE:
4210 /* Return the right POSIX-mappable error code for files opened read-only. */
4211 if (!fsp->can_write) {
4212 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4214 lock_type = WRITE_LOCK;
4215 break;
4216 case POSIX_LOCK_TYPE_UNLOCK:
4217 lock_type = UNLOCK_LOCK;
4218 break;
4219 default:
4220 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4223 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4224 blocking_lock = False;
4225 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4226 blocking_lock = True;
4227 } else {
4228 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4231 if (!lp_blocking_locks(SNUM(conn))) {
4232 blocking_lock = False;
4235 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4236 #if defined(HAVE_LONGLONG)
4237 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4238 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4239 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4240 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4241 #else /* HAVE_LONGLONG */
4242 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4243 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4244 #endif /* HAVE_LONGLONG */
4246 if (lock_type == UNLOCK_LOCK) {
4247 status = do_unlock(fsp,
4248 lock_pid,
4249 count,
4250 offset,
4251 POSIX_LOCK);
4252 } else {
4253 struct byte_range_lock *br_lck = do_lock(fsp,
4254 lock_pid,
4255 count,
4256 offset,
4257 lock_type,
4258 POSIX_LOCK,
4259 blocking_lock,
4260 &status);
4262 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4264 * A blocking lock was requested. Package up
4265 * this smb into a queued request and push it
4266 * onto the blocking lock queue.
4268 if(push_blocking_lock_request(br_lck,
4269 inbuf, length,
4270 fsp,
4271 -1, /* infinite timeout. */
4273 lock_pid,
4274 lock_type,
4275 POSIX_LOCK,
4276 offset,
4277 count)) {
4278 TALLOC_FREE(br_lck);
4279 return -1;
4282 TALLOC_FREE(br_lck);
4285 if (!NT_STATUS_IS_OK(status)) {
4286 return ERROR_NT(status);
4289 SSVAL(params,0,0);
4290 send_trans2_replies(outbuf, bufsize, params, 2, pdata, 0, max_data_bytes);
4291 return -1;
4294 /****************************************************************************
4295 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
4296 ****************************************************************************/
4298 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4299 unsigned int tran_call,
4300 char **pparams, int total_params, char **ppdata, int total_data,
4301 unsigned int max_data_bytes)
4303 char *params = *pparams;
4304 char *pdata = *ppdata;
4305 uint16 info_level;
4306 int dosmode=0;
4307 SMB_OFF_T size=0;
4308 struct utimbuf tvs;
4309 SMB_STRUCT_STAT sbuf;
4310 pstring fname;
4311 int fd = -1;
4312 files_struct *fsp = NULL;
4313 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4314 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4315 mode_t unixmode = 0;
4316 NTSTATUS status = NT_STATUS_OK;
4318 if (!params)
4319 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4321 ZERO_STRUCT(sbuf);
4322 ZERO_STRUCT(tvs);
4324 if (tran_call == TRANSACT2_SETFILEINFO) {
4325 if (total_params < 4) {
4326 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4329 fsp = file_fsp(params,0);
4330 info_level = SVAL(params,2);
4332 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
4334 * This is actually a SETFILEINFO on a directory
4335 * handle (returned from an NT SMB). NT5.0 seems
4336 * to do this call. JRA.
4338 pstrcpy(fname, fsp->fsp_name);
4339 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
4340 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
4341 return UNIXERROR(ERRDOS,ERRbadpath);
4343 } else if (fsp && fsp->print_file) {
4345 * Doing a DELETE_ON_CLOSE should cancel a print job.
4347 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
4348 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
4350 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
4352 SSVAL(params,0,0);
4353 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4354 return(-1);
4355 } else
4356 return (UNIXERROR(ERRDOS,ERRbadpath));
4357 } else {
4359 * Original code - this is an open file.
4361 CHECK_FSP(fsp,conn);
4363 pstrcpy(fname, fsp->fsp_name);
4364 fd = fsp->fh->fd;
4366 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
4367 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
4368 return(UNIXERROR(ERRDOS,ERRbadfid));
4371 } else {
4372 /* set path info */
4373 if (total_params < 7) {
4374 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4377 info_level = SVAL(params,0);
4378 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
4379 if (!NT_STATUS_IS_OK(status)) {
4380 return ERROR_NT(status);
4382 status = unix_convert(conn, fname, False, NULL, &sbuf);
4383 if (!NT_STATUS_IS_OK(status)) {
4384 return ERROR_NT(status);
4388 * For CIFS UNIX extensions the target name may not exist.
4391 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
4392 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
4393 return UNIXERROR(ERRDOS,ERRbadpath);
4396 status = check_name(conn, fname);
4397 if (!NT_STATUS_IS_OK(status)) {
4398 return ERROR_NT(status);
4403 if (!CAN_WRITE(conn))
4404 return ERROR_DOS(ERRSRV,ERRaccess);
4406 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4407 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4410 if (VALID_STAT(sbuf))
4411 unixmode = sbuf.st_mode;
4413 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
4414 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
4416 /* Realloc the parameter size */
4417 *pparams = (char *)SMB_REALLOC(*pparams,2);
4418 if (*pparams == NULL) {
4419 return ERROR_NT(NT_STATUS_NO_MEMORY);
4421 params = *pparams;
4423 SSVAL(params,0,0);
4425 if (fsp && fsp->pending_modtime) {
4426 /* the pending modtime overrides the current modtime */
4427 sbuf.st_mtime = fsp->pending_modtime;
4430 size = get_file_size(sbuf);
4431 tvs.modtime = sbuf.st_mtime;
4432 tvs.actime = sbuf.st_atime;
4433 dosmode = dos_mode(conn,fname,&sbuf);
4434 unixmode = sbuf.st_mode;
4436 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
4437 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
4439 switch (info_level) {
4440 case SMB_INFO_STANDARD:
4442 if (total_data < 12) {
4443 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4446 /* access time */
4447 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
4448 /* write time */
4449 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
4450 break;
4453 case SMB_INFO_SET_EA:
4454 return smb_info_set_ea(conn,
4455 outbuf,
4456 bufsize,
4457 params,
4458 *ppdata,
4459 total_data,
4460 max_data_bytes,
4461 fsp,
4462 fname);
4464 case SMB_SET_FILE_BASIC_INFO:
4465 case SMB_FILE_BASIC_INFORMATION:
4467 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4468 time_t write_time;
4469 time_t changed_time;
4471 if (total_data < 36) {
4472 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4475 /* Ignore create time at offset pdata. */
4477 /* access time */
4478 tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
4480 write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
4481 changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
4483 tvs.modtime = MIN(write_time, changed_time);
4485 if (write_time > tvs.modtime && write_time != (time_t)-1) {
4486 tvs.modtime = write_time;
4488 /* Prefer a defined time to an undefined one. */
4489 if (null_mtime(tvs.modtime)) {
4490 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
4493 /* attributes */
4494 dosmode = IVAL(pdata,32);
4495 break;
4498 case SMB_FILE_ALLOCATION_INFORMATION:
4499 case SMB_SET_FILE_ALLOCATION_INFO:
4501 int ret = -1;
4502 SMB_BIG_UINT allocation_size;
4504 if (total_data < 8) {
4505 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4508 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4509 #ifdef LARGE_SMB_OFF_T
4510 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4511 #else /* LARGE_SMB_OFF_T */
4512 if (IVAL(pdata,4) != 0) {
4513 /* more than 32 bits? */
4514 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4516 #endif /* LARGE_SMB_OFF_T */
4517 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4518 fname, (double)allocation_size ));
4520 if (allocation_size) {
4521 allocation_size = smb_roundup(conn, allocation_size);
4524 if(allocation_size != get_file_size(sbuf)) {
4525 SMB_STRUCT_STAT new_sbuf;
4527 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4528 fname, (double)allocation_size ));
4530 if (fd == -1) {
4531 files_struct *new_fsp = NULL;
4533 status = open_file_ntcreate(conn, fname, &sbuf,
4534 FILE_WRITE_DATA,
4535 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4536 FILE_OPEN,
4538 FILE_ATTRIBUTE_NORMAL,
4539 FORCE_OPLOCK_BREAK_TO_NONE,
4540 NULL, &new_fsp);
4542 if (!NT_STATUS_IS_OK(status)) {
4543 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4544 /* We have re-scheduled this call. */
4545 return -1;
4547 return(UNIXERROR(ERRDOS,ERRnoaccess));
4549 ret = vfs_allocate_file_space(new_fsp, allocation_size);
4550 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4551 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4552 new_fsp->fnum, strerror(errno)));
4553 ret = -1;
4555 close_file(new_fsp,NORMAL_CLOSE);
4556 } else {
4557 ret = vfs_allocate_file_space(fsp, allocation_size);
4558 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4559 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4560 fsp->fnum, strerror(errno)));
4561 ret = -1;
4564 if (ret == -1)
4565 return ERROR_NT(NT_STATUS_DISK_FULL);
4567 /* Allocate can truncate size... */
4568 size = get_file_size(new_sbuf);
4571 break;
4574 case SMB_FILE_END_OF_FILE_INFORMATION:
4575 case SMB_SET_FILE_END_OF_FILE_INFO:
4577 if (total_data < 8) {
4578 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4581 size = IVAL(pdata,0);
4582 #ifdef LARGE_SMB_OFF_T
4583 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4584 #else /* LARGE_SMB_OFF_T */
4585 if (IVAL(pdata,4) != 0) {
4586 /* more than 32 bits? */
4587 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4589 #endif /* LARGE_SMB_OFF_T */
4590 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4591 break;
4594 case SMB_FILE_DISPOSITION_INFORMATION:
4595 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4597 #if 0
4598 /* JRA - We used to just ignore this on a path ?
4599 * Shouldn't this be invalid level on a pathname
4600 * based call ?
4602 if (tran_call != TRANSACT2_SETFILEINFO) {
4603 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4605 #endif
4606 return smb_set_file_disposition_info(conn,
4607 outbuf,
4608 bufsize,
4609 params,
4610 *ppdata,
4611 total_data,
4612 max_data_bytes,
4613 fsp,
4614 dosmode);
4617 case SMB_FILE_POSITION_INFORMATION:
4619 return smb_file_position_information(conn,
4620 outbuf,
4621 bufsize,
4622 params,
4623 *ppdata,
4624 total_data,
4625 max_data_bytes,
4626 fsp);
4629 /* From tridge Samba4 :
4630 * MODE_INFORMATION in setfileinfo (I have no
4631 * idea what "mode information" on a file is - it takes a value of 0,
4632 * 2, 4 or 6. What could it be?).
4635 case SMB_FILE_MODE_INFORMATION:
4637 return smb_file_mode_information(conn,
4638 outbuf,
4639 bufsize,
4640 params,
4641 *ppdata,
4642 total_data,
4643 max_data_bytes);
4647 * CIFS UNIX extensions.
4650 case SMB_SET_FILE_UNIX_BASIC:
4652 uint32 raw_unixmode;
4653 BOOL delete_on_fail = False;
4655 if (total_data < 100) {
4656 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4659 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4660 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4661 size=IVAL(pdata,0); /* first 8 Bytes are size */
4662 #ifdef LARGE_SMB_OFF_T
4663 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4664 #else /* LARGE_SMB_OFF_T */
4665 if (IVAL(pdata,4) != 0) {
4666 /* more than 32 bits? */
4667 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4669 #endif /* LARGE_SMB_OFF_T */
4671 pdata+=24; /* ctime & st_blocks are not changed */
4672 tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */
4673 tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */
4674 pdata+=16;
4675 set_owner = (uid_t)IVAL(pdata,0);
4676 pdata += 8;
4677 set_grp = (gid_t)IVAL(pdata,0);
4678 pdata += 8;
4679 raw_unixmode = IVAL(pdata,28);
4680 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4681 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4683 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4684 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4685 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4687 if (!VALID_STAT(sbuf)) {
4690 * The only valid use of this is to create character and block
4691 * devices, and named pipes. This is deprecated (IMHO) and
4692 * a new info level should be used for mknod. JRA.
4695 uint32 file_type = IVAL(pdata,0);
4696 #if defined(HAVE_MAKEDEV)
4697 uint32 dev_major = IVAL(pdata,4);
4698 uint32 dev_minor = IVAL(pdata,12);
4699 #endif
4701 SMB_DEV_T dev = (SMB_DEV_T)0;
4703 if (tran_call == TRANSACT2_SETFILEINFO)
4704 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4706 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4707 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4710 #if defined(HAVE_MAKEDEV)
4711 dev = makedev(dev_major, dev_minor);
4712 #endif
4714 switch (file_type) {
4715 #if defined(S_IFIFO)
4716 case UNIX_TYPE_FIFO:
4717 unixmode |= S_IFIFO;
4718 break;
4719 #endif
4720 #if defined(S_IFSOCK)
4721 case UNIX_TYPE_SOCKET:
4722 unixmode |= S_IFSOCK;
4723 break;
4724 #endif
4725 #if defined(S_IFCHR)
4726 case UNIX_TYPE_CHARDEV:
4727 unixmode |= S_IFCHR;
4728 break;
4729 #endif
4730 #if defined(S_IFBLK)
4731 case UNIX_TYPE_BLKDEV:
4732 unixmode |= S_IFBLK;
4733 break;
4734 #endif
4735 default:
4736 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4739 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4740 0%o for file %s\n", (double)dev, unixmode, fname ));
4742 /* Ok - do the mknod. */
4743 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0) {
4744 return(UNIXERROR(ERRDOS,ERRnoaccess));
4747 /* If any of the other "set" calls fail we
4748 * don't want to end up with a half-constructed mknod.
4751 delete_on_fail = True;
4753 if (lp_inherit_perms(SNUM(conn))) {
4754 inherit_access_acl(
4755 conn, parent_dirname(fname),
4756 fname, unixmode);
4759 if (SMB_VFS_STAT(conn, fname, &sbuf) != 0) {
4760 int saved_errno = errno;
4761 SMB_VFS_UNLINK(conn,fname);
4762 errno = saved_errno;
4763 return(UNIXERROR(ERRDOS,ERRnoaccess));
4766 /* Ensure we don't try and change anything else. */
4767 raw_unixmode = SMB_MODE_NO_CHANGE;
4768 size = get_file_size(sbuf);
4769 tvs.modtime = sbuf.st_mtime;
4770 tvs.actime = sbuf.st_atime;
4774 * Deal with the UNIX specific mode set.
4777 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4778 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4779 (unsigned int)unixmode, fname ));
4780 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4781 return(UNIXERROR(ERRDOS,ERRnoaccess));
4785 * Deal with the UNIX specific uid set.
4788 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4789 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4790 (unsigned int)set_owner, fname ));
4791 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0) {
4792 if (delete_on_fail) {
4793 int saved_errno = errno;
4794 SMB_VFS_UNLINK(conn,fname);
4795 errno = saved_errno;
4797 return(UNIXERROR(ERRDOS,ERRnoaccess));
4802 * Deal with the UNIX specific gid set.
4805 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4806 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4807 (unsigned int)set_owner, fname ));
4808 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0) {
4809 if (delete_on_fail) {
4810 int saved_errno = errno;
4811 SMB_VFS_UNLINK(conn,fname);
4812 errno = saved_errno;
4814 return(UNIXERROR(ERRDOS,ERRnoaccess));
4817 break;
4820 case SMB_SET_FILE_UNIX_LINK:
4822 if (tran_call != TRANSACT2_SETPATHINFO) {
4823 /* We must have a pathname for this. */
4824 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4826 return smb_set_file_unix_link(conn,
4827 inbuf,
4828 outbuf,
4829 bufsize,
4830 params,
4831 *ppdata,
4832 total_data,
4833 max_data_bytes,
4834 fname);
4837 case SMB_SET_FILE_UNIX_HLINK:
4839 if (tran_call != TRANSACT2_SETPATHINFO) {
4840 /* We must have a pathname for this. */
4841 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4843 return smb_set_file_unix_hlink(conn,
4844 inbuf,
4845 outbuf,
4846 bufsize,
4847 params,
4848 *ppdata,
4849 total_data,
4850 max_data_bytes,
4851 fname);
4854 case SMB_FILE_RENAME_INFORMATION:
4856 return smb_file_rename_information(conn,
4857 inbuf,
4858 outbuf,
4859 bufsize,
4860 params,
4861 pdata,
4862 total_data,
4863 max_data_bytes,
4864 fsp,
4865 fname);
4868 #if defined(HAVE_POSIX_ACLS)
4869 case SMB_SET_POSIX_ACL:
4871 return smb_set_posix_acl(conn,
4872 outbuf,
4873 bufsize,
4874 params,
4875 pdata,
4876 total_data,
4877 max_data_bytes,
4878 fsp,
4879 fname);
4881 #endif
4883 case SMB_SET_POSIX_LOCK:
4885 return smb_set_posix_lock(conn,
4886 inbuf,
4887 outbuf,
4888 length,
4889 bufsize,
4890 params,
4891 pdata,
4892 total_data,
4893 max_data_bytes,
4894 fsp);
4897 default:
4898 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4901 /* get some defaults (no modifications) if any info is zero or -1. */
4902 if (null_mtime(tvs.actime)) {
4903 tvs.actime = sbuf.st_atime;
4906 if (null_mtime(tvs.modtime)) {
4907 tvs.modtime = sbuf.st_mtime;
4910 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4911 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4912 DEBUG(6,("size: %.0f ", (double)size));
4914 if (dosmode) {
4915 if (S_ISDIR(sbuf.st_mode))
4916 dosmode |= aDIR;
4917 else
4918 dosmode &= ~aDIR;
4921 DEBUG(6,("dosmode: %x\n" , dosmode));
4923 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4924 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4925 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4926 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4929 * Only do this test if we are not explicitly
4930 * changing the size of a file.
4932 if (!size)
4933 size = get_file_size(sbuf);
4937 * Try and set the times, size and mode of this file -
4938 * if they are different from the current values
4941 /* check the mode isn't different, before changing it */
4942 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4944 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4946 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4947 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4948 return(UNIXERROR(ERRDOS,ERRnoaccess));
4952 /* Now the size. */
4953 if (size != get_file_size(sbuf)) {
4955 int ret;
4957 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4958 fname, (double)size ));
4960 if (fd == -1) {
4961 files_struct *new_fsp = NULL;
4963 status = open_file_ntcreate(conn, fname, &sbuf,
4964 FILE_WRITE_DATA,
4965 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4966 FILE_OPEN,
4968 FILE_ATTRIBUTE_NORMAL,
4969 FORCE_OPLOCK_BREAK_TO_NONE,
4970 NULL, &new_fsp);
4972 if (!NT_STATUS_IS_OK(status)) {
4973 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4974 /* We have re-scheduled this call. */
4975 return -1;
4977 return(UNIXERROR(ERRDOS,ERRnoaccess));
4979 ret = vfs_set_filelen(new_fsp, size);
4980 close_file(new_fsp,NORMAL_CLOSE);
4981 } else {
4982 ret = vfs_set_filelen(fsp, size);
4985 if (ret == -1) {
4986 return (UNIXERROR(ERRHRD,ERRdiskfull));
4991 * Finally the times.
4993 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4994 if(fsp != NULL) {
4996 * This was a setfileinfo on an open file.
4997 * NT does this a lot. We also need to
4998 * set the time here, as it can be read by
4999 * FindFirst/FindNext and with the patch for bug #2045
5000 * in smbd/fileio.c it ensures that this timestamp is
5001 * kept sticky even after a write. We save the request
5002 * away and will set it on file close and after a write. JRA.
5005 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
5006 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
5007 fsp_set_pending_modtime(fsp, tvs.modtime);
5011 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
5013 if(file_utime(conn, fname, &tvs)!=0) {
5014 return(UNIXERROR(ERRDOS,ERRnoaccess));
5018 SSVAL(params,0,0);
5019 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5021 return(-1);
5024 /****************************************************************************
5025 Reply to a TRANS2_MKDIR (make directory with extended attributes).
5026 ****************************************************************************/
5028 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5029 char **pparams, int total_params, char **ppdata, int total_data,
5030 unsigned int max_data_bytes)
5032 char *params = *pparams;
5033 char *pdata = *ppdata;
5034 pstring directory;
5035 SMB_STRUCT_STAT sbuf;
5036 NTSTATUS status = NT_STATUS_OK;
5037 struct ea_list *ea_list = NULL;
5039 if (!CAN_WRITE(conn))
5040 return ERROR_DOS(ERRSRV,ERRaccess);
5042 if (total_params < 5) {
5043 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5046 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
5047 if (!NT_STATUS_IS_OK(status)) {
5048 return ERROR_NT(status);
5051 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
5053 status = unix_convert(conn, directory, False, NULL, &sbuf);
5054 if (!NT_STATUS_IS_OK(status)) {
5055 return ERROR_NT(status);
5058 /* Any data in this call is an EA list. */
5059 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5060 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5064 * OS/2 workplace shell seems to send SET_EA requests of "null"
5065 * length (4 bytes containing IVAL 4).
5066 * They seem to have no effect. Bug #3212. JRA.
5069 if (total_data != 4) {
5070 if (total_data < 10) {
5071 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5074 if (IVAL(pdata,0) > total_data) {
5075 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
5076 IVAL(pdata,0), (unsigned int)total_data));
5077 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5080 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
5081 total_data - 4);
5082 if (!ea_list) {
5083 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5085 } else if (IVAL(pdata,0) != 4) {
5086 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5089 status = check_name(conn, directory);
5090 if (!NT_STATUS_IS_OK(status)) {
5091 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5092 return ERROR_NT(status);
5095 status = create_directory(conn, directory);
5097 if (!NT_STATUS_IS_OK(status)) {
5098 return ERROR_NT(status);
5101 /* Try and set any given EA. */
5102 if (ea_list) {
5103 status = set_ea(conn, NULL, directory, ea_list);
5104 if (!NT_STATUS_IS_OK(status)) {
5105 return ERROR_NT(status);
5109 /* Realloc the parameter and data sizes */
5110 *pparams = (char *)SMB_REALLOC(*pparams,2);
5111 if(*pparams == NULL) {
5112 return ERROR_NT(NT_STATUS_NO_MEMORY);
5114 params = *pparams;
5116 SSVAL(params,0,0);
5118 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5120 return(-1);
5123 /****************************************************************************
5124 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5125 We don't actually do this - we just send a null response.
5126 ****************************************************************************/
5128 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5129 char **pparams, int total_params, char **ppdata, int total_data,
5130 unsigned int max_data_bytes)
5132 static uint16 fnf_handle = 257;
5133 char *params = *pparams;
5134 uint16 info_level;
5136 if (total_params < 6) {
5137 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5140 info_level = SVAL(params,4);
5141 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5143 switch (info_level) {
5144 case 1:
5145 case 2:
5146 break;
5147 default:
5148 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5151 /* Realloc the parameter and data sizes */
5152 *pparams = (char *)SMB_REALLOC(*pparams,6);
5153 if (*pparams == NULL) {
5154 return ERROR_NT(NT_STATUS_NO_MEMORY);
5156 params = *pparams;
5158 SSVAL(params,0,fnf_handle);
5159 SSVAL(params,2,0); /* No changes */
5160 SSVAL(params,4,0); /* No EA errors */
5162 fnf_handle++;
5164 if(fnf_handle == 0)
5165 fnf_handle = 257;
5167 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
5169 return(-1);
5172 /****************************************************************************
5173 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
5174 changes). Currently this does nothing.
5175 ****************************************************************************/
5177 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5178 char **pparams, int total_params, char **ppdata, int total_data,
5179 unsigned int max_data_bytes)
5181 char *params = *pparams;
5183 DEBUG(3,("call_trans2findnotifynext\n"));
5185 /* Realloc the parameter and data sizes */
5186 *pparams = (char *)SMB_REALLOC(*pparams,4);
5187 if (*pparams == NULL) {
5188 return ERROR_NT(NT_STATUS_NO_MEMORY);
5190 params = *pparams;
5192 SSVAL(params,0,0); /* No changes */
5193 SSVAL(params,2,0); /* No EA errors */
5195 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
5197 return(-1);
5200 /****************************************************************************
5201 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5202 ****************************************************************************/
5204 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5205 char **pparams, int total_params, char **ppdata, int total_data,
5206 unsigned int max_data_bytes)
5208 char *params = *pparams;
5209 pstring pathname;
5210 int reply_size = 0;
5211 int max_referral_level;
5213 DEBUG(10,("call_trans2getdfsreferral\n"));
5215 if (total_params < 3) {
5216 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5219 max_referral_level = SVAL(params,0);
5221 if(!lp_host_msdfs())
5222 return ERROR_DOS(ERRDOS,ERRbadfunc);
5224 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
5225 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
5226 return UNIXERROR(ERRDOS,ERRbadfile);
5228 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5229 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
5231 return(-1);
5234 #define LMCAT_SPL 0x53
5235 #define LMFUNC_GETJOBID 0x60
5237 /****************************************************************************
5238 Reply to a TRANS2_IOCTL - used for OS/2 printing.
5239 ****************************************************************************/
5241 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5242 char **pparams, int total_params, char **ppdata, int total_data,
5243 unsigned int max_data_bytes)
5245 char *pdata = *ppdata;
5246 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
5248 /* check for an invalid fid before proceeding */
5250 if (!fsp)
5251 return(ERROR_DOS(ERRDOS,ERRbadfid));
5253 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5254 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5255 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5256 if (*ppdata == NULL) {
5257 return ERROR_NT(NT_STATUS_NO_MEMORY);
5259 pdata = *ppdata;
5261 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5262 CAN ACCEPT THIS IN UNICODE. JRA. */
5264 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
5265 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5266 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5267 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5268 return(-1);
5269 } else {
5270 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5271 return ERROR_DOS(ERRSRV,ERRerror);
5275 /****************************************************************************
5276 Reply to a SMBfindclose (stop trans2 directory search).
5277 ****************************************************************************/
5279 int reply_findclose(connection_struct *conn,
5280 char *inbuf,char *outbuf,int length,int bufsize)
5282 int outsize = 0;
5283 int dptr_num=SVALS(inbuf,smb_vwv0);
5284 START_PROFILE(SMBfindclose);
5286 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5288 dptr_close(&dptr_num);
5290 outsize = set_message(outbuf,0,0,False);
5292 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5294 END_PROFILE(SMBfindclose);
5295 return(outsize);
5298 /****************************************************************************
5299 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5300 ****************************************************************************/
5302 int reply_findnclose(connection_struct *conn,
5303 char *inbuf,char *outbuf,int length,int bufsize)
5305 int outsize = 0;
5306 int dptr_num= -1;
5307 START_PROFILE(SMBfindnclose);
5309 dptr_num = SVAL(inbuf,smb_vwv0);
5311 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5313 /* We never give out valid handles for a
5314 findnotifyfirst - so any dptr_num is ok here.
5315 Just ignore it. */
5317 outsize = set_message(outbuf,0,0,False);
5319 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5321 END_PROFILE(SMBfindnclose);
5322 return(outsize);
5325 int handle_trans2(connection_struct *conn,
5326 struct trans_state *state,
5327 char *inbuf, char *outbuf, int size, int bufsize)
5329 int outsize;
5331 if (Protocol >= PROTOCOL_NT1) {
5332 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5335 /* Now we must call the relevant TRANS2 function */
5336 switch(state->call) {
5337 case TRANSACT2_OPEN:
5339 START_PROFILE(Trans2_open);
5340 outsize = call_trans2open(
5341 conn, inbuf, outbuf, bufsize,
5342 &state->param, state->total_param,
5343 &state->data, state->total_data,
5344 state->max_data_return);
5345 END_PROFILE(Trans2_open);
5346 break;
5349 case TRANSACT2_FINDFIRST:
5351 START_PROFILE(Trans2_findfirst);
5352 outsize = call_trans2findfirst(
5353 conn, inbuf, outbuf, bufsize,
5354 &state->param, state->total_param,
5355 &state->data, state->total_data,
5356 state->max_data_return);
5357 END_PROFILE(Trans2_findfirst);
5358 break;
5361 case TRANSACT2_FINDNEXT:
5363 START_PROFILE(Trans2_findnext);
5364 outsize = call_trans2findnext(
5365 conn, inbuf, outbuf, size, bufsize,
5366 &state->param, state->total_param,
5367 &state->data, state->total_data,
5368 state->max_data_return);
5369 END_PROFILE(Trans2_findnext);
5370 break;
5373 case TRANSACT2_QFSINFO:
5375 START_PROFILE(Trans2_qfsinfo);
5376 outsize = call_trans2qfsinfo(
5377 conn, inbuf, outbuf, size, bufsize,
5378 &state->param, state->total_param,
5379 &state->data, state->total_data,
5380 state->max_data_return);
5381 END_PROFILE(Trans2_qfsinfo);
5382 break;
5385 case TRANSACT2_SETFSINFO:
5387 START_PROFILE(Trans2_setfsinfo);
5388 outsize = call_trans2setfsinfo(
5389 conn, inbuf, outbuf, size, bufsize,
5390 &state->param, state->total_param,
5391 &state->data, state->total_data,
5392 state->max_data_return);
5393 END_PROFILE(Trans2_setfsinfo);
5394 break;
5397 case TRANSACT2_QPATHINFO:
5398 case TRANSACT2_QFILEINFO:
5400 START_PROFILE(Trans2_qpathinfo);
5401 outsize = call_trans2qfilepathinfo(
5402 conn, inbuf, outbuf, size, bufsize, state->call,
5403 &state->param, state->total_param,
5404 &state->data, state->total_data,
5405 state->max_data_return);
5406 END_PROFILE(Trans2_qpathinfo);
5407 break;
5410 case TRANSACT2_SETPATHINFO:
5411 case TRANSACT2_SETFILEINFO:
5413 START_PROFILE(Trans2_setpathinfo);
5414 outsize = call_trans2setfilepathinfo(
5415 conn, inbuf, outbuf, size, bufsize, state->call,
5416 &state->param, state->total_param,
5417 &state->data, state->total_data,
5418 state->max_data_return);
5419 END_PROFILE(Trans2_setpathinfo);
5420 break;
5423 case TRANSACT2_FINDNOTIFYFIRST:
5425 START_PROFILE(Trans2_findnotifyfirst);
5426 outsize = call_trans2findnotifyfirst(
5427 conn, inbuf, outbuf, size, bufsize,
5428 &state->param, state->total_param,
5429 &state->data, state->total_data,
5430 state->max_data_return);
5431 END_PROFILE(Trans2_findnotifyfirst);
5432 break;
5435 case TRANSACT2_FINDNOTIFYNEXT:
5437 START_PROFILE(Trans2_findnotifynext);
5438 outsize = call_trans2findnotifynext(
5439 conn, inbuf, outbuf, size, bufsize,
5440 &state->param, state->total_param,
5441 &state->data, state->total_data,
5442 state->max_data_return);
5443 END_PROFILE(Trans2_findnotifynext);
5444 break;
5447 case TRANSACT2_MKDIR:
5449 START_PROFILE(Trans2_mkdir);
5450 outsize = call_trans2mkdir(
5451 conn, inbuf, outbuf, size, bufsize,
5452 &state->param, state->total_param,
5453 &state->data, state->total_data,
5454 state->max_data_return);
5455 END_PROFILE(Trans2_mkdir);
5456 break;
5459 case TRANSACT2_GET_DFS_REFERRAL:
5461 START_PROFILE(Trans2_get_dfs_referral);
5462 outsize = call_trans2getdfsreferral(
5463 conn, inbuf, outbuf, size, bufsize,
5464 &state->param, state->total_param,
5465 &state->data, state->total_data,
5466 state->max_data_return);
5467 END_PROFILE(Trans2_get_dfs_referral);
5468 break;
5471 case TRANSACT2_IOCTL:
5473 START_PROFILE(Trans2_ioctl);
5474 outsize = call_trans2ioctl(
5475 conn, inbuf, outbuf, size, bufsize,
5476 &state->param, state->total_param,
5477 &state->data, state->total_data,
5478 state->max_data_return);
5479 END_PROFILE(Trans2_ioctl);
5480 break;
5483 default:
5484 /* Error in request */
5485 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5486 outsize = ERROR_DOS(ERRSRV,ERRerror);
5489 return outsize;
5492 /****************************************************************************
5493 Reply to a SMBtrans2.
5494 ****************************************************************************/
5496 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5497 int size, int bufsize)
5499 int outsize = 0;
5500 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5501 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5502 unsigned int psoff = SVAL(inbuf, smb_psoff);
5503 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5504 unsigned int tran_call = SVAL(inbuf, smb_setup0);
5505 struct trans_state *state;
5506 NTSTATUS result;
5508 START_PROFILE(SMBtrans2);
5510 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5511 if (!NT_STATUS_IS_OK(result)) {
5512 DEBUG(2, ("Got invalid trans2 request: %s\n",
5513 nt_errstr(result)));
5514 END_PROFILE(SMBtrans2);
5515 return ERROR_NT(result);
5518 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5519 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5520 END_PROFILE(SMBtrans2);
5521 return ERROR_DOS(ERRSRV,ERRaccess);
5524 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
5525 DEBUG(0, ("talloc failed\n"));
5526 END_PROFILE(SMBtrans2);
5527 return ERROR_NT(NT_STATUS_NO_MEMORY);
5530 state->cmd = SMBtrans2;
5532 state->mid = SVAL(inbuf, smb_mid);
5533 state->vuid = SVAL(inbuf, smb_uid);
5534 state->setup_count = SVAL(inbuf, smb_suwcnt);
5535 state->setup = NULL;
5536 state->total_param = SVAL(inbuf, smb_tpscnt);
5537 state->param = NULL;
5538 state->total_data = SVAL(inbuf, smb_tdscnt);
5539 state->data = NULL;
5540 state->max_param_return = SVAL(inbuf, smb_mprcnt);
5541 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
5542 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5543 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5544 state->one_way = BITSETW(inbuf+smb_vwv5,1);
5546 state->call = tran_call;
5548 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5549 is so as a sanity check */
5550 if (state->setup_count != 1) {
5552 * Need to have rc=0 for ioctl to get job id for OS/2.
5553 * Network printing will fail if function is not successful.
5554 * Similar function in reply.c will be used if protocol
5555 * is LANMAN1.0 instead of LM1.2X002.
5556 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5557 * outbuf doesn't have to be set(only job id is used).
5559 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5560 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5561 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5562 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5563 } else {
5564 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5565 DEBUG(2,("Transaction is %d\n",tran_call));
5566 TALLOC_FREE(state);
5567 END_PROFILE(SMBtrans2);
5568 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5572 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5573 goto bad_param;
5575 if (state->total_data) {
5576 /* Can't use talloc here, the core routines do realloc on the
5577 * params and data. */
5578 state->data = (char *)SMB_MALLOC(state->total_data);
5579 if (state->data == NULL) {
5580 DEBUG(0,("reply_trans2: data malloc fail for %u "
5581 "bytes !\n", (unsigned int)state->total_data));
5582 TALLOC_FREE(state);
5583 END_PROFILE(SMBtrans2);
5584 return(ERROR_DOS(ERRDOS,ERRnomem));
5586 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5587 goto bad_param;
5588 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5589 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5590 goto bad_param;
5592 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5595 if (state->total_param) {
5596 /* Can't use talloc here, the core routines do realloc on the
5597 * params and data. */
5598 state->param = (char *)SMB_MALLOC(state->total_param);
5599 if (state->param == NULL) {
5600 DEBUG(0,("reply_trans: param malloc fail for %u "
5601 "bytes !\n", (unsigned int)state->total_param));
5602 SAFE_FREE(state->data);
5603 TALLOC_FREE(state);
5604 END_PROFILE(SMBtrans2);
5605 return(ERROR_DOS(ERRDOS,ERRnomem));
5607 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5608 goto bad_param;
5609 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5610 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5611 goto bad_param;
5613 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5616 state->received_data = dscnt;
5617 state->received_param = pscnt;
5619 if ((state->received_param == state->total_param) &&
5620 (state->received_data == state->total_data)) {
5622 outsize = handle_trans2(conn, state, inbuf, outbuf,
5623 size, bufsize);
5624 SAFE_FREE(state->data);
5625 SAFE_FREE(state->param);
5626 TALLOC_FREE(state);
5627 END_PROFILE(SMBtrans2);
5628 return outsize;
5631 DLIST_ADD(conn->pending_trans, state);
5633 /* We need to send an interim response then receive the rest
5634 of the parameter/data bytes */
5635 outsize = set_message(outbuf,0,0,False);
5636 show_msg(outbuf);
5637 END_PROFILE(SMBtrans2);
5638 return outsize;
5640 bad_param:
5642 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5643 SAFE_FREE(state->data);
5644 SAFE_FREE(state->param);
5645 TALLOC_FREE(state);
5646 END_PROFILE(SMBtrans2);
5647 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5651 /****************************************************************************
5652 Reply to a SMBtranss2
5653 ****************************************************************************/
5655 int reply_transs2(connection_struct *conn,
5656 char *inbuf,char *outbuf,int size,int bufsize)
5658 int outsize = 0;
5659 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5660 struct trans_state *state;
5662 START_PROFILE(SMBtranss2);
5664 show_msg(inbuf);
5666 for (state = conn->pending_trans; state != NULL;
5667 state = state->next) {
5668 if (state->mid == SVAL(inbuf,smb_mid)) {
5669 break;
5673 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5674 END_PROFILE(SMBtranss2);
5675 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5678 /* Revise state->total_param and state->total_data in case they have
5679 changed downwards */
5681 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5682 state->total_param = SVAL(inbuf, smb_tpscnt);
5683 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5684 state->total_data = SVAL(inbuf, smb_tdscnt);
5686 pcnt = SVAL(inbuf, smb_spscnt);
5687 poff = SVAL(inbuf, smb_spsoff);
5688 pdisp = SVAL(inbuf, smb_spsdisp);
5690 dcnt = SVAL(inbuf, smb_sdscnt);
5691 doff = SVAL(inbuf, smb_sdsoff);
5692 ddisp = SVAL(inbuf, smb_sdsdisp);
5694 state->received_param += pcnt;
5695 state->received_data += dcnt;
5697 if ((state->received_data > state->total_data) ||
5698 (state->received_param > state->total_param))
5699 goto bad_param;
5701 if (pcnt) {
5702 if (pdisp+pcnt > state->total_param)
5703 goto bad_param;
5704 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5705 goto bad_param;
5706 if (pdisp > state->total_param)
5707 goto bad_param;
5708 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5709 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5710 goto bad_param;
5711 if (state->param + pdisp < state->param)
5712 goto bad_param;
5714 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5715 pcnt);
5718 if (dcnt) {
5719 if (ddisp+dcnt > state->total_data)
5720 goto bad_param;
5721 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5722 goto bad_param;
5723 if (ddisp > state->total_data)
5724 goto bad_param;
5725 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5726 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5727 goto bad_param;
5728 if (state->data + ddisp < state->data)
5729 goto bad_param;
5731 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5732 dcnt);
5735 if ((state->received_param < state->total_param) ||
5736 (state->received_data < state->total_data)) {
5737 END_PROFILE(SMBtranss2);
5738 return -1;
5741 /* construct_reply_common has done us the favor to pre-fill the
5742 * command field with SMBtranss2 which is wrong :-)
5744 SCVAL(outbuf,smb_com,SMBtrans2);
5746 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5748 DLIST_REMOVE(conn->pending_trans, state);
5749 SAFE_FREE(state->data);
5750 SAFE_FREE(state->param);
5751 TALLOC_FREE(state);
5753 if (outsize == 0) {
5754 END_PROFILE(SMBtranss2);
5755 return(ERROR_DOS(ERRSRV,ERRnosupport));
5758 END_PROFILE(SMBtranss2);
5759 return(outsize);
5761 bad_param:
5763 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5764 DLIST_REMOVE(conn->pending_trans, state);
5765 SAFE_FREE(state->data);
5766 SAFE_FREE(state->param);
5767 TALLOC_FREE(state);
5768 END_PROFILE(SMBtranss2);
5769 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);