Samba 3: added Samba 3.0.24 sources
[tomato.git] / release / src / router / samba3 / source / smbd / trans2.c
blob445570c6c450ca245b791f33ac1a5de9a94e3d16
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(mem_ctx, 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, *tmp;
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, tmp);
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 *tmp;
400 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
401 unsigned int namelen = CVAL(pdata,offset);
403 offset++; /* Go past the namelen byte. */
405 /* integer wrap paranioa. */
406 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
407 (offset > data_size) || (namelen > data_size) ||
408 (offset + namelen >= data_size)) {
409 break;
411 /* Ensure the name is null terminated. */
412 if (pdata[offset + namelen] != '\0') {
413 return NULL;
415 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
416 if (!eal->ea.name) {
417 return NULL;
420 offset += (namelen + 1); /* Go past the name + terminating zero. */
421 DLIST_ADD_END(ea_list_head, eal, tmp);
422 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
425 return ea_list_head;
428 /****************************************************************************
429 Read one EA list entry from the buffer.
430 ****************************************************************************/
432 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
434 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
435 uint16 val_len;
436 unsigned int namelen;
438 if (!eal) {
439 return NULL;
442 if (data_size < 6) {
443 return NULL;
446 eal->ea.flags = CVAL(pdata,0);
447 namelen = CVAL(pdata,1);
448 val_len = SVAL(pdata,2);
450 if (4 + namelen + 1 + val_len > data_size) {
451 return NULL;
454 /* Ensure the name is null terminated. */
455 if (pdata[namelen + 4] != '\0') {
456 return NULL;
458 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
459 if (!eal->ea.name) {
460 return NULL;
463 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
464 if (!eal->ea.value.data) {
465 return NULL;
468 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
470 /* Ensure we're null terminated just in case we print the value. */
471 eal->ea.value.data[val_len] = '\0';
472 /* But don't count the null. */
473 eal->ea.value.length--;
475 if (pbytes_used) {
476 *pbytes_used = 4 + namelen + 1 + val_len;
479 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
480 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
482 return eal;
485 /****************************************************************************
486 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
487 ****************************************************************************/
489 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
491 struct ea_list *ea_list_head = NULL;
492 size_t offset = 0;
493 size_t bytes_used = 0;
495 while (offset < data_size) {
496 struct ea_list *tmp;
497 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
499 if (!eal) {
500 return NULL;
503 DLIST_ADD_END(ea_list_head, eal, tmp);
504 offset += bytes_used;
507 return ea_list_head;
510 /****************************************************************************
511 Count the total EA size needed.
512 ****************************************************************************/
514 static size_t ea_list_size(struct ea_list *ealist)
516 fstring dos_ea_name;
517 struct ea_list *listp;
518 size_t ret = 0;
520 for (listp = ealist; listp; listp = listp->next) {
521 push_ascii_fstring(dos_ea_name, listp->ea.name);
522 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
524 /* Add on 4 for total length. */
525 if (ret) {
526 ret += 4;
529 return ret;
532 /****************************************************************************
533 Return a union of EA's from a file list and a list of names.
534 The TALLOC context for the two lists *MUST* be identical as we steal
535 memory from one list to add to another. JRA.
536 ****************************************************************************/
538 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
540 struct ea_list *nlistp, *flistp;
542 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
543 for (flistp = file_list; flistp; flistp = flistp->next) {
544 if (strequal(nlistp->ea.name, flistp->ea.name)) {
545 break;
549 if (flistp) {
550 /* Copy the data from this entry. */
551 nlistp->ea.flags = flistp->ea.flags;
552 nlistp->ea.value = flistp->ea.value;
553 } else {
554 /* Null entry. */
555 nlistp->ea.flags = 0;
556 ZERO_STRUCT(nlistp->ea.value);
560 *total_ea_len = ea_list_size(name_list);
561 return name_list;
564 /****************************************************************************
565 Send the required number of replies back.
566 We assume all fields other than the data fields are
567 set correctly for the type of call.
568 HACK ! Always assumes smb_setup field is zero.
569 ****************************************************************************/
571 int send_trans2_replies(char *outbuf,
572 int bufsize,
573 char *params,
574 int paramsize,
575 char *pdata,
576 int datasize)
578 /* As we are using a protocol > LANMAN1 then the max_send
579 variable must have been set in the sessetupX call.
580 This takes precedence over the max_xmit field in the
581 global struct. These different max_xmit variables should
582 be merged as this is now too confusing */
584 int data_to_send = datasize;
585 int params_to_send = paramsize;
586 int useable_space;
587 char *pp = params;
588 char *pd = pdata;
589 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
590 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
591 int data_alignment_offset = 0;
593 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
595 set_message(outbuf,10,0,True);
597 /* If there genuinely are no parameters or data to send just send the empty packet */
599 if(params_to_send == 0 && data_to_send == 0) {
600 show_msg(outbuf);
601 if (!send_smb(smbd_server_fd(),outbuf))
602 exit_server("send_trans2_replies: send_smb failed.");
603 return 0;
606 /* When sending params and data ensure that both are nicely aligned */
607 /* Only do this alignment when there is also data to send - else
608 can cause NT redirector problems. */
610 if (((params_to_send % 4) != 0) && (data_to_send != 0))
611 data_alignment_offset = 4 - (params_to_send % 4);
613 /* Space is bufsize minus Netbios over TCP header minus SMB header */
614 /* The alignment_offset is to align the param bytes on an even byte
615 boundary. NT 4.0 Beta needs this to work correctly. */
617 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
619 /* useable_space can never be more than max_send minus the alignment offset. */
621 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
623 while (params_to_send || data_to_send) {
624 /* Calculate whether we will totally or partially fill this packet */
626 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
628 /* We can never send more than useable_space */
630 * Note that 'useable_space' does not include the alignment offsets,
631 * but we must include the alignment offsets in the calculation of
632 * the length of the data we send over the wire, as the alignment offsets
633 * are sent here. Fix from Marc_Jacobsen@hp.com.
636 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
638 set_message(outbuf, 10, total_sent_thistime, True);
640 /* Set total params and data to be sent */
641 SSVAL(outbuf,smb_tprcnt,paramsize);
642 SSVAL(outbuf,smb_tdrcnt,datasize);
644 /* Calculate how many parameters and data we can fit into
645 * this packet. Parameters get precedence
648 params_sent_thistime = MIN(params_to_send,useable_space);
649 data_sent_thistime = useable_space - params_sent_thistime;
650 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
652 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
654 /* smb_proff is the offset from the start of the SMB header to the
655 parameter bytes, however the first 4 bytes of outbuf are
656 the Netbios over TCP header. Thus use smb_base() to subtract
657 them from the calculation */
659 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
661 if(params_sent_thistime == 0)
662 SSVAL(outbuf,smb_prdisp,0);
663 else
664 /* Absolute displacement of param bytes sent in this packet */
665 SSVAL(outbuf,smb_prdisp,pp - params);
667 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
668 if(data_sent_thistime == 0) {
669 SSVAL(outbuf,smb_droff,0);
670 SSVAL(outbuf,smb_drdisp, 0);
671 } else {
672 /* The offset of the data bytes is the offset of the
673 parameter bytes plus the number of parameters being sent this time */
674 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
675 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
676 SSVAL(outbuf,smb_drdisp, pd - pdata);
679 /* Copy the param bytes into the packet */
681 if(params_sent_thistime)
682 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
684 /* Copy in the data bytes */
685 if(data_sent_thistime)
686 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
687 data_alignment_offset,pd,data_sent_thistime);
689 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
690 params_sent_thistime, data_sent_thistime, useable_space));
691 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
692 params_to_send, data_to_send, paramsize, datasize));
694 /* Send the packet */
695 show_msg(outbuf);
696 if (!send_smb(smbd_server_fd(),outbuf))
697 exit_server("send_trans2_replies: send_smb failed.");
699 pp += params_sent_thistime;
700 pd += data_sent_thistime;
702 params_to_send -= params_sent_thistime;
703 data_to_send -= data_sent_thistime;
705 /* Sanity check */
706 if(params_to_send < 0 || data_to_send < 0) {
707 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
708 params_to_send, data_to_send));
709 return -1;
713 return 0;
716 /****************************************************************************
717 Reply to a TRANSACT2_OPEN.
718 ****************************************************************************/
720 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
721 char **pparams, int total_params, char **ppdata, int total_data,
722 unsigned int max_data_bytes)
724 char *params = *pparams;
725 char *pdata = *ppdata;
726 int deny_mode;
727 int32 open_attr;
728 BOOL oplock_request;
729 #if 0
730 BOOL return_additional_info;
731 int16 open_sattr;
732 time_t open_time;
733 #endif
734 int open_ofun;
735 uint32 open_size;
736 char *pname;
737 pstring fname;
738 SMB_OFF_T size=0;
739 int fattr=0,mtime=0;
740 SMB_INO_T inode = 0;
741 SMB_STRUCT_STAT sbuf;
742 int smb_action = 0;
743 BOOL bad_path = False;
744 files_struct *fsp;
745 TALLOC_CTX *ctx = NULL;
746 struct ea_list *ea_list = NULL;
747 uint16 flags = 0;
748 NTSTATUS status;
749 uint32 access_mask;
750 uint32 share_mode;
751 uint32 create_disposition;
752 uint32 create_options = 0;
755 * Ensure we have enough parameters to perform the operation.
758 if (total_params < 29) {
759 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
762 flags = SVAL(params, 0);
763 deny_mode = SVAL(params, 2);
764 open_attr = SVAL(params,6);
765 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
766 if (oplock_request) {
767 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
770 #if 0
771 return_additional_info = BITSETW(params,0);
772 open_sattr = SVAL(params, 4);
773 open_time = make_unix_date3(params+8);
774 #endif
775 open_ofun = SVAL(params,12);
776 open_size = IVAL(params,14);
777 pname = &params[28];
779 if (IS_IPC(conn)) {
780 return(ERROR_DOS(ERRSRV,ERRaccess));
783 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
784 if (!NT_STATUS_IS_OK(status)) {
785 return ERROR_NT(status);
788 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
789 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
790 (unsigned int)open_ofun, open_size));
792 /* XXXX we need to handle passed times, sattr and flags */
794 unix_convert(fname,conn,0,&bad_path,&sbuf);
795 if (bad_path) {
796 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
799 if (!check_name(fname,conn)) {
800 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
803 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
804 &access_mask,
805 &share_mode,
806 &create_disposition,
807 &create_options)) {
808 return ERROR_DOS(ERRDOS, ERRbadaccess);
811 /* Any data in this call is an EA list. */
812 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
813 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
816 if (total_data != 4) {
817 if (total_data < 10) {
818 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
821 if (IVAL(pdata,0) > total_data) {
822 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
823 IVAL(pdata,0), (unsigned int)total_data));
824 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
827 ctx = talloc_init("TRANS2_OPEN_SET_EA");
828 if (!ctx) {
829 return ERROR_NT(NT_STATUS_NO_MEMORY);
831 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
832 if (!ea_list) {
833 talloc_destroy(ctx);
834 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
836 } else if (IVAL(pdata,0) != 4) {
837 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
840 fsp = open_file_ntcreate(conn,fname,&sbuf,
841 access_mask,
842 share_mode,
843 create_disposition,
844 create_options,
845 open_attr,
846 oplock_request,
847 &smb_action);
849 if (!fsp) {
850 talloc_destroy(ctx);
851 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
852 /* We have re-scheduled this call. */
853 return -1;
855 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
858 size = get_file_size(sbuf);
859 fattr = dos_mode(conn,fname,&sbuf);
860 mtime = sbuf.st_mtime;
861 inode = sbuf.st_ino;
862 if (fattr & aDIR) {
863 talloc_destroy(ctx);
864 close_file(fsp,ERROR_CLOSE);
865 return(ERROR_DOS(ERRDOS,ERRnoaccess));
868 /* Save the requested allocation size. */
869 /* Allocate space for the file if a size hint is supplied */
870 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
871 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
872 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
873 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
874 if (fsp->is_directory) {
875 close_file(fsp,ERROR_CLOSE);
876 /* Can't set allocation size on a directory. */
877 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
879 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
880 close_file(fsp,ERROR_CLOSE);
881 return ERROR_NT(NT_STATUS_DISK_FULL);
884 /* Adjust size here to return the right size in the reply.
885 Windows does it this way. */
886 size = fsp->initial_allocation_size;
887 } else {
888 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
892 if (total_data && smb_action == FILE_WAS_CREATED) {
893 status = set_ea(conn, fsp, fname, ea_list);
894 talloc_destroy(ctx);
895 if (!NT_STATUS_IS_OK(status)) {
896 close_file(fsp,ERROR_CLOSE);
897 return ERROR_NT(status);
901 /* Realloc the size of parameters and data we will return */
902 *pparams = SMB_REALLOC(*pparams, 30);
903 if(*pparams == NULL ) {
904 return ERROR_NT(NT_STATUS_NO_MEMORY);
906 params = *pparams;
908 SSVAL(params,0,fsp->fnum);
909 SSVAL(params,2,open_attr);
910 srv_put_dos_date2(params,4, mtime);
911 SIVAL(params,8, (uint32)size);
912 SSVAL(params,12,deny_mode);
913 SSVAL(params,14,0); /* open_type - file or directory. */
914 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
916 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
917 smb_action |= EXTENDED_OPLOCK_GRANTED;
920 SSVAL(params,18,smb_action);
923 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
925 SIVAL(params,20,inode);
926 SSVAL(params,24,0); /* Padding. */
927 if (flags & 8) {
928 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
929 SIVAL(params, 26, ea_size);
930 } else {
931 SIVAL(params, 26, 0);
934 /* Send the required number of replies */
935 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
937 return -1;
940 /*********************************************************
941 Routine to check if a given string matches exactly.
942 as a special case a mask of "." does NOT match. That
943 is required for correct wildcard semantics
944 Case can be significant or not.
945 **********************************************************/
947 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
949 if (mask[0] == '.' && mask[1] == 0)
950 return False;
951 if (conn->case_sensitive)
952 return strcmp(str,mask)==0;
953 if (StrCaseCmp(str,mask) != 0) {
954 return False;
956 if (dptr_has_wild(conn->dirptr)) {
957 return False;
959 return True;
962 /****************************************************************************
963 Return the filetype for UNIX extensions.
964 ****************************************************************************/
966 static uint32 unix_filetype(mode_t mode)
968 if(S_ISREG(mode))
969 return UNIX_TYPE_FILE;
970 else if(S_ISDIR(mode))
971 return UNIX_TYPE_DIR;
972 #ifdef S_ISLNK
973 else if(S_ISLNK(mode))
974 return UNIX_TYPE_SYMLINK;
975 #endif
976 #ifdef S_ISCHR
977 else if(S_ISCHR(mode))
978 return UNIX_TYPE_CHARDEV;
979 #endif
980 #ifdef S_ISBLK
981 else if(S_ISBLK(mode))
982 return UNIX_TYPE_BLKDEV;
983 #endif
984 #ifdef S_ISFIFO
985 else if(S_ISFIFO(mode))
986 return UNIX_TYPE_FIFO;
987 #endif
988 #ifdef S_ISSOCK
989 else if(S_ISSOCK(mode))
990 return UNIX_TYPE_SOCKET;
991 #endif
993 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
994 return UNIX_TYPE_UNKNOWN;
997 /****************************************************************************
998 Map wire perms onto standard UNIX permissions. Obey share restrictions.
999 ****************************************************************************/
1001 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
1003 mode_t ret = 0;
1005 if (perms == SMB_MODE_NO_CHANGE)
1006 return pst->st_mode;
1008 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1009 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1010 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1011 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1012 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1013 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1014 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1015 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1016 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1017 #ifdef S_ISVTX
1018 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1019 #endif
1020 #ifdef S_ISGID
1021 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1022 #endif
1023 #ifdef S_ISUID
1024 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1025 #endif
1027 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
1028 ret &= lp_dir_mask(SNUM(conn));
1029 /* Add in force bits */
1030 ret |= lp_force_dir_mode(SNUM(conn));
1031 } else {
1032 /* Apply mode mask */
1033 ret &= lp_create_mask(SNUM(conn));
1034 /* Add in force bits */
1035 ret |= lp_force_create_mode(SNUM(conn));
1038 return ret;
1041 /****************************************************************************
1042 Get a level dependent lanman2 dir entry.
1043 ****************************************************************************/
1045 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1046 void *inbuf, void *outbuf,
1047 char *path_mask,uint32 dirtype,int info_level,
1048 int requires_resume_key,
1049 BOOL dont_descend,char **ppdata,
1050 char *base_data, int space_remaining,
1051 BOOL *out_of_space, BOOL *got_exact_match,
1052 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1054 const char *dname;
1055 BOOL found = False;
1056 SMB_STRUCT_STAT sbuf;
1057 pstring mask;
1058 pstring pathreal;
1059 pstring fname;
1060 char *p, *q, *pdata = *ppdata;
1061 uint32 reskey=0;
1062 long prev_dirpos=0;
1063 uint32 mode=0;
1064 SMB_OFF_T file_size = 0;
1065 SMB_BIG_UINT allocation_size = 0;
1066 uint32 len;
1067 time_t mdate=0, adate=0, cdate=0;
1068 char *nameptr;
1069 char *last_entry_ptr;
1070 BOOL was_8_3;
1071 uint32 nt_extmode; /* Used for NT connections instead of mode */
1072 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1073 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1075 *fname = 0;
1076 *out_of_space = False;
1077 *got_exact_match = False;
1079 if (!conn->dirptr)
1080 return(False);
1082 p = strrchr_m(path_mask,'/');
1083 if(p != NULL) {
1084 if(p[1] == '\0')
1085 pstrcpy(mask,"*.*");
1086 else
1087 pstrcpy(mask, p+1);
1088 } else
1089 pstrcpy(mask, path_mask);
1092 while (!found) {
1093 BOOL got_match;
1094 BOOL ms_dfs_link = False;
1096 /* Needed if we run out of space */
1097 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1098 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1101 * Due to bugs in NT client redirectors we are not using
1102 * resume keys any more - set them to zero.
1103 * Check out the related comments in findfirst/findnext.
1104 * JRA.
1107 reskey = 0;
1109 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1110 (long)conn->dirptr,curr_dirpos));
1112 if (!dname)
1113 return(False);
1115 pstrcpy(fname,dname);
1117 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1118 got_match = mask_match(fname, mask, conn->case_sensitive);
1120 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1123 * It turns out that NT matches wildcards against
1124 * both long *and* short names. This may explain some
1125 * of the wildcard wierdness from old DOS clients
1126 * that some people have been seeing.... JRA.
1129 pstring newname;
1130 pstrcpy( newname, fname);
1131 mangle_map( newname, True, False, SNUM(conn));
1132 if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1133 got_match = mask_match(newname, mask, conn->case_sensitive);
1136 if(got_match) {
1137 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1138 if (dont_descend && !isdots)
1139 continue;
1141 pstrcpy(pathreal,conn->dirpath);
1142 if(needslash)
1143 pstrcat(pathreal,"/");
1144 pstrcat(pathreal,dname);
1146 if (INFO_LEVEL_IS_UNIX(info_level)) {
1147 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1148 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1149 pathreal,strerror(errno)));
1150 continue;
1152 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1154 /* Needed to show the msdfs symlinks as
1155 * directories */
1157 if(lp_host_msdfs() &&
1158 lp_msdfs_root(SNUM(conn)) &&
1159 ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1161 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1162 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1164 } else {
1166 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1167 pathreal,strerror(errno)));
1168 continue;
1172 if (ms_dfs_link) {
1173 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1174 } else {
1175 mode = dos_mode(conn,pathreal,&sbuf);
1178 if (!dir_check_ftype(conn,mode,dirtype)) {
1179 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1180 continue;
1183 if (!(mode & aDIR))
1184 file_size = get_file_size(sbuf);
1185 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1186 mdate = sbuf.st_mtime;
1187 adate = sbuf.st_atime;
1188 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1190 if (lp_dos_filetime_resolution(SNUM(conn))) {
1191 cdate &= ~1;
1192 mdate &= ~1;
1193 adate &= ~1;
1197 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1199 found = True;
1201 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1205 mangle_map(fname,False,True,SNUM(conn));
1207 p = pdata;
1208 last_entry_ptr = p;
1210 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1212 switch (info_level) {
1213 case SMB_FIND_INFO_STANDARD:
1214 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1215 if(requires_resume_key) {
1216 SIVAL(p,0,reskey);
1217 p += 4;
1219 srv_put_dos_date2(p,0,cdate);
1220 srv_put_dos_date2(p,4,adate);
1221 srv_put_dos_date2(p,8,mdate);
1222 SIVAL(p,12,(uint32)file_size);
1223 SIVAL(p,16,(uint32)allocation_size);
1224 SSVAL(p,20,mode);
1225 p += 23;
1226 nameptr = p;
1227 p += align_string(outbuf, p, 0);
1228 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1229 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1230 if (len > 2) {
1231 SCVAL(nameptr, -1, len - 2);
1232 } else {
1233 SCVAL(nameptr, -1, 0);
1235 } else {
1236 if (len > 1) {
1237 SCVAL(nameptr, -1, len - 1);
1238 } else {
1239 SCVAL(nameptr, -1, 0);
1242 p += len;
1243 break;
1245 case SMB_FIND_EA_SIZE:
1246 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1247 if(requires_resume_key) {
1248 SIVAL(p,0,reskey);
1249 p += 4;
1251 srv_put_dos_date2(p,0,cdate);
1252 srv_put_dos_date2(p,4,adate);
1253 srv_put_dos_date2(p,8,mdate);
1254 SIVAL(p,12,(uint32)file_size);
1255 SIVAL(p,16,(uint32)allocation_size);
1256 SSVAL(p,20,mode);
1258 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1259 SIVAL(p,22,ea_size); /* Extended attributes */
1261 p += 27;
1262 nameptr = p - 1;
1263 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1264 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1265 if (len > 2) {
1266 len -= 2;
1267 } else {
1268 len = 0;
1270 } else {
1271 if (len > 1) {
1272 len -= 1;
1273 } else {
1274 len = 0;
1277 SCVAL(nameptr,0,len);
1278 p += len;
1279 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1280 break;
1282 case SMB_FIND_EA_LIST:
1284 struct ea_list *file_list = NULL;
1285 size_t ea_len = 0;
1287 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1288 if (!name_list) {
1289 return False;
1291 if(requires_resume_key) {
1292 SIVAL(p,0,reskey);
1293 p += 4;
1295 srv_put_dos_date2(p,0,cdate);
1296 srv_put_dos_date2(p,4,adate);
1297 srv_put_dos_date2(p,8,mdate);
1298 SIVAL(p,12,(uint32)file_size);
1299 SIVAL(p,16,(uint32)allocation_size);
1300 SSVAL(p,20,mode);
1301 p += 22; /* p now points to the EA area. */
1303 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1304 name_list = ea_list_union(name_list, file_list, &ea_len);
1306 /* We need to determine if this entry will fit in the space available. */
1307 /* Max string size is 255 bytes. */
1308 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1309 /* Move the dirptr back to prev_dirpos */
1310 dptr_SeekDir(conn->dirptr, prev_dirpos);
1311 *out_of_space = True;
1312 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1313 return False; /* Not finished - just out of space */
1316 /* Push the ea_data followed by the name. */
1317 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1318 nameptr = p;
1319 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1320 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1321 if (len > 2) {
1322 len -= 2;
1323 } else {
1324 len = 0;
1326 } else {
1327 if (len > 1) {
1328 len -= 1;
1329 } else {
1330 len = 0;
1333 SCVAL(nameptr,0,len);
1334 p += len + 1;
1335 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1336 break;
1339 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1340 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1341 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1342 p += 4;
1343 SIVAL(p,0,reskey); p += 4;
1344 put_long_date(p,cdate); p += 8;
1345 put_long_date(p,adate); p += 8;
1346 put_long_date(p,mdate); p += 8;
1347 put_long_date(p,mdate); p += 8;
1348 SOFF_T(p,0,file_size); p += 8;
1349 SOFF_T(p,0,allocation_size); p += 8;
1350 SIVAL(p,0,nt_extmode); p += 4;
1351 q = p; p += 4; /* q is placeholder for name length. */
1353 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1354 SIVAL(p,0,ea_size); /* Extended attributes */
1355 p += 4;
1357 /* Clear the short name buffer. This is
1358 * IMPORTANT as not doing so will trigger
1359 * a Win2k client bug. JRA.
1361 if (!was_8_3 && check_mangled_names) {
1362 pstring mangled_name;
1363 pstrcpy(mangled_name, fname);
1364 mangle_map(mangled_name,True,True,SNUM(conn));
1365 mangled_name[12] = 0;
1366 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1367 if (len < 24) {
1368 memset(p + 2 + len,'\0',24 - len);
1370 SSVAL(p, 0, len);
1371 } else {
1372 memset(p,'\0',26);
1374 p += 2 + 24;
1375 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1376 SIVAL(q,0,len);
1377 p += len;
1378 SIVAL(p,0,0); /* Ensure any padding is null. */
1379 len = PTR_DIFF(p, pdata);
1380 len = (len + 3) & ~3;
1381 SIVAL(pdata,0,len);
1382 p = pdata + len;
1383 break;
1385 case SMB_FIND_FILE_DIRECTORY_INFO:
1386 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1387 p += 4;
1388 SIVAL(p,0,reskey); p += 4;
1389 put_long_date(p,cdate); p += 8;
1390 put_long_date(p,adate); p += 8;
1391 put_long_date(p,mdate); p += 8;
1392 put_long_date(p,mdate); p += 8;
1393 SOFF_T(p,0,file_size); p += 8;
1394 SOFF_T(p,0,allocation_size); p += 8;
1395 SIVAL(p,0,nt_extmode); p += 4;
1396 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1397 SIVAL(p,0,len);
1398 p += 4 + len;
1399 SIVAL(p,0,0); /* Ensure any padding is null. */
1400 len = PTR_DIFF(p, pdata);
1401 len = (len + 3) & ~3;
1402 SIVAL(pdata,0,len);
1403 p = pdata + len;
1404 break;
1406 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1407 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1408 p += 4;
1409 SIVAL(p,0,reskey); p += 4;
1410 put_long_date(p,cdate); p += 8;
1411 put_long_date(p,adate); p += 8;
1412 put_long_date(p,mdate); p += 8;
1413 put_long_date(p,mdate); p += 8;
1414 SOFF_T(p,0,file_size); p += 8;
1415 SOFF_T(p,0,allocation_size); p += 8;
1416 SIVAL(p,0,nt_extmode); p += 4;
1417 q = p; p += 4; /* q is placeholder for name length. */
1419 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1420 SIVAL(p,0,ea_size); /* Extended attributes */
1421 p +=4;
1423 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1424 SIVAL(q, 0, len);
1425 p += len;
1427 SIVAL(p,0,0); /* Ensure any padding is null. */
1428 len = PTR_DIFF(p, pdata);
1429 len = (len + 3) & ~3;
1430 SIVAL(pdata,0,len);
1431 p = pdata + len;
1432 break;
1434 case SMB_FIND_FILE_NAMES_INFO:
1435 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1436 p += 4;
1437 SIVAL(p,0,reskey); p += 4;
1438 p += 4;
1439 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1440 acl on a dir (tridge) */
1441 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1442 SIVAL(p, -4, len);
1443 p += len;
1444 SIVAL(p,0,0); /* Ensure any padding is null. */
1445 len = PTR_DIFF(p, pdata);
1446 len = (len + 3) & ~3;
1447 SIVAL(pdata,0,len);
1448 p = pdata + len;
1449 break;
1451 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1452 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1453 p += 4;
1454 SIVAL(p,0,reskey); p += 4;
1455 put_long_date(p,cdate); p += 8;
1456 put_long_date(p,adate); p += 8;
1457 put_long_date(p,mdate); p += 8;
1458 put_long_date(p,mdate); p += 8;
1459 SOFF_T(p,0,file_size); p += 8;
1460 SOFF_T(p,0,allocation_size); p += 8;
1461 SIVAL(p,0,nt_extmode); p += 4;
1462 q = p; p += 4; /* q is placeholder for name length. */
1464 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1465 SIVAL(p,0,ea_size); /* Extended attributes */
1466 p +=4;
1468 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1469 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1470 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1471 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1472 SIVAL(q, 0, len);
1473 p += len;
1474 SIVAL(p,0,0); /* Ensure any padding is null. */
1475 len = PTR_DIFF(p, pdata);
1476 len = (len + 3) & ~3;
1477 SIVAL(pdata,0,len);
1478 p = pdata + len;
1479 break;
1481 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1482 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1483 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1484 p += 4;
1485 SIVAL(p,0,reskey); p += 4;
1486 put_long_date(p,cdate); p += 8;
1487 put_long_date(p,adate); p += 8;
1488 put_long_date(p,mdate); p += 8;
1489 put_long_date(p,mdate); p += 8;
1490 SOFF_T(p,0,file_size); p += 8;
1491 SOFF_T(p,0,allocation_size); p += 8;
1492 SIVAL(p,0,nt_extmode); p += 4;
1493 q = p; p += 4; /* q is placeholder for name length */
1495 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1496 SIVAL(p,0,ea_size); /* Extended attributes */
1497 p +=4;
1499 /* Clear the short name buffer. This is
1500 * IMPORTANT as not doing so will trigger
1501 * a Win2k client bug. JRA.
1503 if (!was_8_3 && check_mangled_names) {
1504 pstring mangled_name;
1505 pstrcpy(mangled_name, fname);
1506 mangle_map(mangled_name,True,True,SNUM(conn));
1507 mangled_name[12] = 0;
1508 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1509 SSVAL(p, 0, len);
1510 if (len < 24) {
1511 memset(p + 2 + len,'\0',24 - len);
1513 SSVAL(p, 0, len);
1514 } else {
1515 memset(p,'\0',26);
1517 p += 26;
1518 SSVAL(p,0,0); p += 2; /* Reserved ? */
1519 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1520 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1521 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1522 SIVAL(q,0,len);
1523 p += len;
1524 SIVAL(p,0,0); /* Ensure any padding is null. */
1525 len = PTR_DIFF(p, pdata);
1526 len = (len + 3) & ~3;
1527 SIVAL(pdata,0,len);
1528 p = pdata + len;
1529 break;
1531 /* CIFS UNIX Extension. */
1533 case SMB_FIND_FILE_UNIX:
1534 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1535 p+= 4;
1536 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1538 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1539 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1540 p+= 8;
1542 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1543 p+= 8;
1545 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1546 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1547 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1548 p+= 24;
1550 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1551 SIVAL(p,4,0);
1552 p+= 8;
1554 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1555 SIVAL(p,4,0);
1556 p+= 8;
1558 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1559 p+= 4;
1561 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1562 SIVAL(p,4,0);
1563 p+= 8;
1565 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1566 SIVAL(p,4,0);
1567 p+= 8;
1569 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1570 p+= 8;
1572 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1573 SIVAL(p,4,0);
1574 p+= 8;
1576 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1577 SIVAL(p,4,0);
1578 p+= 8;
1580 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1581 p += len;
1582 SIVAL(p,0,0); /* Ensure any padding is null. */
1584 len = PTR_DIFF(p, pdata);
1585 len = (len + 3) & ~3;
1586 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1587 p = pdata + len;
1588 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1590 break;
1592 default:
1593 return(False);
1597 if (PTR_DIFF(p,pdata) > space_remaining) {
1598 /* Move the dirptr back to prev_dirpos */
1599 dptr_SeekDir(conn->dirptr, prev_dirpos);
1600 *out_of_space = True;
1601 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1602 return False; /* Not finished - just out of space */
1605 /* Setup the last entry pointer, as an offset from base_data */
1606 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1607 /* Advance the data pointer to the next slot */
1608 *ppdata = p;
1610 return(found);
1613 /****************************************************************************
1614 Reply to a TRANS2_FINDFIRST.
1615 ****************************************************************************/
1617 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1618 char **pparams, int total_params, char **ppdata, int total_data,
1619 unsigned int max_data_bytes)
1621 /* We must be careful here that we don't return more than the
1622 allowed number of data bytes. If this means returning fewer than
1623 maxentries then so be it. We assume that the redirector has
1624 enough room for the fixed number of parameter bytes it has
1625 requested. */
1626 char *params = *pparams;
1627 char *pdata = *ppdata;
1628 uint32 dirtype = SVAL(params,0);
1629 int maxentries = SVAL(params,2);
1630 uint16 findfirst_flags = SVAL(params,4);
1631 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1632 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1633 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1634 int info_level = SVAL(params,6);
1635 pstring directory;
1636 pstring mask;
1637 char *p;
1638 int last_entry_off=0;
1639 int dptr_num = -1;
1640 int numentries = 0;
1641 int i;
1642 BOOL finished = False;
1643 BOOL dont_descend = False;
1644 BOOL out_of_space = False;
1645 int space_remaining;
1646 BOOL bad_path = False;
1647 BOOL mask_contains_wcard = False;
1648 SMB_STRUCT_STAT sbuf;
1649 TALLOC_CTX *ea_ctx = NULL;
1650 struct ea_list *ea_list = NULL;
1651 NTSTATUS ntstatus = NT_STATUS_OK;
1653 if (total_params < 12) {
1654 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1657 *directory = *mask = 0;
1659 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1660 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1661 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1662 info_level, max_data_bytes));
1664 if (!maxentries) {
1665 /* W2K3 seems to treat zero as 1. */
1666 maxentries = 1;
1669 switch (info_level) {
1670 case SMB_FIND_INFO_STANDARD:
1671 case SMB_FIND_EA_SIZE:
1672 case SMB_FIND_EA_LIST:
1673 case SMB_FIND_FILE_DIRECTORY_INFO:
1674 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1675 case SMB_FIND_FILE_NAMES_INFO:
1676 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1677 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1678 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1679 break;
1680 case SMB_FIND_FILE_UNIX:
1681 if (!lp_unix_extensions()) {
1682 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1684 break;
1685 default:
1686 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1689 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1690 if (!NT_STATUS_IS_OK(ntstatus)) {
1691 return ERROR_NT(ntstatus);
1694 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1696 unix_convert(directory,conn,0,&bad_path,&sbuf);
1697 if (bad_path) {
1698 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1700 if(!check_name(directory,conn)) {
1701 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1704 p = strrchr_m(directory,'/');
1705 if(p == NULL) {
1706 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1707 if((directory[0] == '.') && (directory[1] == '\0')) {
1708 pstrcpy(mask,"*");
1709 mask_contains_wcard = True;
1710 } else {
1711 pstrcpy(mask,directory);
1713 pstrcpy(directory,"./");
1714 } else {
1715 pstrcpy(mask,p+1);
1716 *p = 0;
1719 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1721 if (info_level == SMB_FIND_EA_LIST) {
1722 uint32 ea_size;
1724 if (total_data < 4) {
1725 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1728 ea_size = IVAL(pdata,0);
1729 if (ea_size != total_data) {
1730 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1731 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1732 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1735 if (!lp_ea_support(SNUM(conn))) {
1736 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1739 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1740 return ERROR_NT(NT_STATUS_NO_MEMORY);
1743 /* Pull out the list of names. */
1744 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1745 if (!ea_list) {
1746 talloc_destroy(ea_ctx);
1747 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1751 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1752 if(*ppdata == NULL ) {
1753 talloc_destroy(ea_ctx);
1754 return ERROR_NT(NT_STATUS_NO_MEMORY);
1756 pdata = *ppdata;
1758 /* Realloc the params space */
1759 *pparams = SMB_REALLOC(*pparams, 10);
1760 if (*pparams == NULL) {
1761 talloc_destroy(ea_ctx);
1762 return ERROR_NT(NT_STATUS_NO_MEMORY);
1764 params = *pparams;
1766 /* Save the wildcard match and attribs we are using on this directory -
1767 needed as lanman2 assumes these are being saved between calls */
1769 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1770 if (dptr_num < 0) {
1771 talloc_destroy(ea_ctx);
1772 return(UNIXERROR(ERRDOS,ERRbadfile));
1775 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1777 /* We don't need to check for VOL here as this is returned by
1778 a different TRANS2 call. */
1780 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1781 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1782 dont_descend = True;
1784 p = pdata;
1785 space_remaining = max_data_bytes;
1786 out_of_space = False;
1788 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1789 BOOL got_exact_match = False;
1791 /* this is a heuristic to avoid seeking the dirptr except when
1792 absolutely necessary. It allows for a filename of about 40 chars */
1793 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1794 out_of_space = True;
1795 finished = False;
1796 } else {
1797 finished = !get_lanman2_dir_entry(conn,
1798 inbuf, outbuf,
1799 mask,dirtype,info_level,
1800 requires_resume_key,dont_descend,
1801 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1802 &last_entry_off, ea_list, ea_ctx);
1805 if (finished && out_of_space)
1806 finished = False;
1808 if (!finished && !out_of_space)
1809 numentries++;
1812 * As an optimisation if we know we aren't looking
1813 * for a wildcard name (ie. the name matches the wildcard exactly)
1814 * then we can finish on any (first) match.
1815 * This speeds up large directory searches. JRA.
1818 if(got_exact_match)
1819 finished = True;
1821 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1824 talloc_destroy(ea_ctx);
1826 /* Check if we can close the dirptr */
1827 if(close_after_first || (finished && close_if_end)) {
1828 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1829 dptr_close(&dptr_num);
1833 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1834 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1835 * the protocol level is less than NT1. Tested with smbclient. JRA.
1836 * This should fix the OS/2 client bug #2335.
1839 if(numentries == 0) {
1840 dptr_close(&dptr_num);
1841 if (Protocol < PROTOCOL_NT1) {
1842 return ERROR_DOS(ERRDOS,ERRnofiles);
1843 } else {
1844 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1848 /* At this point pdata points to numentries directory entries. */
1850 /* Set up the return parameter block */
1851 SSVAL(params,0,dptr_num);
1852 SSVAL(params,2,numentries);
1853 SSVAL(params,4,finished);
1854 SSVAL(params,6,0); /* Never an EA error */
1855 SSVAL(params,8,last_entry_off);
1857 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1859 if ((! *directory) && dptr_path(dptr_num))
1860 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1862 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1863 smb_fn_name(CVAL(inbuf,smb_com)),
1864 mask, directory, dirtype, numentries ) );
1867 * Force a name mangle here to ensure that the
1868 * mask as an 8.3 name is top of the mangled cache.
1869 * The reasons for this are subtle. Don't remove
1870 * this code unless you know what you are doing
1871 * (see PR#13758). JRA.
1874 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1875 mangle_map(mask, True, True, SNUM(conn));
1877 return(-1);
1880 /****************************************************************************
1881 Reply to a TRANS2_FINDNEXT.
1882 ****************************************************************************/
1884 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1885 char **pparams, int total_params, char **ppdata, int total_data,
1886 unsigned int max_data_bytes)
1888 /* We must be careful here that we don't return more than the
1889 allowed number of data bytes. If this means returning fewer than
1890 maxentries then so be it. We assume that the redirector has
1891 enough room for the fixed number of parameter bytes it has
1892 requested. */
1893 char *params = *pparams;
1894 char *pdata = *ppdata;
1895 int dptr_num = SVAL(params,0);
1896 int maxentries = SVAL(params,2);
1897 uint16 info_level = SVAL(params,4);
1898 uint32 resume_key = IVAL(params,6);
1899 uint16 findnext_flags = SVAL(params,10);
1900 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1901 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1902 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1903 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1904 BOOL mask_contains_wcard = False;
1905 pstring resume_name;
1906 pstring mask;
1907 pstring directory;
1908 char *p;
1909 uint16 dirtype;
1910 int numentries = 0;
1911 int i, last_entry_off=0;
1912 BOOL finished = False;
1913 BOOL dont_descend = False;
1914 BOOL out_of_space = False;
1915 int space_remaining;
1916 TALLOC_CTX *ea_ctx = NULL;
1917 struct ea_list *ea_list = NULL;
1918 NTSTATUS ntstatus = NT_STATUS_OK;
1920 if (total_params < 12) {
1921 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1924 *mask = *directory = *resume_name = 0;
1926 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1927 if (!NT_STATUS_IS_OK(ntstatus)) {
1928 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1929 complain (it thinks we're asking for the directory above the shared
1930 path or an invalid name). Catch this as the resume name is only compared, never used in
1931 a file access. JRA. */
1932 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1933 pstrcpy(resume_name, "..");
1934 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1935 pstrcpy(resume_name, ".");
1936 } else {
1937 return ERROR_NT(ntstatus);
1941 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1942 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1943 resume_key = %d resume name = %s continue=%d level = %d\n",
1944 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1945 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1947 if (!maxentries) {
1948 /* W2K3 seems to treat zero as 1. */
1949 maxentries = 1;
1952 switch (info_level) {
1953 case SMB_FIND_INFO_STANDARD:
1954 case SMB_FIND_EA_SIZE:
1955 case SMB_FIND_EA_LIST:
1956 case SMB_FIND_FILE_DIRECTORY_INFO:
1957 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1958 case SMB_FIND_FILE_NAMES_INFO:
1959 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1960 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1961 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1962 break;
1963 case SMB_FIND_FILE_UNIX:
1964 if (!lp_unix_extensions()) {
1965 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1967 break;
1968 default:
1969 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1972 if (info_level == SMB_FIND_EA_LIST) {
1973 uint32 ea_size;
1975 if (total_data < 4) {
1976 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1979 ea_size = IVAL(pdata,0);
1980 if (ea_size != total_data) {
1981 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1982 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1983 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1986 if (!lp_ea_support(SNUM(conn))) {
1987 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1990 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1991 return ERROR_NT(NT_STATUS_NO_MEMORY);
1994 /* Pull out the list of names. */
1995 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1996 if (!ea_list) {
1997 talloc_destroy(ea_ctx);
1998 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2002 *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2003 if(*ppdata == NULL) {
2004 talloc_destroy(ea_ctx);
2005 return ERROR_NT(NT_STATUS_NO_MEMORY);
2008 pdata = *ppdata;
2010 /* Realloc the params space */
2011 *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2012 if(*pparams == NULL ) {
2013 talloc_destroy(ea_ctx);
2014 return ERROR_NT(NT_STATUS_NO_MEMORY);
2017 params = *pparams;
2019 /* Check that the dptr is valid */
2020 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2021 talloc_destroy(ea_ctx);
2022 return ERROR_DOS(ERRDOS,ERRnofiles);
2025 string_set(&conn->dirpath,dptr_path(dptr_num));
2027 /* Get the wildcard mask from the dptr */
2028 if((p = dptr_wcard(dptr_num))== NULL) {
2029 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2030 talloc_destroy(ea_ctx);
2031 return ERROR_DOS(ERRDOS,ERRnofiles);
2034 pstrcpy(mask, p);
2035 pstrcpy(directory,conn->dirpath);
2037 /* Get the attr mask from the dptr */
2038 dirtype = dptr_attr(dptr_num);
2040 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2041 dptr_num, mask, dirtype,
2042 (long)conn->dirptr,
2043 dptr_TellDir(conn->dirptr)));
2045 /* We don't need to check for VOL here as this is returned by
2046 a different TRANS2 call. */
2048 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2049 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2050 dont_descend = True;
2052 p = pdata;
2053 space_remaining = max_data_bytes;
2054 out_of_space = False;
2057 * Seek to the correct position. We no longer use the resume key but
2058 * depend on the last file name instead.
2061 if(*resume_name && !continue_bit) {
2062 SMB_STRUCT_STAT st;
2064 long current_pos = 0;
2066 * Remember, mangle_map is called by
2067 * get_lanman2_dir_entry(), so the resume name
2068 * could be mangled. Ensure we check the unmangled name.
2071 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2072 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2076 * Fix for NT redirector problem triggered by resume key indexes
2077 * changing between directory scans. We now return a resume key of 0
2078 * and instead look for the filename to continue from (also given
2079 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2080 * findfirst/findnext (as is usual) then the directory pointer
2081 * should already be at the correct place.
2084 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2085 } /* end if resume_name && !continue_bit */
2087 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2088 BOOL got_exact_match = False;
2090 /* this is a heuristic to avoid seeking the dirptr except when
2091 absolutely necessary. It allows for a filename of about 40 chars */
2092 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2093 out_of_space = True;
2094 finished = False;
2095 } else {
2096 finished = !get_lanman2_dir_entry(conn,
2097 inbuf, outbuf,
2098 mask,dirtype,info_level,
2099 requires_resume_key,dont_descend,
2100 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2101 &last_entry_off, ea_list, ea_ctx);
2104 if (finished && out_of_space)
2105 finished = False;
2107 if (!finished && !out_of_space)
2108 numentries++;
2111 * As an optimisation if we know we aren't looking
2112 * for a wildcard name (ie. the name matches the wildcard exactly)
2113 * then we can finish on any (first) match.
2114 * This speeds up large directory searches. JRA.
2117 if(got_exact_match)
2118 finished = True;
2120 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2123 talloc_destroy(ea_ctx);
2125 /* Check if we can close the dirptr */
2126 if(close_after_request || (finished && close_if_end)) {
2127 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2128 dptr_close(&dptr_num); /* This frees up the saved mask */
2131 /* Set up the return parameter block */
2132 SSVAL(params,0,numentries);
2133 SSVAL(params,2,finished);
2134 SSVAL(params,4,0); /* Never an EA error */
2135 SSVAL(params,6,last_entry_off);
2137 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2139 if ((! *directory) && dptr_path(dptr_num))
2140 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2142 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2143 smb_fn_name(CVAL(inbuf,smb_com)),
2144 mask, directory, dirtype, numentries ) );
2146 return(-1);
2149 /****************************************************************************
2150 Reply to a TRANS2_QFSINFO (query filesystem info).
2151 ****************************************************************************/
2153 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2154 char **pparams, int total_params, char **ppdata, int total_data,
2155 unsigned int max_data_bytes)
2157 char *pdata = *ppdata;
2158 char *params = *pparams;
2159 uint16 info_level = SVAL(params,0);
2160 int data_len, len;
2161 SMB_STRUCT_STAT st;
2162 char *vname = volume_label(SNUM(conn));
2163 int snum = SNUM(conn);
2164 char *fstype = lp_fstype(SNUM(conn));
2165 int quota_flag = 0;
2167 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2169 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2170 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2171 return ERROR_DOS(ERRSRV,ERRinvdevice);
2174 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2175 if (*ppdata == NULL ) {
2176 return ERROR_NT(NT_STATUS_NO_MEMORY);
2179 pdata = *ppdata;
2180 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2182 switch (info_level) {
2183 case SMB_INFO_ALLOCATION:
2185 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2186 data_len = 18;
2187 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2188 return(UNIXERROR(ERRHRD,ERRgeneral));
2191 block_size = lp_block_size(snum);
2192 if (bsize < block_size) {
2193 SMB_BIG_UINT factor = block_size/bsize;
2194 bsize = block_size;
2195 dsize /= factor;
2196 dfree /= factor;
2198 if (bsize > block_size) {
2199 SMB_BIG_UINT factor = bsize/block_size;
2200 bsize = block_size;
2201 dsize *= factor;
2202 dfree *= factor;
2204 bytes_per_sector = 512;
2205 sectors_per_unit = bsize/bytes_per_sector;
2207 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2208 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2209 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2211 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2212 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2213 SIVAL(pdata,l1_cUnit,dsize);
2214 SIVAL(pdata,l1_cUnitAvail,dfree);
2215 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2216 break;
2219 case SMB_INFO_VOLUME:
2220 /* Return volume name */
2222 * Add volume serial number - hash of a combination of
2223 * the called hostname and the service name.
2225 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2227 * Win2k3 and previous mess this up by sending a name length
2228 * one byte short. I believe only older clients (OS/2 Win9x) use
2229 * this call so try fixing this by adding a terminating null to
2230 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2232 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2233 SCVAL(pdata,l2_vol_cch,len);
2234 data_len = l2_vol_szVolLabel + len;
2235 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2236 (unsigned)st.st_ctime, len, vname));
2237 break;
2239 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2240 case SMB_FS_ATTRIBUTE_INFORMATION:
2243 #if defined(HAVE_SYS_QUOTAS)
2244 quota_flag = FILE_VOLUME_QUOTAS;
2245 #endif
2247 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2248 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2249 quota_flag); /* FS ATTRIBUTES */
2251 SIVAL(pdata,4,255); /* Max filename component length */
2252 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2253 and will think we can't do long filenames */
2254 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2255 SIVAL(pdata,8,len);
2256 data_len = 12 + len;
2257 break;
2259 case SMB_QUERY_FS_LABEL_INFO:
2260 case SMB_FS_LABEL_INFORMATION:
2261 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2262 data_len = 4 + len;
2263 SIVAL(pdata,0,len);
2264 break;
2266 case SMB_QUERY_FS_VOLUME_INFO:
2267 case SMB_FS_VOLUME_INFORMATION:
2270 * Add volume serial number - hash of a combination of
2271 * the called hostname and the service name.
2273 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2274 (str_checksum(get_local_machine_name())<<16));
2276 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2277 SIVAL(pdata,12,len);
2278 data_len = 18+len;
2279 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2280 (int)strlen(vname),vname, lp_servicename(snum)));
2281 break;
2283 case SMB_QUERY_FS_SIZE_INFO:
2284 case SMB_FS_SIZE_INFORMATION:
2286 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2287 data_len = 24;
2288 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2289 return(UNIXERROR(ERRHRD,ERRgeneral));
2291 block_size = lp_block_size(snum);
2292 if (bsize < block_size) {
2293 SMB_BIG_UINT factor = block_size/bsize;
2294 bsize = block_size;
2295 dsize /= factor;
2296 dfree /= factor;
2298 if (bsize > block_size) {
2299 SMB_BIG_UINT factor = bsize/block_size;
2300 bsize = block_size;
2301 dsize *= factor;
2302 dfree *= factor;
2304 bytes_per_sector = 512;
2305 sectors_per_unit = bsize/bytes_per_sector;
2306 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2307 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2308 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2309 SBIG_UINT(pdata,0,dsize);
2310 SBIG_UINT(pdata,8,dfree);
2311 SIVAL(pdata,16,sectors_per_unit);
2312 SIVAL(pdata,20,bytes_per_sector);
2313 break;
2316 case SMB_FS_FULL_SIZE_INFORMATION:
2318 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2319 data_len = 32;
2320 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2321 return(UNIXERROR(ERRHRD,ERRgeneral));
2323 block_size = lp_block_size(snum);
2324 if (bsize < block_size) {
2325 SMB_BIG_UINT factor = block_size/bsize;
2326 bsize = block_size;
2327 dsize /= factor;
2328 dfree /= factor;
2330 if (bsize > block_size) {
2331 SMB_BIG_UINT factor = bsize/block_size;
2332 bsize = block_size;
2333 dsize *= factor;
2334 dfree *= factor;
2336 bytes_per_sector = 512;
2337 sectors_per_unit = bsize/bytes_per_sector;
2338 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2339 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2340 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2341 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2342 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2343 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2344 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2345 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2346 break;
2349 case SMB_QUERY_FS_DEVICE_INFO:
2350 case SMB_FS_DEVICE_INFORMATION:
2351 data_len = 8;
2352 SIVAL(pdata,0,0); /* dev type */
2353 SIVAL(pdata,4,0); /* characteristics */
2354 break;
2356 #ifdef HAVE_SYS_QUOTAS
2357 case SMB_FS_QUOTA_INFORMATION:
2359 * what we have to send --metze:
2361 * Unknown1: 24 NULL bytes
2362 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2363 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2364 * Quota Flags: 2 byte :
2365 * Unknown3: 6 NULL bytes
2367 * 48 bytes total
2369 * details for Quota Flags:
2371 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2372 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2373 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2374 * 0x0001 Enable Quotas: enable quota for this fs
2378 /* we need to fake up a fsp here,
2379 * because its not send in this call
2381 files_struct fsp;
2382 SMB_NTQUOTA_STRUCT quotas;
2384 ZERO_STRUCT(fsp);
2385 ZERO_STRUCT(quotas);
2387 fsp.conn = conn;
2388 fsp.fnum = -1;
2390 /* access check */
2391 if (current_user.ut.uid != 0) {
2392 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2393 lp_servicename(SNUM(conn)),conn->user));
2394 return ERROR_DOS(ERRDOS,ERRnoaccess);
2397 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2398 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2399 return ERROR_DOS(ERRSRV,ERRerror);
2402 data_len = 48;
2404 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2406 /* Unknown1 24 NULL bytes*/
2407 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2408 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2409 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2411 /* Default Soft Quota 8 bytes */
2412 SBIG_UINT(pdata,24,quotas.softlim);
2414 /* Default Hard Quota 8 bytes */
2415 SBIG_UINT(pdata,32,quotas.hardlim);
2417 /* Quota flag 2 bytes */
2418 SSVAL(pdata,40,quotas.qflags);
2420 /* Unknown3 6 NULL bytes */
2421 SSVAL(pdata,42,0);
2422 SIVAL(pdata,44,0);
2424 break;
2426 #endif /* HAVE_SYS_QUOTAS */
2427 case SMB_FS_OBJECTID_INFORMATION:
2428 data_len = 64;
2429 break;
2432 * Query the version and capabilities of the CIFS UNIX extensions
2433 * in use.
2436 case SMB_QUERY_CIFS_UNIX_INFO:
2437 if (!lp_unix_extensions()) {
2438 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2440 data_len = 12;
2441 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2442 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2443 /* We have POSIX ACLs, pathname and locking capability. */
2444 #if defined(DEVELOPER) /* Not quite finished yet... */
2445 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2446 CIFS_UNIX_POSIX_ACLS_CAP|
2447 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2448 CIFS_UNIX_FCNTL_LOCKS_CAP)));
2449 #else
2450 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2451 CIFS_UNIX_POSIX_ACLS_CAP|
2452 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2453 0)));
2454 #endif
2455 break;
2457 case SMB_QUERY_POSIX_FS_INFO:
2459 int rc;
2460 vfs_statvfs_struct svfs;
2462 if (!lp_unix_extensions()) {
2463 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2466 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2468 if (!rc) {
2469 data_len = 56;
2470 SIVAL(pdata,0,svfs.OptimalTransferSize);
2471 SIVAL(pdata,4,svfs.BlockSize);
2472 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2473 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2474 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2475 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2476 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2477 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2478 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2479 #ifdef EOPNOTSUPP
2480 } else if (rc == EOPNOTSUPP) {
2481 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2482 #endif /* EOPNOTSUPP */
2483 } else {
2484 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2485 return ERROR_DOS(ERRSRV,ERRerror);
2487 break;
2490 case SMB_MAC_QUERY_FS_INFO:
2492 * Thursby MAC extension... ONLY on NTFS filesystems
2493 * once we do streams then we don't need this
2495 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2496 data_len = 88;
2497 SIVAL(pdata,84,0x100); /* Don't support mac... */
2498 break;
2500 /* drop through */
2501 default:
2502 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2506 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2508 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2510 return -1;
2513 /****************************************************************************
2514 Reply to a TRANS2_SETFSINFO (set filesystem info).
2515 ****************************************************************************/
2517 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2518 char **pparams, int total_params, char **ppdata, int total_data,
2519 unsigned int max_data_bytes)
2521 char *pdata = *ppdata;
2522 char *params = *pparams;
2523 uint16 info_level;
2524 int outsize;
2526 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2528 /* */
2529 if (total_params < 4) {
2530 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2531 total_params));
2532 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2535 info_level = SVAL(params,2);
2537 switch(info_level) {
2538 case SMB_SET_CIFS_UNIX_INFO:
2540 uint16 client_unix_major;
2541 uint16 client_unix_minor;
2542 uint32 client_unix_cap_low;
2543 uint32 client_unix_cap_high;
2545 if (!lp_unix_extensions()) {
2546 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2549 /* There should be 12 bytes of capabilities set. */
2550 if (total_data < 8) {
2551 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2553 client_unix_major = SVAL(pdata,0);
2554 client_unix_minor = SVAL(pdata,2);
2555 client_unix_cap_low = IVAL(pdata,4);
2556 client_unix_cap_high = IVAL(pdata,8);
2557 /* Just print these values for now. */
2558 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2559 cap_low = 0x%x, cap_high = 0x%x\n",
2560 (unsigned int)client_unix_major,
2561 (unsigned int)client_unix_minor,
2562 (unsigned int)client_unix_cap_low,
2563 (unsigned int)client_unix_cap_high ));
2565 /* Here is where we must switch to posix pathname processing... */
2566 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2567 lp_set_posix_pathnames();
2568 mangle_change_to_posix();
2570 #if defined(DEVELOPER)
2571 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2572 lp_set_posix_cifsx_locktype(POSIX_LOCK);
2574 #endif
2575 break;
2577 case SMB_FS_QUOTA_INFORMATION:
2579 files_struct *fsp = NULL;
2580 SMB_NTQUOTA_STRUCT quotas;
2582 ZERO_STRUCT(quotas);
2584 /* access check */
2585 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2586 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2587 lp_servicename(SNUM(conn)),conn->user));
2588 return ERROR_DOS(ERRSRV,ERRaccess);
2591 /* note: normaly there're 48 bytes,
2592 * but we didn't use the last 6 bytes for now
2593 * --metze
2595 fsp = file_fsp(params,0);
2596 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2597 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2598 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2601 if (total_data < 42) {
2602 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2603 total_data));
2604 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2607 /* unknown_1 24 NULL bytes in pdata*/
2609 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2610 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2611 #ifdef LARGE_SMB_OFF_T
2612 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2613 #else /* LARGE_SMB_OFF_T */
2614 if ((IVAL(pdata,28) != 0)&&
2615 ((quotas.softlim != 0xFFFFFFFF)||
2616 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2617 /* more than 32 bits? */
2618 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2620 #endif /* LARGE_SMB_OFF_T */
2622 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2623 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2624 #ifdef LARGE_SMB_OFF_T
2625 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2626 #else /* LARGE_SMB_OFF_T */
2627 if ((IVAL(pdata,36) != 0)&&
2628 ((quotas.hardlim != 0xFFFFFFFF)||
2629 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2630 /* more than 32 bits? */
2631 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2633 #endif /* LARGE_SMB_OFF_T */
2635 /* quota_flags 2 bytes **/
2636 quotas.qflags = SVAL(pdata,40);
2638 /* unknown_2 6 NULL bytes follow*/
2640 /* now set the quotas */
2641 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2642 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2643 return ERROR_DOS(ERRSRV,ERRerror);
2646 break;
2648 default:
2649 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2650 info_level));
2651 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2652 break;
2656 * sending this reply works fine,
2657 * but I'm not sure it's the same
2658 * like windows do...
2659 * --metze
2661 outsize = set_message(outbuf,10,0,True);
2663 return outsize;
2666 /****************************************************************************
2667 Utility function to set bad path error.
2668 ****************************************************************************/
2670 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2672 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2673 err, (int)bad_path ));
2675 if(err == ENOENT) {
2676 if (bad_path) {
2677 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2678 } else {
2679 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2682 return UNIXERROR(def_class,def_code);
2685 #if defined(HAVE_POSIX_ACLS)
2686 /****************************************************************************
2687 Utility function to count the number of entries in a POSIX acl.
2688 ****************************************************************************/
2690 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2692 unsigned int ace_count = 0;
2693 int entry_id = SMB_ACL_FIRST_ENTRY;
2694 SMB_ACL_ENTRY_T entry;
2696 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2697 /* get_next... */
2698 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2699 entry_id = SMB_ACL_NEXT_ENTRY;
2701 ace_count++;
2703 return ace_count;
2706 /****************************************************************************
2707 Utility function to marshall a POSIX acl into wire format.
2708 ****************************************************************************/
2710 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2712 int entry_id = SMB_ACL_FIRST_ENTRY;
2713 SMB_ACL_ENTRY_T entry;
2715 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2716 SMB_ACL_TAG_T tagtype;
2717 SMB_ACL_PERMSET_T permset;
2718 unsigned char perms = 0;
2719 unsigned int own_grp;
2721 /* get_next... */
2722 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2723 entry_id = SMB_ACL_NEXT_ENTRY;
2726 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2727 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2728 return False;
2731 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2732 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2733 return False;
2736 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2737 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2738 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2740 SCVAL(pdata,1,perms);
2742 switch (tagtype) {
2743 case SMB_ACL_USER_OBJ:
2744 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2745 own_grp = (unsigned int)pst->st_uid;
2746 SIVAL(pdata,2,own_grp);
2747 SIVAL(pdata,6,0);
2748 break;
2749 case SMB_ACL_USER:
2751 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2752 if (!puid) {
2753 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2755 own_grp = (unsigned int)*puid;
2756 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2757 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2758 SIVAL(pdata,2,own_grp);
2759 SIVAL(pdata,6,0);
2760 break;
2762 case SMB_ACL_GROUP_OBJ:
2763 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2764 own_grp = (unsigned int)pst->st_gid;
2765 SIVAL(pdata,2,own_grp);
2766 SIVAL(pdata,6,0);
2767 break;
2768 case SMB_ACL_GROUP:
2770 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2771 if (!pgid) {
2772 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2774 own_grp = (unsigned int)*pgid;
2775 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2776 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2777 SIVAL(pdata,2,own_grp);
2778 SIVAL(pdata,6,0);
2779 break;
2781 case SMB_ACL_MASK:
2782 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2783 SIVAL(pdata,2,0xFFFFFFFF);
2784 SIVAL(pdata,6,0xFFFFFFFF);
2785 break;
2786 case SMB_ACL_OTHER:
2787 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2788 SIVAL(pdata,2,0xFFFFFFFF);
2789 SIVAL(pdata,6,0xFFFFFFFF);
2790 break;
2791 default:
2792 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2793 return False;
2795 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2798 return True;
2800 #endif
2802 /****************************************************************************
2803 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2804 file name or file id).
2805 ****************************************************************************/
2807 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2808 unsigned int tran_call,
2809 char **pparams, int total_params, char **ppdata, int total_data,
2810 unsigned int max_data_bytes)
2812 char *params = *pparams;
2813 char *pdata = *ppdata;
2814 uint16 info_level;
2815 int mode=0;
2816 int nlink;
2817 SMB_OFF_T file_size=0;
2818 SMB_BIG_UINT allocation_size=0;
2819 unsigned int data_size = 0;
2820 unsigned int param_size = 2;
2821 SMB_STRUCT_STAT sbuf;
2822 pstring fname, dos_fname;
2823 char *fullpathname;
2824 char *base_name;
2825 char *p;
2826 SMB_OFF_T pos = 0;
2827 BOOL bad_path = False;
2828 BOOL delete_pending = False;
2829 int len;
2830 time_t c_time;
2831 files_struct *fsp = NULL;
2832 TALLOC_CTX *data_ctx = NULL;
2833 struct ea_list *ea_list = NULL;
2834 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2835 #if defined(DEVELOPER)
2836 char *lock_data = NULL;
2837 #endif
2839 if (!params)
2840 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2842 ZERO_STRUCT(sbuf);
2844 if (tran_call == TRANSACT2_QFILEINFO) {
2845 if (total_params < 4) {
2846 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2849 fsp = file_fsp(params,0);
2850 info_level = SVAL(params,2);
2852 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2854 if(fsp && (fsp->fake_file_handle)) {
2856 * This is actually for the QUOTA_FAKE_FILE --metze
2859 pstrcpy(fname, fsp->fsp_name);
2860 /* We know this name is ok, it's already passed the checks. */
2862 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2864 * This is actually a QFILEINFO on a directory
2865 * handle (returned from an NT SMB). NT5.0 seems
2866 * to do this call. JRA.
2868 /* We know this name is ok, it's already passed the checks. */
2869 pstrcpy(fname, fsp->fsp_name);
2871 if (INFO_LEVEL_IS_UNIX(info_level)) {
2872 /* Always do lstat for UNIX calls. */
2873 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2874 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2875 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2877 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2878 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2879 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2882 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2883 } else {
2885 * Original code - this is an open file.
2887 CHECK_FSP(fsp,conn);
2889 pstrcpy(fname, fsp->fsp_name);
2890 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2891 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2892 return(UNIXERROR(ERRDOS,ERRbadfid));
2894 pos = fsp->fh->position_information;
2895 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2896 access_mask = fsp->access_mask;
2898 } else {
2899 NTSTATUS status = NT_STATUS_OK;
2901 /* qpathinfo */
2902 if (total_params < 6) {
2903 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2906 info_level = SVAL(params,0);
2908 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2910 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2911 if (!NT_STATUS_IS_OK(status)) {
2912 return ERROR_NT(status);
2915 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2917 unix_convert(fname,conn,0,&bad_path,&sbuf);
2918 if (bad_path) {
2919 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2921 if (!check_name(fname,conn)) {
2922 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2923 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2926 if (INFO_LEVEL_IS_UNIX(info_level)) {
2927 /* Always do lstat for UNIX calls. */
2928 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2929 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2930 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2932 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2933 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2934 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2937 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2938 if (delete_pending) {
2939 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2943 nlink = sbuf.st_nlink;
2945 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2946 /* NTFS does not seem to count ".." */
2947 nlink -= 1;
2950 if ((nlink > 0) && delete_pending) {
2951 nlink -= 1;
2954 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2955 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2958 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2959 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2961 p = strrchr_m(fname,'/');
2962 if (!p)
2963 base_name = fname;
2964 else
2965 base_name = p+1;
2967 mode = dos_mode(conn,fname,&sbuf);
2968 if (!mode)
2969 mode = FILE_ATTRIBUTE_NORMAL;
2971 fullpathname = fname;
2972 if (!(mode & aDIR))
2973 file_size = get_file_size(sbuf);
2975 /* Pull out any data sent here before we realloc. */
2976 switch (info_level) {
2977 case SMB_INFO_QUERY_EAS_FROM_LIST:
2979 /* Pull any EA list from the data portion. */
2980 uint32 ea_size;
2982 if (total_data < 4) {
2983 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2985 ea_size = IVAL(pdata,0);
2987 if (total_data > 0 && ea_size != total_data) {
2988 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2989 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2990 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2993 if (!lp_ea_support(SNUM(conn))) {
2994 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2997 if ((data_ctx = talloc_init("ea_list")) == NULL) {
2998 return ERROR_NT(NT_STATUS_NO_MEMORY);
3001 /* Pull out the list of names. */
3002 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3003 if (!ea_list) {
3004 talloc_destroy(data_ctx);
3005 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3007 break;
3009 #if defined(DEVELOPER)
3010 case SMB_QUERY_POSIX_LOCK:
3012 if (fsp == NULL || fsp->fh->fd == -1) {
3013 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3016 if (total_data != POSIX_LOCK_DATA_SIZE) {
3017 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3020 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3021 return ERROR_NT(NT_STATUS_NO_MEMORY);
3024 /* Copy the lock range data. */
3025 lock_data = talloc_memdup(data_ctx, pdata, total_data);
3026 if (!lock_data) {
3027 talloc_destroy(data_ctx);
3028 return ERROR_NT(NT_STATUS_NO_MEMORY);
3031 #endif
3032 default:
3033 break;
3036 *pparams = SMB_REALLOC(*pparams,2);
3037 if (*pparams == NULL) {
3038 talloc_destroy(data_ctx);
3039 return ERROR_NT(NT_STATUS_NO_MEMORY);
3041 params = *pparams;
3042 SSVAL(params,0,0);
3043 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3044 *ppdata = SMB_REALLOC(*ppdata, data_size);
3045 if (*ppdata == NULL ) {
3046 talloc_destroy(data_ctx);
3047 return ERROR_NT(NT_STATUS_NO_MEMORY);
3049 pdata = *ppdata;
3051 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3053 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3055 if (fsp) {
3056 if (fsp->pending_modtime) {
3057 /* the pending modtime overrides the current modtime */
3058 sbuf.st_mtime = fsp->pending_modtime;
3060 } else {
3061 /* Do we have this path open ? */
3062 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3063 if (fsp1 && fsp1->pending_modtime) {
3064 /* the pending modtime overrides the current modtime */
3065 sbuf.st_mtime = fsp1->pending_modtime;
3067 if (fsp1 && fsp1->initial_allocation_size) {
3068 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3072 if (lp_dos_filetime_resolution(SNUM(conn))) {
3073 c_time &= ~1;
3074 sbuf.st_atime &= ~1;
3075 sbuf.st_ctime &= ~1;
3076 sbuf.st_mtime &= ~1;
3079 /* NT expects the name to be in an exact form of the *full*
3080 filename. See the trans2 torture test */
3081 if (strequal(base_name,".")) {
3082 pstrcpy(dos_fname, "\\");
3083 } else {
3084 pstr_sprintf(dos_fname, "\\%s", fname);
3085 string_replace(dos_fname, '/', '\\');
3088 switch (info_level) {
3089 case SMB_INFO_STANDARD:
3090 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3091 data_size = 22;
3092 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3093 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3094 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3095 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3096 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3097 SSVAL(pdata,l1_attrFile,mode);
3098 break;
3100 case SMB_INFO_QUERY_EA_SIZE:
3102 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3103 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3104 data_size = 26;
3105 srv_put_dos_date2(pdata,0,c_time);
3106 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3107 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3108 SIVAL(pdata,12,(uint32)file_size);
3109 SIVAL(pdata,16,(uint32)allocation_size);
3110 SSVAL(pdata,20,mode);
3111 SIVAL(pdata,22,ea_size);
3112 break;
3115 case SMB_INFO_IS_NAME_VALID:
3116 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3117 if (tran_call == TRANSACT2_QFILEINFO) {
3118 /* os/2 needs this ? really ?*/
3119 return ERROR_DOS(ERRDOS,ERRbadfunc);
3121 data_size = 0;
3122 param_size = 0;
3123 break;
3125 case SMB_INFO_QUERY_EAS_FROM_LIST:
3127 size_t total_ea_len = 0;
3128 struct ea_list *ea_file_list = NULL;
3130 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3132 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3133 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3135 if (!ea_list || (total_ea_len > data_size)) {
3136 talloc_destroy(data_ctx);
3137 data_size = 4;
3138 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3139 break;
3142 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3143 talloc_destroy(data_ctx);
3144 break;
3147 case SMB_INFO_QUERY_ALL_EAS:
3149 /* We have data_size bytes to put EA's into. */
3150 size_t total_ea_len = 0;
3152 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3154 data_ctx = talloc_init("ea_ctx");
3155 if (!data_ctx) {
3156 return ERROR_NT(NT_STATUS_NO_MEMORY);
3159 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3160 if (!ea_list || (total_ea_len > data_size)) {
3161 talloc_destroy(data_ctx);
3162 data_size = 4;
3163 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3164 break;
3167 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3168 talloc_destroy(data_ctx);
3169 break;
3172 case SMB_FILE_BASIC_INFORMATION:
3173 case SMB_QUERY_FILE_BASIC_INFO:
3175 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3176 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3177 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3178 } else {
3179 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3180 data_size = 40;
3181 SIVAL(pdata,36,0);
3183 put_long_date(pdata,c_time);
3184 put_long_date(pdata+8,sbuf.st_atime);
3185 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3186 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3187 SIVAL(pdata,32,mode);
3189 DEBUG(5,("SMB_QFBI - "));
3191 time_t create_time = c_time;
3192 DEBUG(5,("create: %s ", ctime(&create_time)));
3194 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3195 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3196 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3197 DEBUG(5,("mode: %x\n", mode));
3198 break;
3200 case SMB_FILE_STANDARD_INFORMATION:
3201 case SMB_QUERY_FILE_STANDARD_INFO:
3203 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3204 data_size = 24;
3205 SOFF_T(pdata,0,allocation_size);
3206 SOFF_T(pdata,8,file_size);
3207 SIVAL(pdata,16,nlink);
3208 SCVAL(pdata,20,delete_pending?1:0);
3209 SCVAL(pdata,21,(mode&aDIR)?1:0);
3210 SSVAL(pdata,22,0); /* Padding. */
3211 break;
3213 case SMB_FILE_EA_INFORMATION:
3214 case SMB_QUERY_FILE_EA_INFO:
3216 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3217 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3218 data_size = 4;
3219 SIVAL(pdata,0,ea_size);
3220 break;
3223 /* Get the 8.3 name - used if NT SMB was negotiated. */
3224 case SMB_QUERY_FILE_ALT_NAME_INFO:
3225 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3227 pstring short_name;
3229 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3230 pstrcpy(short_name,base_name);
3231 /* Mangle if not already 8.3 */
3232 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3233 mangle_map(short_name,True,True,SNUM(conn));
3235 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3236 data_size = 4 + len;
3237 SIVAL(pdata,0,len);
3238 break;
3241 case SMB_QUERY_FILE_NAME_INFO:
3243 this must be *exactly* right for ACLs on mapped drives to work
3245 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3246 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3247 data_size = 4 + len;
3248 SIVAL(pdata,0,len);
3249 break;
3251 case SMB_FILE_ALLOCATION_INFORMATION:
3252 case SMB_QUERY_FILE_ALLOCATION_INFO:
3253 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3254 data_size = 8;
3255 SOFF_T(pdata,0,allocation_size);
3256 break;
3258 case SMB_FILE_END_OF_FILE_INFORMATION:
3259 case SMB_QUERY_FILE_END_OF_FILEINFO:
3260 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3261 data_size = 8;
3262 SOFF_T(pdata,0,file_size);
3263 break;
3265 case SMB_QUERY_FILE_ALL_INFO:
3266 case SMB_FILE_ALL_INFORMATION:
3268 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3269 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3270 put_long_date(pdata,c_time);
3271 put_long_date(pdata+8,sbuf.st_atime);
3272 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3273 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3274 SIVAL(pdata,32,mode);
3275 SIVAL(pdata,36,0); /* padding. */
3276 pdata += 40;
3277 SOFF_T(pdata,0,allocation_size);
3278 SOFF_T(pdata,8,file_size);
3279 SIVAL(pdata,16,nlink);
3280 SCVAL(pdata,20,delete_pending);
3281 SCVAL(pdata,21,(mode&aDIR)?1:0);
3282 SSVAL(pdata,22,0);
3283 pdata += 24;
3284 SIVAL(pdata,0,ea_size);
3285 pdata += 4; /* EA info */
3286 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3287 SIVAL(pdata,0,len);
3288 pdata += 4 + len;
3289 data_size = PTR_DIFF(pdata,(*ppdata));
3290 break;
3292 case SMB_FILE_INTERNAL_INFORMATION:
3293 /* This should be an index number - looks like
3294 dev/ino to me :-)
3296 I think this causes us to fail the IFSKIT
3297 BasicFileInformationTest. -tpot */
3299 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3300 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3301 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3302 data_size = 8;
3303 break;
3305 case SMB_FILE_ACCESS_INFORMATION:
3306 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3307 SIVAL(pdata,0,access_mask);
3308 data_size = 4;
3309 break;
3311 case SMB_FILE_NAME_INFORMATION:
3312 /* Pathname with leading '\'. */
3314 size_t byte_len;
3315 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3316 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3317 SIVAL(pdata,0,byte_len);
3318 data_size = 4 + byte_len;
3319 break;
3322 case SMB_FILE_DISPOSITION_INFORMATION:
3323 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3324 data_size = 1;
3325 SCVAL(pdata,0,delete_pending);
3326 break;
3328 case SMB_FILE_POSITION_INFORMATION:
3329 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3330 data_size = 8;
3331 SOFF_T(pdata,0,pos);
3332 break;
3334 case SMB_FILE_MODE_INFORMATION:
3335 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3336 SIVAL(pdata,0,mode);
3337 data_size = 4;
3338 break;
3340 case SMB_FILE_ALIGNMENT_INFORMATION:
3341 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3342 SIVAL(pdata,0,0); /* No alignment needed. */
3343 data_size = 4;
3344 break;
3346 #if 0
3348 * NT4 server just returns "invalid query" to this - if we try to answer
3349 * it then NTws gets a BSOD! (tridge).
3350 * W2K seems to want this. JRA.
3352 case SMB_QUERY_FILE_STREAM_INFO:
3353 #endif
3354 case SMB_FILE_STREAM_INFORMATION:
3355 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3356 if (mode & aDIR) {
3357 data_size = 0;
3358 } else {
3359 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3360 SIVAL(pdata,0,0); /* ??? */
3361 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3362 SOFF_T(pdata,8,file_size);
3363 SIVAL(pdata,16,allocation_size);
3364 SIVAL(pdata,20,0); /* ??? */
3365 data_size = 24 + byte_len;
3367 break;
3369 case SMB_QUERY_COMPRESSION_INFO:
3370 case SMB_FILE_COMPRESSION_INFORMATION:
3371 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3372 SOFF_T(pdata,0,file_size);
3373 SIVAL(pdata,8,0); /* ??? */
3374 SIVAL(pdata,12,0); /* ??? */
3375 data_size = 16;
3376 break;
3378 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3379 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3380 put_long_date(pdata,c_time);
3381 put_long_date(pdata+8,sbuf.st_atime);
3382 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3383 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3384 SIVAL(pdata,32,allocation_size);
3385 SOFF_T(pdata,40,file_size);
3386 SIVAL(pdata,48,mode);
3387 SIVAL(pdata,52,0); /* ??? */
3388 data_size = 56;
3389 break;
3391 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3392 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3393 SIVAL(pdata,0,mode);
3394 SIVAL(pdata,4,0);
3395 data_size = 8;
3396 break;
3399 * CIFS UNIX Extensions.
3402 case SMB_QUERY_FILE_UNIX_BASIC:
3404 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3405 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3407 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3408 pdata += 8;
3410 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3411 pdata += 8;
3413 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3414 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3415 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3416 pdata += 24;
3418 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3419 SIVAL(pdata,4,0);
3420 pdata += 8;
3422 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3423 SIVAL(pdata,4,0);
3424 pdata += 8;
3426 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3427 pdata += 4;
3429 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3430 SIVAL(pdata,4,0);
3431 pdata += 8;
3433 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3434 SIVAL(pdata,4,0);
3435 pdata += 8;
3437 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3438 pdata += 8;
3440 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3441 SIVAL(pdata,4,0);
3442 pdata += 8;
3444 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3445 SIVAL(pdata,4,0);
3446 pdata += 8;
3447 data_size = PTR_DIFF(pdata,(*ppdata));
3450 int i;
3451 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3453 for (i=0; i<100; i++)
3454 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3455 DEBUG(4,("\n"));
3458 break;
3460 case SMB_QUERY_FILE_UNIX_LINK:
3462 pstring buffer;
3464 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3465 #ifdef S_ISLNK
3466 if(!S_ISLNK(sbuf.st_mode))
3467 return(UNIXERROR(ERRSRV,ERRbadlink));
3468 #else
3469 return(UNIXERROR(ERRDOS,ERRbadlink));
3470 #endif
3471 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3472 if (len == -1)
3473 return(UNIXERROR(ERRDOS,ERRnoaccess));
3474 buffer[len] = 0;
3475 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3476 pdata += len;
3477 data_size = PTR_DIFF(pdata,(*ppdata));
3479 break;
3482 #if defined(HAVE_POSIX_ACLS)
3483 case SMB_QUERY_POSIX_ACL:
3485 SMB_ACL_T file_acl = NULL;
3486 SMB_ACL_T def_acl = NULL;
3487 uint16 num_file_acls = 0;
3488 uint16 num_def_acls = 0;
3490 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3491 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3492 } else {
3493 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3496 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3497 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3498 fname ));
3499 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3502 if (S_ISDIR(sbuf.st_mode)) {
3503 if (fsp && fsp->is_directory) {
3504 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3505 } else {
3506 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3508 def_acl = free_empty_sys_acl(conn, def_acl);
3511 num_file_acls = count_acl_entries(conn, file_acl);
3512 num_def_acls = count_acl_entries(conn, def_acl);
3514 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3515 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3516 data_size,
3517 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3518 SMB_POSIX_ACL_HEADER_SIZE) ));
3519 if (file_acl) {
3520 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3522 if (def_acl) {
3523 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3525 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3528 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3529 SSVAL(pdata,2,num_file_acls);
3530 SSVAL(pdata,4,num_def_acls);
3531 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3532 if (file_acl) {
3533 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3535 if (def_acl) {
3536 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3538 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3540 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3541 if (file_acl) {
3542 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3544 if (def_acl) {
3545 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3547 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3550 if (file_acl) {
3551 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3553 if (def_acl) {
3554 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3556 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3557 break;
3559 #endif
3562 #if defined(DEVELOPER)
3563 case SMB_QUERY_POSIX_LOCK:
3565 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3566 SMB_BIG_UINT count;
3567 SMB_BIG_UINT offset;
3568 uint16 lock_pid;
3569 enum brl_type lock_type;
3571 if (total_data != POSIX_LOCK_DATA_SIZE) {
3572 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3575 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3576 case POSIX_LOCK_TYPE_READ:
3577 lock_type = READ_LOCK;
3578 break;
3579 case POSIX_LOCK_TYPE_WRITE:
3580 lock_type = WRITE_LOCK;
3581 break;
3582 case POSIX_LOCK_TYPE_UNLOCK:
3583 default:
3584 /* There's no point in asking for an unlock... */
3585 talloc_destroy(data_ctx);
3586 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3589 lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3590 #if defined(HAVE_LONGLONG)
3591 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3592 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3593 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3594 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3595 #else /* HAVE_LONGLONG */
3596 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3597 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3598 #endif /* HAVE_LONGLONG */
3600 status = query_lock(fsp,
3601 &lock_pid,
3602 &count,
3603 &offset,
3604 &lock_type,
3605 POSIX_LOCK);
3607 if (ERROR_WAS_LOCK_DENIED(status)) {
3608 /* Here we need to report who has it locked... */
3609 data_size = POSIX_LOCK_DATA_SIZE;
3611 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3612 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3613 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3614 #if defined(HAVE_LONGLONG)
3615 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3616 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3617 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3618 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3619 #else /* HAVE_LONGLONG */
3620 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3621 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3622 #endif /* HAVE_LONGLONG */
3624 } else if (NT_STATUS_IS_OK(status)) {
3625 /* For success we just return a copy of what we sent
3626 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3627 data_size = POSIX_LOCK_DATA_SIZE;
3628 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3629 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3630 } else {
3631 return ERROR_NT(status);
3633 break;
3635 #endif
3637 default:
3638 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3641 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3643 return(-1);
3646 /****************************************************************************
3647 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3648 code.
3649 ****************************************************************************/
3651 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3653 BOOL bad_path_oldname = False;
3654 BOOL bad_path_newname = False;
3655 SMB_STRUCT_STAT sbuf1, sbuf2;
3656 pstring last_component_oldname;
3657 pstring last_component_newname;
3658 NTSTATUS status = NT_STATUS_OK;
3660 ZERO_STRUCT(sbuf1);
3661 ZERO_STRUCT(sbuf2);
3663 /* No wildcards. */
3664 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3665 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3668 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3669 if (bad_path_oldname) {
3670 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3673 /* Quick check for "." and ".." */
3674 if (last_component_oldname[0] == '.') {
3675 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3676 return NT_STATUS_OBJECT_NAME_INVALID;
3680 /* source must already exist. */
3681 if (!VALID_STAT(sbuf1)) {
3682 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3685 if (!check_name(oldname,conn)) {
3686 return NT_STATUS_ACCESS_DENIED;
3689 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3690 if (bad_path_newname) {
3691 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3694 /* Quick check for "." and ".." */
3695 if (last_component_newname[0] == '.') {
3696 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3697 return NT_STATUS_OBJECT_NAME_INVALID;
3701 /* Disallow if newname already exists. */
3702 if (VALID_STAT(sbuf2)) {
3703 return NT_STATUS_OBJECT_NAME_COLLISION;
3706 if (!check_name(newname,conn)) {
3707 return NT_STATUS_ACCESS_DENIED;
3710 /* No links from a directory. */
3711 if (S_ISDIR(sbuf1.st_mode)) {
3712 return NT_STATUS_FILE_IS_A_DIRECTORY;
3715 /* Ensure this is within the share. */
3716 if (!reduce_name(conn, oldname) != 0)
3717 return NT_STATUS_ACCESS_DENIED;
3719 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3721 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3722 status = map_nt_error_from_unix(errno);
3723 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3724 nt_errstr(status), newname, oldname));
3727 return status;
3730 /****************************************************************************
3731 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3732 ****************************************************************************/
3734 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3735 unsigned int tran_call,
3736 char **pparams, int total_params, char **ppdata, int total_data,
3737 unsigned int max_data_bytes)
3739 char *params = *pparams;
3740 char *pdata = *ppdata;
3741 uint16 info_level;
3742 int dosmode=0;
3743 SMB_OFF_T size=0;
3744 struct utimbuf tvs;
3745 SMB_STRUCT_STAT sbuf;
3746 pstring fname;
3747 int fd = -1;
3748 BOOL bad_path = False;
3749 files_struct *fsp = NULL;
3750 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3751 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3752 mode_t unixmode = 0;
3753 NTSTATUS status = NT_STATUS_OK;
3755 if (!params)
3756 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3758 ZERO_STRUCT(sbuf);
3759 ZERO_STRUCT(tvs);
3761 if (tran_call == TRANSACT2_SETFILEINFO) {
3762 if (total_params < 4) {
3763 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3766 fsp = file_fsp(params,0);
3767 info_level = SVAL(params,2);
3769 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3771 * This is actually a SETFILEINFO on a directory
3772 * handle (returned from an NT SMB). NT5.0 seems
3773 * to do this call. JRA.
3775 pstrcpy(fname, fsp->fsp_name);
3776 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3777 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3778 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3780 } else if (fsp && fsp->print_file) {
3782 * Doing a DELETE_ON_CLOSE should cancel a print job.
3784 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3785 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3787 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3789 SSVAL(params,0,0);
3790 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3791 return(-1);
3792 } else
3793 return (UNIXERROR(ERRDOS,ERRbadpath));
3794 } else {
3796 * Original code - this is an open file.
3798 CHECK_FSP(fsp,conn);
3800 pstrcpy(fname, fsp->fsp_name);
3801 fd = fsp->fh->fd;
3803 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3804 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3805 return(UNIXERROR(ERRDOS,ERRbadfid));
3808 } else {
3809 /* set path info */
3810 if (total_params < 6) {
3811 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3814 info_level = SVAL(params,0);
3815 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3816 if (!NT_STATUS_IS_OK(status)) {
3817 return ERROR_NT(status);
3819 unix_convert(fname,conn,0,&bad_path,&sbuf);
3820 if (bad_path) {
3821 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3825 * For CIFS UNIX extensions the target name may not exist.
3828 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3829 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3830 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3833 if(!check_name(fname, conn)) {
3834 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3839 if (!CAN_WRITE(conn))
3840 return ERROR_DOS(ERRSRV,ERRaccess);
3842 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3843 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3846 if (VALID_STAT(sbuf))
3847 unixmode = sbuf.st_mode;
3849 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3850 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3852 /* Realloc the parameter size */
3853 *pparams = SMB_REALLOC(*pparams,2);
3854 if (*pparams == NULL) {
3855 return ERROR_NT(NT_STATUS_NO_MEMORY);
3857 params = *pparams;
3859 SSVAL(params,0,0);
3861 if (fsp && fsp->pending_modtime) {
3862 /* the pending modtime overrides the current modtime */
3863 sbuf.st_mtime = fsp->pending_modtime;
3866 size = get_file_size(sbuf);
3867 tvs.modtime = sbuf.st_mtime;
3868 tvs.actime = sbuf.st_atime;
3869 dosmode = dos_mode(conn,fname,&sbuf);
3870 unixmode = sbuf.st_mode;
3872 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3873 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3875 switch (info_level) {
3876 case SMB_INFO_STANDARD:
3878 if (total_data < 12) {
3879 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3882 /* access time */
3883 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3884 /* write time */
3885 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3886 break;
3889 case SMB_INFO_SET_EA:
3891 struct ea_list *ea_list = NULL;
3892 TALLOC_CTX *ctx = NULL;
3894 if (total_data < 10) {
3896 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3897 length. They seem to have no effect. Bug #3212. JRA */
3899 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3900 /* We're done. We only get EA info in this call. */
3901 SSVAL(params,0,0);
3902 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3903 return(-1);
3906 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3909 if (IVAL(pdata,0) > total_data) {
3910 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3911 IVAL(pdata,0), (unsigned int)total_data));
3912 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3915 ctx = talloc_init("SMB_INFO_SET_EA");
3916 if (!ctx) {
3917 return ERROR_NT(NT_STATUS_NO_MEMORY);
3919 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3920 if (!ea_list) {
3921 talloc_destroy(ctx);
3922 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3924 status = set_ea(conn, fsp, fname, ea_list);
3925 talloc_destroy(ctx);
3927 if (!NT_STATUS_IS_OK(status)) {
3928 return ERROR_NT(status);
3931 /* We're done. We only get EA info in this call. */
3932 SSVAL(params,0,0);
3933 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3934 return(-1);
3937 #if 0
3938 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3939 /* XXXX um, i don't think this is right.
3940 it's also not in the cifs6.txt spec.
3942 case SMB_INFO_QUERY_EAS_FROM_LIST:
3943 if (total_data < 28)
3944 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3946 tvs.actime = make_unix_date2(pdata+8);
3947 tvs.modtime = make_unix_date2(pdata+12);
3948 size = IVAL(pdata,16);
3949 dosmode = IVAL(pdata,24);
3950 break;
3952 /* XXXX nor this. not in cifs6.txt, either. */
3953 case SMB_INFO_QUERY_ALL_EAS:
3954 if (total_data < 28)
3955 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3957 tvs.actime = make_unix_date2(pdata+8);
3958 tvs.modtime = make_unix_date2(pdata+12);
3959 size = IVAL(pdata,16);
3960 dosmode = IVAL(pdata,24);
3961 break;
3962 #endif
3964 case SMB_SET_FILE_BASIC_INFO:
3965 case SMB_FILE_BASIC_INFORMATION:
3967 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3968 time_t write_time;
3969 time_t changed_time;
3971 if (total_data < 36) {
3972 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3975 /* Ignore create time at offset pdata. */
3977 /* access time */
3978 tvs.actime = interpret_long_date(pdata+8);
3980 write_time = interpret_long_date(pdata+16);
3981 changed_time = interpret_long_date(pdata+24);
3983 tvs.modtime = MIN(write_time, changed_time);
3985 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3986 tvs.modtime = write_time;
3988 /* Prefer a defined time to an undefined one. */
3989 if (null_mtime(tvs.modtime)) {
3990 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3993 /* attributes */
3994 dosmode = IVAL(pdata,32);
3995 break;
3998 case SMB_FILE_ALLOCATION_INFORMATION:
3999 case SMB_SET_FILE_ALLOCATION_INFO:
4001 int ret = -1;
4002 SMB_BIG_UINT allocation_size;
4004 if (total_data < 8) {
4005 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4008 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4009 #ifdef LARGE_SMB_OFF_T
4010 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4011 #else /* LARGE_SMB_OFF_T */
4012 if (IVAL(pdata,4) != 0) {
4013 /* more than 32 bits? */
4014 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4016 #endif /* LARGE_SMB_OFF_T */
4017 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4018 fname, (double)allocation_size ));
4020 if (allocation_size) {
4021 allocation_size = smb_roundup(conn, allocation_size);
4024 if(allocation_size != get_file_size(sbuf)) {
4025 SMB_STRUCT_STAT new_sbuf;
4027 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4028 fname, (double)allocation_size ));
4030 if (fd == -1) {
4031 files_struct *new_fsp = NULL;
4033 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4034 FILE_WRITE_DATA,
4035 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4036 FILE_OPEN,
4038 FILE_ATTRIBUTE_NORMAL,
4039 FORCE_OPLOCK_BREAK_TO_NONE,
4040 NULL);
4042 if (new_fsp == NULL) {
4043 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4044 /* We have re-scheduled this call. */
4045 return -1;
4047 return(UNIXERROR(ERRDOS,ERRnoaccess));
4049 ret = vfs_allocate_file_space(new_fsp, allocation_size);
4050 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4051 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4052 new_fsp->fnum, strerror(errno)));
4053 ret = -1;
4055 close_file(new_fsp,NORMAL_CLOSE);
4056 } else {
4057 ret = vfs_allocate_file_space(fsp, allocation_size);
4058 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4059 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4060 fsp->fnum, strerror(errno)));
4061 ret = -1;
4064 if (ret == -1)
4065 return ERROR_NT(NT_STATUS_DISK_FULL);
4067 /* Allocate can truncate size... */
4068 size = get_file_size(new_sbuf);
4071 break;
4074 case SMB_FILE_END_OF_FILE_INFORMATION:
4075 case SMB_SET_FILE_END_OF_FILE_INFO:
4077 if (total_data < 8) {
4078 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4081 size = IVAL(pdata,0);
4082 #ifdef LARGE_SMB_OFF_T
4083 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4084 #else /* LARGE_SMB_OFF_T */
4085 if (IVAL(pdata,4) != 0) {
4086 /* more than 32 bits? */
4087 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4089 #endif /* LARGE_SMB_OFF_T */
4090 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4091 break;
4094 case SMB_FILE_DISPOSITION_INFORMATION:
4095 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4097 BOOL delete_on_close;
4099 if (total_data < 1) {
4100 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4103 delete_on_close = (CVAL(pdata,0) ? True : False);
4105 /* Just ignore this set on a path. */
4106 if (tran_call != TRANSACT2_SETFILEINFO)
4107 break;
4109 if (fsp == NULL)
4110 return(UNIXERROR(ERRDOS,ERRbadfid));
4112 status = can_set_delete_on_close(fsp, delete_on_close,
4113 dosmode);
4115 if (!NT_STATUS_IS_OK(status)) {
4116 return ERROR_NT(status);
4119 /* The set is across all open files on this dev/inode pair. */
4120 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4121 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4124 SSVAL(params,0,0);
4125 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4126 return(-1);
4129 case SMB_FILE_POSITION_INFORMATION:
4131 SMB_BIG_UINT position_information;
4133 if (total_data < 8) {
4134 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4137 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4138 #ifdef LARGE_SMB_OFF_T
4139 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4140 #else /* LARGE_SMB_OFF_T */
4141 if (IVAL(pdata,4) != 0) {
4142 /* more than 32 bits? */
4143 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4145 #endif /* LARGE_SMB_OFF_T */
4146 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4147 fname, (double)position_information ));
4148 if (fsp) {
4149 fsp->fh->position_information = position_information;
4152 /* We're done. We only get position info in this call. */
4153 SSVAL(params,0,0);
4154 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4155 return(-1);
4158 /* From tridge Samba4 :
4159 * MODE_INFORMATION in setfileinfo (I have no
4160 * idea what "mode information" on a file is - it takes a value of 0,
4161 * 2, 4 or 6. What could it be?).
4164 case SMB_FILE_MODE_INFORMATION:
4166 uint32 mode;
4168 if (total_data < 4) {
4169 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4171 mode = IVAL(pdata,0);
4172 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4173 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4176 /* We're done. We only get mode info in this call. */
4177 SSVAL(params,0,0);
4178 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4179 return(-1);
4183 * CIFS UNIX extensions.
4186 case SMB_SET_FILE_UNIX_BASIC:
4188 uint32 raw_unixmode;
4190 if (total_data < 100) {
4191 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4194 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4195 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4196 size=IVAL(pdata,0); /* first 8 Bytes are size */
4197 #ifdef LARGE_SMB_OFF_T
4198 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4199 #else /* LARGE_SMB_OFF_T */
4200 if (IVAL(pdata,4) != 0) {
4201 /* more than 32 bits? */
4202 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4204 #endif /* LARGE_SMB_OFF_T */
4206 pdata+=24; /* ctime & st_blocks are not changed */
4207 tvs.actime = interpret_long_date(pdata); /* access_time */
4208 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4209 pdata+=16;
4210 set_owner = (uid_t)IVAL(pdata,0);
4211 pdata += 8;
4212 set_grp = (gid_t)IVAL(pdata,0);
4213 pdata += 8;
4214 raw_unixmode = IVAL(pdata,28);
4215 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4216 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4218 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4219 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4220 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4222 if (!VALID_STAT(sbuf)) {
4225 * The only valid use of this is to create character and block
4226 * devices, and named pipes. This is deprecated (IMHO) and
4227 * a new info level should be used for mknod. JRA.
4230 uint32 file_type = IVAL(pdata,0);
4231 #if defined(HAVE_MAKEDEV)
4232 uint32 dev_major = IVAL(pdata,4);
4233 uint32 dev_minor = IVAL(pdata,12);
4234 #endif
4236 uid_t myuid = geteuid();
4237 gid_t mygid = getegid();
4238 SMB_DEV_T dev = (SMB_DEV_T)0;
4240 if (tran_call == TRANSACT2_SETFILEINFO)
4241 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4243 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4244 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4247 #if defined(HAVE_MAKEDEV)
4248 dev = makedev(dev_major, dev_minor);
4249 #endif
4251 /* We can only create as the owner/group we are. */
4253 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4254 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4255 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4256 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4258 switch (file_type) {
4259 #if defined(S_IFIFO)
4260 case UNIX_TYPE_FIFO:
4261 unixmode |= S_IFIFO;
4262 break;
4263 #endif
4264 #if defined(S_IFSOCK)
4265 case UNIX_TYPE_SOCKET:
4266 unixmode |= S_IFSOCK;
4267 break;
4268 #endif
4269 #if defined(S_IFCHR)
4270 case UNIX_TYPE_CHARDEV:
4271 unixmode |= S_IFCHR;
4272 break;
4273 #endif
4274 #if defined(S_IFBLK)
4275 case UNIX_TYPE_BLKDEV:
4276 unixmode |= S_IFBLK;
4277 break;
4278 #endif
4279 default:
4280 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4283 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4284 0%o for file %s\n", (double)dev, unixmode, fname ));
4286 /* Ok - do the mknod. */
4287 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4288 return(UNIXERROR(ERRDOS,ERRnoaccess));
4290 inherit_access_acl(conn, fname, unixmode);
4292 SSVAL(params,0,0);
4293 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4294 return(-1);
4298 * Deal with the UNIX specific mode set.
4301 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4302 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4303 (unsigned int)unixmode, fname ));
4304 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4305 return(UNIXERROR(ERRDOS,ERRnoaccess));
4309 * Deal with the UNIX specific uid set.
4312 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4313 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4314 (unsigned int)set_owner, fname ));
4315 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4316 return(UNIXERROR(ERRDOS,ERRnoaccess));
4320 * Deal with the UNIX specific gid set.
4323 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4324 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4325 (unsigned int)set_owner, fname ));
4326 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4327 return(UNIXERROR(ERRDOS,ERRnoaccess));
4329 break;
4332 case SMB_SET_FILE_UNIX_LINK:
4334 pstring link_target;
4335 char *newname = fname;
4337 /* Set a symbolic link. */
4338 /* Don't allow this if follow links is false. */
4340 if (!lp_symlinks(SNUM(conn)))
4341 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4343 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4345 /* !widelinks forces the target path to be within the share. */
4346 /* This means we can interpret the target as a pathname. */
4347 if (!lp_widelinks(SNUM(conn))) {
4348 pstring rel_name;
4349 char *last_dirp = NULL;
4351 unix_format(link_target);
4352 if (*link_target == '/') {
4353 /* No absolute paths allowed. */
4354 return(UNIXERROR(ERRDOS,ERRnoaccess));
4356 pstrcpy(rel_name, newname);
4357 last_dirp = strrchr_m(rel_name, '/');
4358 if (last_dirp) {
4359 last_dirp[1] = '\0';
4360 } else {
4361 pstrcpy(rel_name, "./");
4363 pstrcat(rel_name, link_target);
4365 if (!check_name(rel_name, conn)) {
4366 return(UNIXERROR(ERRDOS,ERRnoaccess));
4370 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4371 fname, link_target ));
4373 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4374 return(UNIXERROR(ERRDOS,ERRnoaccess));
4375 SSVAL(params,0,0);
4376 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4377 return(-1);
4380 case SMB_SET_FILE_UNIX_HLINK:
4382 pstring oldname;
4383 char *newname = fname;
4385 /* Set a hard link. */
4386 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4387 if (!NT_STATUS_IS_OK(status)) {
4388 return ERROR_NT(status);
4391 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4392 fname, oldname));
4394 status = hardlink_internals(conn, oldname, newname);
4395 if (!NT_STATUS_IS_OK(status)) {
4396 return ERROR_NT(status);
4399 SSVAL(params,0,0);
4400 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4401 return(-1);
4404 case SMB_FILE_RENAME_INFORMATION:
4406 BOOL overwrite;
4407 uint32 root_fid;
4408 uint32 len;
4409 pstring newname;
4410 pstring base_name;
4411 char *p;
4413 if (total_data < 12) {
4414 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4417 overwrite = (CVAL(pdata,0) ? True : False);
4418 root_fid = IVAL(pdata,4);
4419 len = IVAL(pdata,8);
4420 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4421 if (!NT_STATUS_IS_OK(status)) {
4422 return ERROR_NT(status);
4425 /* Check the new name has no '/' characters. */
4426 if (strchr_m(newname, '/'))
4427 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4429 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4431 /* Create the base directory. */
4432 pstrcpy(base_name, fname);
4433 p = strrchr_m(base_name, '/');
4434 if (p)
4435 *p = '\0';
4436 /* Append the new name. */
4437 pstrcat(base_name, "/");
4438 pstrcat(base_name, newname);
4440 if (fsp) {
4441 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4442 fsp->fnum, fsp->fsp_name, base_name ));
4443 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4444 } else {
4445 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4446 fname, newname ));
4447 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4452 /* We have re-scheduled this call. */
4453 return -1;
4455 return ERROR_NT(status);
4458 process_pending_change_notify_queue((time_t)0);
4459 SSVAL(params,0,0);
4460 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4461 return(-1);
4464 #if defined(HAVE_POSIX_ACLS)
4465 case SMB_SET_POSIX_ACL:
4467 uint16 posix_acl_version;
4468 uint16 num_file_acls;
4469 uint16 num_def_acls;
4470 BOOL valid_file_acls = True;
4471 BOOL valid_def_acls = True;
4473 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4474 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4476 posix_acl_version = SVAL(pdata,0);
4477 num_file_acls = SVAL(pdata,2);
4478 num_def_acls = SVAL(pdata,4);
4480 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4481 valid_file_acls = False;
4482 num_file_acls = 0;
4485 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4486 valid_def_acls = False;
4487 num_def_acls = 0;
4490 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4491 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4494 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4495 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4496 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4499 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4500 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4501 return(UNIXERROR(ERRDOS,ERRnoaccess));
4504 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4505 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4506 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4507 return(UNIXERROR(ERRDOS,ERRnoaccess));
4510 SSVAL(params,0,0);
4511 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4512 return(-1);
4514 #endif
4516 #if defined(DEVELOPER)
4517 case SMB_SET_POSIX_LOCK:
4519 SMB_BIG_UINT count;
4520 SMB_BIG_UINT offset;
4521 uint16 lock_pid;
4522 BOOL lock_blocking;
4523 enum brl_type lock_type;
4524 BOOL my_lock_ctx;
4526 if (fsp == NULL || fsp->fh->fd == -1) {
4527 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4530 if (total_data != POSIX_LOCK_DATA_SIZE) {
4531 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4534 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4535 case POSIX_LOCK_TYPE_READ:
4536 lock_type = READ_LOCK;
4537 break;
4538 case POSIX_LOCK_TYPE_WRITE:
4539 /* Return the right POSIX-mappable error code for files opened read-only. */
4540 if (!fsp->can_write) {
4541 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4543 lock_type = WRITE_LOCK;
4544 break;
4545 case POSIX_LOCK_TYPE_UNLOCK:
4546 lock_type = UNLOCK_LOCK;
4547 break;
4548 default:
4549 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4552 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4553 lock_blocking = False;
4554 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4555 lock_blocking = True;
4556 } else {
4557 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4560 lock_pid = (uint16)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4561 #if defined(HAVE_LONGLONG)
4562 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4563 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4564 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4565 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4566 #else /* HAVE_LONGLONG */
4567 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4568 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4569 #endif /* HAVE_LONGLONG */
4571 if (lock_type == UNLOCK_LOCK) {
4572 status = do_unlock(fsp,
4573 lock_pid,
4574 count,
4575 offset,
4576 POSIX_LOCK);
4577 } else {
4578 status = do_lock(fsp,
4579 lock_pid,
4580 count,
4581 offset,
4582 lock_type,
4583 POSIX_LOCK,
4584 &my_lock_ctx);
4586 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4588 * A blocking lock was requested. Package up
4589 * this smb into a queued request and push it
4590 * onto the blocking lock queue.
4592 if(push_blocking_lock_request(inbuf, length,
4593 fsp,
4594 -1, /* infinite timeout. */
4596 lock_pid,
4597 lock_type,
4598 POSIX_LOCK,
4599 offset,
4600 count)) {
4601 return -1;
4606 if (!NT_STATUS_IS_OK(status)) {
4607 return ERROR_NT(status);
4610 SSVAL(params,0,0);
4611 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4612 return(-1);
4614 #endif
4616 default:
4617 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4620 /* get some defaults (no modifications) if any info is zero or -1. */
4621 if (null_mtime(tvs.actime)) {
4622 tvs.actime = sbuf.st_atime;
4625 if (null_mtime(tvs.modtime)) {
4626 tvs.modtime = sbuf.st_mtime;
4629 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4630 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4631 DEBUG(6,("size: %.0f ", (double)size));
4633 if (dosmode) {
4634 if (S_ISDIR(sbuf.st_mode))
4635 dosmode |= aDIR;
4636 else
4637 dosmode &= ~aDIR;
4640 DEBUG(6,("dosmode: %x\n" , dosmode));
4642 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4643 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4644 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4645 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4648 * Only do this test if we are not explicitly
4649 * changing the size of a file.
4651 if (!size)
4652 size = get_file_size(sbuf);
4656 * Try and set the times, size and mode of this file -
4657 * if they are different from the current values
4660 /* check the mode isn't different, before changing it */
4661 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4663 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4665 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4666 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4667 return(UNIXERROR(ERRDOS,ERRnoaccess));
4671 /* Now the size. */
4672 if (size != get_file_size(sbuf)) {
4674 int ret;
4676 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4677 fname, (double)size ));
4679 if (fd == -1) {
4680 files_struct *new_fsp = NULL;
4682 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4683 FILE_WRITE_DATA,
4684 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4685 FILE_OPEN,
4687 FILE_ATTRIBUTE_NORMAL,
4688 FORCE_OPLOCK_BREAK_TO_NONE,
4689 NULL);
4691 if (new_fsp == NULL) {
4692 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4693 /* We have re-scheduled this call. */
4694 return -1;
4696 return(UNIXERROR(ERRDOS,ERRnoaccess));
4698 ret = vfs_set_filelen(new_fsp, size);
4699 close_file(new_fsp,NORMAL_CLOSE);
4700 } else {
4701 ret = vfs_set_filelen(fsp, size);
4704 if (ret == -1) {
4705 return (UNIXERROR(ERRHRD,ERRdiskfull));
4710 * Finally the times.
4712 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4713 if(fsp != NULL) {
4715 * This was a setfileinfo on an open file.
4716 * NT does this a lot. We also need to
4717 * set the time here, as it can be read by
4718 * FindFirst/FindNext and with the patch for bug #2045
4719 * in smbd/fileio.c it ensures that this timestamp is
4720 * kept sticky even after a write. We save the request
4721 * away and will set it on file close and after a write. JRA.
4724 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4725 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4726 fsp_set_pending_modtime(fsp, tvs.modtime);
4730 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4732 if(file_utime(conn, fname, &tvs)!=0) {
4733 return(UNIXERROR(ERRDOS,ERRnoaccess));
4737 SSVAL(params,0,0);
4738 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4740 return(-1);
4743 /****************************************************************************
4744 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4745 ****************************************************************************/
4747 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4748 char **pparams, int total_params, char **ppdata, int total_data,
4749 unsigned int max_data_bytes)
4751 char *params = *pparams;
4752 char *pdata = *ppdata;
4753 pstring directory;
4754 int ret = -1;
4755 SMB_STRUCT_STAT sbuf;
4756 BOOL bad_path = False;
4757 NTSTATUS status = NT_STATUS_OK;
4758 TALLOC_CTX *ctx = NULL;
4759 struct ea_list *ea_list = NULL;
4761 if (!CAN_WRITE(conn))
4762 return ERROR_DOS(ERRSRV,ERRaccess);
4764 if (total_params < 4) {
4765 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4768 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
4769 if (!NT_STATUS_IS_OK(status)) {
4770 return ERROR_NT(status);
4773 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4775 unix_convert(directory,conn,0,&bad_path,&sbuf);
4776 if (bad_path) {
4777 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4780 /* Any data in this call is an EA list. */
4781 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4782 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4786 * OS/2 workplace shell seems to send SET_EA requests of "null"
4787 * length (4 bytes containing IVAL 4).
4788 * They seem to have no effect. Bug #3212. JRA.
4791 if (total_data != 4) {
4792 if (total_data < 10) {
4793 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4796 if (IVAL(pdata,0) > total_data) {
4797 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4798 IVAL(pdata,0), (unsigned int)total_data));
4799 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4802 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4803 if (!ctx) {
4804 return ERROR_NT(NT_STATUS_NO_MEMORY);
4806 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4807 if (!ea_list) {
4808 talloc_destroy(ctx);
4809 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4811 } else if (IVAL(pdata,0) != 4) {
4812 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4815 if (check_name(directory,conn)) {
4816 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4819 if(ret < 0) {
4820 talloc_destroy(ctx);
4821 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4822 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4825 /* Try and set any given EA. */
4826 if (total_data) {
4827 status = set_ea(conn, NULL, directory, ea_list);
4828 talloc_destroy(ctx);
4829 if (!NT_STATUS_IS_OK(status)) {
4830 return ERROR_NT(status);
4834 /* Realloc the parameter and data sizes */
4835 *pparams = SMB_REALLOC(*pparams,2);
4836 if(*pparams == NULL) {
4837 return ERROR_NT(NT_STATUS_NO_MEMORY);
4839 params = *pparams;
4841 SSVAL(params,0,0);
4843 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4845 return(-1);
4848 /****************************************************************************
4849 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4850 We don't actually do this - we just send a null response.
4851 ****************************************************************************/
4853 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4854 char **pparams, int total_params, char **ppdata, int total_data,
4855 unsigned int max_data_bytes)
4857 static uint16 fnf_handle = 257;
4858 char *params = *pparams;
4859 uint16 info_level;
4861 if (total_params < 6) {
4862 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4865 info_level = SVAL(params,4);
4866 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4868 switch (info_level) {
4869 case 1:
4870 case 2:
4871 break;
4872 default:
4873 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4876 /* Realloc the parameter and data sizes */
4877 *pparams = SMB_REALLOC(*pparams,6);
4878 if (*pparams == NULL) {
4879 return ERROR_NT(NT_STATUS_NO_MEMORY);
4881 params = *pparams;
4883 SSVAL(params,0,fnf_handle);
4884 SSVAL(params,2,0); /* No changes */
4885 SSVAL(params,4,0); /* No EA errors */
4887 fnf_handle++;
4889 if(fnf_handle == 0)
4890 fnf_handle = 257;
4892 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4894 return(-1);
4897 /****************************************************************************
4898 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4899 changes). Currently this does nothing.
4900 ****************************************************************************/
4902 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4903 char **pparams, int total_params, char **ppdata, int total_data,
4904 unsigned int max_data_bytes)
4906 char *params = *pparams;
4908 DEBUG(3,("call_trans2findnotifynext\n"));
4910 /* Realloc the parameter and data sizes */
4911 *pparams = SMB_REALLOC(*pparams,4);
4912 if (*pparams == NULL) {
4913 return ERROR_NT(NT_STATUS_NO_MEMORY);
4915 params = *pparams;
4917 SSVAL(params,0,0); /* No changes */
4918 SSVAL(params,2,0); /* No EA errors */
4920 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4922 return(-1);
4925 /****************************************************************************
4926 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4927 ****************************************************************************/
4929 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4930 char **pparams, int total_params, char **ppdata, int total_data,
4931 unsigned int max_data_bytes)
4933 char *params = *pparams;
4934 pstring pathname;
4935 int reply_size = 0;
4936 int max_referral_level;
4938 DEBUG(10,("call_trans2getdfsreferral\n"));
4940 if (total_params < 2) {
4941 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4944 max_referral_level = SVAL(params,0);
4946 if(!lp_host_msdfs())
4947 return ERROR_DOS(ERRDOS,ERRbadfunc);
4949 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4950 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4951 return UNIXERROR(ERRDOS,ERRbadfile);
4953 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4954 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4956 return(-1);
4959 #define LMCAT_SPL 0x53
4960 #define LMFUNC_GETJOBID 0x60
4962 /****************************************************************************
4963 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4964 ****************************************************************************/
4966 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4967 char **pparams, int total_params, char **ppdata, int total_data,
4968 unsigned int max_data_bytes)
4970 char *pdata = *ppdata;
4971 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4973 /* check for an invalid fid before proceeding */
4975 if (!fsp)
4976 return(ERROR_DOS(ERRDOS,ERRbadfid));
4978 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4979 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4980 *ppdata = SMB_REALLOC(*ppdata, 32);
4981 if (*ppdata == NULL) {
4982 return ERROR_NT(NT_STATUS_NO_MEMORY);
4984 pdata = *ppdata;
4986 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4987 CAN ACCEPT THIS IN UNICODE. JRA. */
4989 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4990 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4991 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4992 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4993 return(-1);
4994 } else {
4995 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4996 return ERROR_DOS(ERRSRV,ERRerror);
5000 /****************************************************************************
5001 Reply to a SMBfindclose (stop trans2 directory search).
5002 ****************************************************************************/
5004 int reply_findclose(connection_struct *conn,
5005 char *inbuf,char *outbuf,int length,int bufsize)
5007 int outsize = 0;
5008 int dptr_num=SVALS(inbuf,smb_vwv0);
5009 START_PROFILE(SMBfindclose);
5011 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5013 dptr_close(&dptr_num);
5015 outsize = set_message(outbuf,0,0,False);
5017 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5019 END_PROFILE(SMBfindclose);
5020 return(outsize);
5023 /****************************************************************************
5024 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5025 ****************************************************************************/
5027 int reply_findnclose(connection_struct *conn,
5028 char *inbuf,char *outbuf,int length,int bufsize)
5030 int outsize = 0;
5031 int dptr_num= -1;
5032 START_PROFILE(SMBfindnclose);
5034 dptr_num = SVAL(inbuf,smb_vwv0);
5036 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5038 /* We never give out valid handles for a
5039 findnotifyfirst - so any dptr_num is ok here.
5040 Just ignore it. */
5042 outsize = set_message(outbuf,0,0,False);
5044 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5046 END_PROFILE(SMBfindnclose);
5047 return(outsize);
5050 int handle_trans2(connection_struct *conn,
5051 struct trans_state *state,
5052 char *inbuf, char *outbuf, int size, int bufsize)
5054 int outsize;
5056 if (Protocol >= PROTOCOL_NT1) {
5057 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5060 /* Now we must call the relevant TRANS2 function */
5061 switch(state->call) {
5062 case TRANSACT2_OPEN:
5064 START_PROFILE_NESTED(Trans2_open);
5065 outsize = call_trans2open(
5066 conn, inbuf, outbuf, bufsize,
5067 &state->param, state->total_param,
5068 &state->data, state->total_data,
5069 state->max_data_return);
5070 END_PROFILE_NESTED(Trans2_open);
5071 break;
5074 case TRANSACT2_FINDFIRST:
5076 START_PROFILE_NESTED(Trans2_findfirst);
5077 outsize = call_trans2findfirst(
5078 conn, inbuf, outbuf, bufsize,
5079 &state->param, state->total_param,
5080 &state->data, state->total_data,
5081 state->max_data_return);
5082 END_PROFILE_NESTED(Trans2_findfirst);
5083 break;
5086 case TRANSACT2_FINDNEXT:
5088 START_PROFILE_NESTED(Trans2_findnext);
5089 outsize = call_trans2findnext(
5090 conn, inbuf, outbuf, size, bufsize,
5091 &state->param, state->total_param,
5092 &state->data, state->total_data,
5093 state->max_data_return);
5094 END_PROFILE_NESTED(Trans2_findnext);
5095 break;
5098 case TRANSACT2_QFSINFO:
5100 START_PROFILE_NESTED(Trans2_qfsinfo);
5101 outsize = call_trans2qfsinfo(
5102 conn, inbuf, outbuf, size, bufsize,
5103 &state->param, state->total_param,
5104 &state->data, state->total_data,
5105 state->max_data_return);
5106 END_PROFILE_NESTED(Trans2_qfsinfo);
5107 break;
5110 case TRANSACT2_SETFSINFO:
5112 START_PROFILE_NESTED(Trans2_setfsinfo);
5113 outsize = call_trans2setfsinfo(
5114 conn, inbuf, outbuf, size, bufsize,
5115 &state->param, state->total_param,
5116 &state->data, state->total_data,
5117 state->max_data_return);
5118 END_PROFILE_NESTED(Trans2_setfsinfo);
5119 break;
5122 case TRANSACT2_QPATHINFO:
5123 case TRANSACT2_QFILEINFO:
5125 START_PROFILE_NESTED(Trans2_qpathinfo);
5126 outsize = call_trans2qfilepathinfo(
5127 conn, inbuf, outbuf, size, bufsize, state->call,
5128 &state->param, state->total_param,
5129 &state->data, state->total_data,
5130 state->max_data_return);
5131 END_PROFILE_NESTED(Trans2_qpathinfo);
5132 break;
5135 case TRANSACT2_SETPATHINFO:
5136 case TRANSACT2_SETFILEINFO:
5138 START_PROFILE_NESTED(Trans2_setpathinfo);
5139 outsize = call_trans2setfilepathinfo(
5140 conn, inbuf, outbuf, size, bufsize, state->call,
5141 &state->param, state->total_param,
5142 &state->data, state->total_data,
5143 state->max_data_return);
5144 END_PROFILE_NESTED(Trans2_setpathinfo);
5145 break;
5148 case TRANSACT2_FINDNOTIFYFIRST:
5150 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5151 outsize = call_trans2findnotifyfirst(
5152 conn, inbuf, outbuf, size, bufsize,
5153 &state->param, state->total_param,
5154 &state->data, state->total_data,
5155 state->max_data_return);
5156 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5157 break;
5160 case TRANSACT2_FINDNOTIFYNEXT:
5162 START_PROFILE_NESTED(Trans2_findnotifynext);
5163 outsize = call_trans2findnotifynext(
5164 conn, inbuf, outbuf, size, bufsize,
5165 &state->param, state->total_param,
5166 &state->data, state->total_data,
5167 state->max_data_return);
5168 END_PROFILE_NESTED(Trans2_findnotifynext);
5169 break;
5172 case TRANSACT2_MKDIR:
5174 START_PROFILE_NESTED(Trans2_mkdir);
5175 outsize = call_trans2mkdir(
5176 conn, inbuf, outbuf, size, bufsize,
5177 &state->param, state->total_param,
5178 &state->data, state->total_data,
5179 state->max_data_return);
5180 END_PROFILE_NESTED(Trans2_mkdir);
5181 break;
5184 case TRANSACT2_GET_DFS_REFERRAL:
5186 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5187 outsize = call_trans2getdfsreferral(
5188 conn, inbuf, outbuf, size, bufsize,
5189 &state->param, state->total_param,
5190 &state->data, state->total_data,
5191 state->max_data_return);
5192 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5193 break;
5196 case TRANSACT2_IOCTL:
5198 START_PROFILE_NESTED(Trans2_ioctl);
5199 outsize = call_trans2ioctl(
5200 conn, inbuf, outbuf, size, bufsize,
5201 &state->param, state->total_param,
5202 &state->data, state->total_data,
5203 state->max_data_return);
5204 END_PROFILE_NESTED(Trans2_ioctl);
5205 break;
5208 default:
5209 /* Error in request */
5210 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5211 outsize = ERROR_DOS(ERRSRV,ERRerror);
5214 return outsize;
5217 /****************************************************************************
5218 Reply to a SMBtrans2.
5219 ****************************************************************************/
5221 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5222 int size, int bufsize)
5224 int outsize = 0;
5225 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5226 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5227 unsigned int psoff = SVAL(inbuf, smb_psoff);
5228 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5229 unsigned int tran_call = SVAL(inbuf, smb_setup0);
5230 struct trans_state *state;
5231 NTSTATUS result;
5233 START_PROFILE(SMBtrans2);
5235 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5236 if (!NT_STATUS_IS_OK(result)) {
5237 DEBUG(2, ("Got invalid trans2 request: %s\n",
5238 nt_errstr(result)));
5239 END_PROFILE(SMBtrans2);
5240 return ERROR_NT(result);
5243 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5244 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5245 END_PROFILE(SMBtrans2);
5246 return ERROR_DOS(ERRSRV,ERRaccess);
5249 if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
5250 DEBUG(0, ("talloc failed\n"));
5251 END_PROFILE(SMBtrans2);
5252 return ERROR_NT(NT_STATUS_NO_MEMORY);
5255 state->cmd = SMBtrans2;
5257 state->mid = SVAL(inbuf, smb_mid);
5258 state->vuid = SVAL(inbuf, smb_uid);
5259 state->setup_count = SVAL(inbuf, smb_suwcnt);
5260 state->total_param = SVAL(inbuf, smb_tpscnt);
5261 state->param = NULL;
5262 state->total_data = SVAL(inbuf, smb_tdscnt);
5263 state->data = NULL;
5264 state->max_param_return = SVAL(inbuf, smb_mprcnt);
5265 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
5266 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5267 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5268 state->one_way = BITSETW(inbuf+smb_vwv5,1);
5270 state->call = tran_call;
5272 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5273 is so as a sanity check */
5274 if (state->setup_count != 1) {
5276 * Need to have rc=0 for ioctl to get job id for OS/2.
5277 * Network printing will fail if function is not successful.
5278 * Similar function in reply.c will be used if protocol
5279 * is LANMAN1.0 instead of LM1.2X002.
5280 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
5281 * outbuf doesn't have to be set(only job id is used).
5283 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5284 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5285 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5286 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5287 } else {
5288 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5289 DEBUG(2,("Transaction is %d\n",tran_call));
5290 TALLOC_FREE(state);
5291 END_PROFILE(SMBtrans2);
5292 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5296 if ((dscnt > state->total_data) || (pscnt > state->total_param))
5297 goto bad_param;
5299 if (state->total_data) {
5300 /* Can't use talloc here, the core routines do realloc on the
5301 * params and data. */
5302 state->data = SMB_MALLOC(state->total_data);
5303 if (state->data == NULL) {
5304 DEBUG(0,("reply_trans2: data malloc fail for %u "
5305 "bytes !\n", (unsigned int)state->total_data));
5306 TALLOC_FREE(state);
5307 END_PROFILE(SMBtrans2);
5308 return(ERROR_DOS(ERRDOS,ERRnomem));
5310 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5311 goto bad_param;
5312 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5313 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5314 goto bad_param;
5316 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5319 if (state->total_param) {
5320 /* Can't use talloc here, the core routines do realloc on the
5321 * params and data. */
5322 state->param = SMB_MALLOC(state->total_param);
5323 if (state->param == NULL) {
5324 DEBUG(0,("reply_trans: param malloc fail for %u "
5325 "bytes !\n", (unsigned int)state->total_param));
5326 SAFE_FREE(state->data);
5327 TALLOC_FREE(state);
5328 END_PROFILE(SMBtrans2);
5329 return(ERROR_DOS(ERRDOS,ERRnomem));
5331 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5332 goto bad_param;
5333 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5334 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5335 goto bad_param;
5337 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5340 state->received_data = dscnt;
5341 state->received_param = pscnt;
5343 if ((state->received_param == state->total_param) &&
5344 (state->received_data == state->total_data)) {
5346 outsize = handle_trans2(conn, state, inbuf, outbuf,
5347 size, bufsize);
5348 SAFE_FREE(state->data);
5349 SAFE_FREE(state->param);
5350 TALLOC_FREE(state);
5351 END_PROFILE(SMBtrans2);
5352 return outsize;
5355 DLIST_ADD(conn->pending_trans, state);
5357 /* We need to send an interim response then receive the rest
5358 of the parameter/data bytes */
5359 outsize = set_message(outbuf,0,0,False);
5360 show_msg(outbuf);
5361 END_PROFILE(SMBtrans2);
5362 return outsize;
5364 bad_param:
5366 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5367 SAFE_FREE(state->data);
5368 SAFE_FREE(state->param);
5369 TALLOC_FREE(state);
5370 END_PROFILE(SMBtrans2);
5371 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5375 /****************************************************************************
5376 Reply to a SMBtranss2
5377 ****************************************************************************/
5379 int reply_transs2(connection_struct *conn,
5380 char *inbuf,char *outbuf,int size,int bufsize)
5382 int outsize = 0;
5383 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5384 struct trans_state *state;
5386 START_PROFILE(SMBtranss2);
5388 show_msg(inbuf);
5390 for (state = conn->pending_trans; state != NULL;
5391 state = state->next) {
5392 if (state->mid == SVAL(inbuf,smb_mid)) {
5393 break;
5397 if ((state == NULL) || (state->cmd != SMBtrans2)) {
5398 END_PROFILE(SMBtranss2);
5399 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5402 /* Revise state->total_param and state->total_data in case they have
5403 changed downwards */
5405 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5406 state->total_param = SVAL(inbuf, smb_tpscnt);
5407 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5408 state->total_data = SVAL(inbuf, smb_tdscnt);
5410 pcnt = SVAL(inbuf, smb_spscnt);
5411 poff = SVAL(inbuf, smb_spsoff);
5412 pdisp = SVAL(inbuf, smb_spsdisp);
5414 dcnt = SVAL(inbuf, smb_sdscnt);
5415 doff = SVAL(inbuf, smb_sdsoff);
5416 ddisp = SVAL(inbuf, smb_sdsdisp);
5418 state->received_param += pcnt;
5419 state->received_data += dcnt;
5421 if ((state->received_data > state->total_data) ||
5422 (state->received_param > state->total_param))
5423 goto bad_param;
5425 if (pcnt) {
5426 if (pdisp+pcnt > state->total_param)
5427 goto bad_param;
5428 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5429 goto bad_param;
5430 if (pdisp > state->total_param)
5431 goto bad_param;
5432 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5433 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5434 goto bad_param;
5435 if (state->param + pdisp < state->param)
5436 goto bad_param;
5438 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5439 pcnt);
5442 if (dcnt) {
5443 if (ddisp+dcnt > state->total_data)
5444 goto bad_param;
5445 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5446 goto bad_param;
5447 if (ddisp > state->total_data)
5448 goto bad_param;
5449 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5450 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5451 goto bad_param;
5452 if (state->data + ddisp < state->data)
5453 goto bad_param;
5455 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5456 dcnt);
5459 if ((state->received_param < state->total_param) ||
5460 (state->received_data < state->total_data)) {
5461 END_PROFILE(SMBtranss2);
5462 return -1;
5465 /* construct_reply_common has done us the favor to pre-fill the
5466 * command field with SMBtranss2 which is wrong :-)
5468 SCVAL(outbuf,smb_com,SMBtrans2);
5470 outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5472 DLIST_REMOVE(conn->pending_trans, state);
5473 SAFE_FREE(state->data);
5474 SAFE_FREE(state->param);
5475 TALLOC_FREE(state);
5477 if (outsize == 0) {
5478 END_PROFILE(SMBtranss2);
5479 return(ERROR_DOS(ERRSRV,ERRnosupport));
5482 END_PROFILE(SMBtranss2);
5483 return(outsize);
5485 bad_param:
5487 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5488 DLIST_REMOVE(conn->pending_trans, state);
5489 SAFE_FREE(state->data);
5490 SAFE_FREE(state->param);
5491 TALLOC_FREE(state);
5492 END_PROFILE(SMBtranss2);
5493 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);