r5739: sync for 3.0.12rc1 (current with SAMBA_3_0 r5738)
[Samba/gbeck.git] / source / smbd / trans2.c
blob3f3d9c2f461fa33975116b9d24c6050bc6c7f336
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 extern enum protocol_types Protocol;
27 extern int smb_read_error;
28 extern int global_oplock_break;
29 extern uint32 global_client_caps;
30 extern struct current_user current_user;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 /********************************************************************
36 Roundup a value to the nearest allocation roundup size boundary.
37 Only do this for Windows clients.
38 ********************************************************************/
40 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
42 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
44 /* Only roundup for Windows clients. */
45 enum remote_arch_types ra_type = get_remote_arch();
46 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
47 val = SMB_ROUNDUP(val,rval);
49 return val;
52 /********************************************************************
53 Given a stat buffer return the allocated size on disk, taking into
54 account sparse files.
55 ********************************************************************/
57 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
59 SMB_BIG_UINT ret;
61 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
62 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
63 #else
64 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
65 #endif
67 if (!ret && fsp && fsp->initial_allocation_size)
68 ret = fsp->initial_allocation_size;
70 return smb_roundup(conn, ret);
73 /****************************************************************************
74 Utility functions for dealing with extended attributes.
75 ****************************************************************************/
77 static const char *prohibited_ea_names[] = {
78 SAMBA_POSIX_INHERITANCE_EA_NAME,
79 SAMBA_XATTR_DOS_ATTRIB,
80 NULL
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static BOOL samba_private_attr_name(const char *unix_ea_name)
89 int i;
91 for (i = 0; prohibited_ea_names[i]; i++) {
92 if (strequal( prohibited_ea_names[i], unix_ea_name))
93 return True;
95 return False;
98 struct ea_list {
99 struct ea_list *next, *prev;
100 struct ea_struct ea;
103 /****************************************************************************
104 Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108 const char *fname, char *ea_name, struct ea_struct *pea)
110 /* Get the value of this xattr. Max size is 64k. */
111 size_t attr_size = 256;
112 char *val = NULL;
113 ssize_t sizeret;
115 again:
117 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
118 if (!val) {
119 return False;
122 if (fsp && fsp->fd != -1) {
123 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
124 } else {
125 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
128 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
129 attr_size = 65536;
130 goto again;
133 if (sizeret == -1) {
134 return False;
137 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
138 dump_data(10, val, sizeret);
140 pea->flags = 0;
141 if (strnequal(ea_name, "user.", 5)) {
142 pea->name = &ea_name[5];
143 } else {
144 pea->name = ea_name;
146 pea->value.data = val;
147 pea->value.length = (size_t)sizeret;
148 return True;
151 /****************************************************************************
152 Return a linked list of the total EA's. Plus the total size
153 ****************************************************************************/
155 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
157 /* Get a list of all xattrs. Max namesize is 64k. */
158 size_t ea_namelist_size = 1024;
159 char *ea_namelist;
160 char *p;
161 ssize_t sizeret;
162 int i;
163 struct ea_list *ea_list_head = NULL;
165 *pea_total_len = 0;
167 if (!lp_ea_support(SNUM(conn))) {
168 return NULL;
171 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
172 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
173 if (fsp && fsp->fd != -1) {
174 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
175 } else {
176 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
179 if (sizeret == -1 && errno == ERANGE) {
180 ea_namelist_size *= 2;
181 } else {
182 break;
186 if (sizeret == -1)
187 return NULL;
189 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
191 if (sizeret) {
192 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
193 struct ea_list *listp, *tmp;
195 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
196 continue;
198 listp = TALLOC_P(mem_ctx, struct ea_list);
199 if (!listp)
200 return NULL;
202 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
203 return NULL;
207 fstring dos_ea_name;
208 push_ascii_fstring(dos_ea_name, listp->ea.name);
209 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
210 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
211 *pea_total_len, dos_ea_name,
212 (unsigned int)listp->ea.value.length ));
214 DLIST_ADD_END(ea_list_head, listp, tmp);
216 /* Add on 4 for total length. */
217 if (*pea_total_len) {
218 *pea_total_len += 4;
222 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
223 return ea_list_head;
226 /****************************************************************************
227 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
228 that was filled.
229 ****************************************************************************/
231 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
232 connection_struct *conn, files_struct *fsp, const char *fname)
234 unsigned int ret_data_size = 4;
235 char *p = pdata;
236 size_t total_ea_len;
237 TALLOC_CTX *mem_ctx;
238 struct ea_list *ea_list;
240 SMB_ASSERT(total_data_size >= 4);
242 SIVAL(pdata,0,0);
243 if (!lp_ea_support(SNUM(conn))) {
244 return 4;
246 mem_ctx = talloc_init("fill_ea_buffer");
247 if (!mem_ctx) {
248 return 4;
251 ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
252 if (!ea_list) {
253 talloc_destroy(mem_ctx);
254 return 4;
257 if (total_ea_len > total_data_size) {
258 talloc_destroy(mem_ctx);
259 return 4;
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263 size_t dos_namelen;
264 fstring dos_ea_name;
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
268 break;
270 if (ea_list->ea.value.length > 65535) {
271 break;
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
274 break;
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
290 ret_data_size, total_ea_len ));
291 talloc_destroy(mem_ctx);
292 SIVAL(pdata,0,ret_data_size);
293 return ret_data_size;
296 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
298 size_t total_ea_len = 0;
299 TALLOC_CTX *mem_ctx = NULL;
301 if (!lp_ea_support(SNUM(conn))) {
302 return 0;
304 mem_ctx = talloc_init("estimate_ea_size");
305 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
306 talloc_destroy(mem_ctx);
307 return total_ea_len;
310 /****************************************************************************
311 Ensure the EA name is case insensitive by matching any existing EA name.
312 ****************************************************************************/
314 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
316 size_t total_ea_len;
317 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
318 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
320 for (; ea_list; ea_list = ea_list->next) {
321 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
322 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
323 &unix_ea_name[5], ea_list->ea.name));
324 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
325 break;
328 talloc_destroy(mem_ctx);
331 /****************************************************************************
332 Set or delete an extended attribute.
333 ****************************************************************************/
335 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
336 char *pdata, int total_data)
338 unsigned int namelen;
339 unsigned int ealen;
340 int ret;
341 fstring unix_ea_name;
343 if (!lp_ea_support(SNUM(conn))) {
344 return NT_STATUS_EAS_NOT_SUPPORTED;
347 if (total_data < 8) {
348 return NT_STATUS_INVALID_PARAMETER;
351 if (IVAL(pdata,0) > total_data) {
352 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
353 return NT_STATUS_INVALID_PARAMETER;
356 pdata += 4;
357 namelen = CVAL(pdata,1);
358 ealen = SVAL(pdata,2);
359 pdata += 4;
360 if (total_data < 8 + namelen + 1 + ealen) {
361 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
362 (unsigned int)total_data, namelen, ealen));
363 return NT_STATUS_INVALID_PARAMETER;
366 if (pdata[namelen] != '\0') {
367 DEBUG(10,("set_ea: ea name not null terminated\n"));
368 return NT_STATUS_INVALID_PARAMETER;
371 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
372 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
373 pdata += (namelen + 1);
375 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
377 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
378 if (ealen) {
379 DEBUG(10,("set_ea: data :\n"));
380 dump_data(10, pdata, ealen);
383 if (samba_private_attr_name(unix_ea_name)) {
384 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
385 return NT_STATUS_ACCESS_DENIED;
388 if (ealen == 0) {
389 /* Remove the attribute. */
390 if (fsp && (fsp->fd != -1)) {
391 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
392 unix_ea_name, fsp->fsp_name));
393 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
394 } else {
395 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
396 unix_ea_name, fname));
397 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
399 #ifdef ENOATTR
400 /* Removing a non existent attribute always succeeds. */
401 if (ret == -1 && errno == ENOATTR) {
402 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
403 ret = 0;
405 #endif
406 } else {
407 if (fsp && (fsp->fd != -1)) {
408 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
409 unix_ea_name, fsp->fsp_name));
410 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
411 } else {
412 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
413 unix_ea_name, fname));
414 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
418 if (ret == -1) {
419 #ifdef ENOTSUP
420 if (errno == ENOTSUP) {
421 return NT_STATUS_EAS_NOT_SUPPORTED;
423 #endif
424 return map_nt_error_from_unix(errno);
427 return NT_STATUS_OK;
430 /****************************************************************************
431 Send the required number of replies back.
432 We assume all fields other than the data fields are
433 set correctly for the type of call.
434 HACK ! Always assumes smb_setup field is zero.
435 ****************************************************************************/
437 static int send_trans2_replies(char *outbuf,
438 int bufsize,
439 char *params,
440 int paramsize,
441 char *pdata,
442 int datasize)
444 /* As we are using a protocol > LANMAN1 then the max_send
445 variable must have been set in the sessetupX call.
446 This takes precedence over the max_xmit field in the
447 global struct. These different max_xmit variables should
448 be merged as this is now too confusing */
450 extern int max_send;
451 int data_to_send = datasize;
452 int params_to_send = paramsize;
453 int useable_space;
454 char *pp = params;
455 char *pd = pdata;
456 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
457 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
458 int data_alignment_offset = 0;
460 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
462 set_message(outbuf,10,0,True);
464 /* If there genuinely are no parameters or data to send just send the empty packet */
466 if(params_to_send == 0 && data_to_send == 0) {
467 if (!send_smb(smbd_server_fd(),outbuf))
468 exit_server("send_trans2_replies: send_smb failed.");
469 return 0;
472 /* When sending params and data ensure that both are nicely aligned */
473 /* Only do this alignment when there is also data to send - else
474 can cause NT redirector problems. */
476 if (((params_to_send % 4) != 0) && (data_to_send != 0))
477 data_alignment_offset = 4 - (params_to_send % 4);
479 /* Space is bufsize minus Netbios over TCP header minus SMB header */
480 /* The alignment_offset is to align the param bytes on an even byte
481 boundary. NT 4.0 Beta needs this to work correctly. */
483 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
485 /* useable_space can never be more than max_send minus the alignment offset. */
487 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
489 while (params_to_send || data_to_send) {
490 /* Calculate whether we will totally or partially fill this packet */
492 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
494 /* We can never send more than useable_space */
496 * Note that 'useable_space' does not include the alignment offsets,
497 * but we must include the alignment offsets in the calculation of
498 * the length of the data we send over the wire, as the alignment offsets
499 * are sent here. Fix from Marc_Jacobsen@hp.com.
502 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
504 set_message(outbuf, 10, total_sent_thistime, True);
506 /* Set total params and data to be sent */
507 SSVAL(outbuf,smb_tprcnt,paramsize);
508 SSVAL(outbuf,smb_tdrcnt,datasize);
510 /* Calculate how many parameters and data we can fit into
511 * this packet. Parameters get precedence
514 params_sent_thistime = MIN(params_to_send,useable_space);
515 data_sent_thistime = useable_space - params_sent_thistime;
516 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
518 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
520 /* smb_proff is the offset from the start of the SMB header to the
521 parameter bytes, however the first 4 bytes of outbuf are
522 the Netbios over TCP header. Thus use smb_base() to subtract
523 them from the calculation */
525 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
527 if(params_sent_thistime == 0)
528 SSVAL(outbuf,smb_prdisp,0);
529 else
530 /* Absolute displacement of param bytes sent in this packet */
531 SSVAL(outbuf,smb_prdisp,pp - params);
533 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
534 if(data_sent_thistime == 0) {
535 SSVAL(outbuf,smb_droff,0);
536 SSVAL(outbuf,smb_drdisp, 0);
537 } else {
538 /* The offset of the data bytes is the offset of the
539 parameter bytes plus the number of parameters being sent this time */
540 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
541 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
542 SSVAL(outbuf,smb_drdisp, pd - pdata);
545 /* Copy the param bytes into the packet */
547 if(params_sent_thistime)
548 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
550 /* Copy in the data bytes */
551 if(data_sent_thistime)
552 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
553 data_alignment_offset,pd,data_sent_thistime);
555 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
556 params_sent_thistime, data_sent_thistime, useable_space));
557 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
558 params_to_send, data_to_send, paramsize, datasize));
560 /* Send the packet */
561 if (!send_smb(smbd_server_fd(),outbuf))
562 exit_server("send_trans2_replies: send_smb failed.");
564 pp += params_sent_thistime;
565 pd += data_sent_thistime;
567 params_to_send -= params_sent_thistime;
568 data_to_send -= data_sent_thistime;
570 /* Sanity check */
571 if(params_to_send < 0 || data_to_send < 0) {
572 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
573 params_to_send, data_to_send));
574 return -1;
578 return 0;
581 /****************************************************************************
582 Reply to a TRANSACT2_OPEN.
583 ****************************************************************************/
585 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
586 char **pparams, int total_params, char **ppdata, int total_data,
587 unsigned int max_data_bytes)
589 char *params = *pparams;
590 int16 open_mode;
591 int16 open_attr;
592 BOOL oplock_request;
593 #if 0
594 BOOL return_additional_info;
595 int16 open_sattr;
596 time_t open_time;
597 #endif
598 int16 open_ofun;
599 int32 open_size;
600 char *pname;
601 pstring fname;
602 SMB_OFF_T size=0;
603 int fmode=0,mtime=0,rmode;
604 SMB_INO_T inode = 0;
605 SMB_STRUCT_STAT sbuf;
606 int smb_action = 0;
607 BOOL bad_path = False;
608 files_struct *fsp;
609 NTSTATUS status;
612 * Ensure we have enough parameters to perform the operation.
615 if (total_params < 29)
616 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
618 open_mode = SVAL(params, 2);
619 open_attr = SVAL(params,6);
620 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
621 #if 0
622 return_additional_info = BITSETW(params,0);
623 open_sattr = SVAL(params, 4);
624 open_time = make_unix_date3(params+8);
625 #endif
626 open_ofun = SVAL(params,12);
627 open_size = IVAL(params,14);
628 pname = &params[28];
630 if (IS_IPC(conn))
631 return(ERROR_DOS(ERRSRV,ERRaccess));
633 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
634 if (!NT_STATUS_IS_OK(status)) {
635 return ERROR_NT(status);
638 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
639 fname,open_mode, open_attr, open_ofun, open_size));
641 /* XXXX we need to handle passed times, sattr and flags */
643 unix_convert(fname,conn,0,&bad_path,&sbuf);
644 if (bad_path) {
645 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
648 if (!check_name(fname,conn)) {
649 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
652 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
653 oplock_request, &rmode,&smb_action);
655 if (!fsp) {
656 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
657 /* We have re-scheduled this call. */
658 clear_cached_errors();
659 return -1;
661 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
664 size = get_file_size(sbuf);
665 fmode = dos_mode(conn,fname,&sbuf);
666 mtime = sbuf.st_mtime;
667 inode = sbuf.st_ino;
668 if (fmode & aDIR) {
669 close_file(fsp,False);
670 return(ERROR_DOS(ERRDOS,ERRnoaccess));
673 /* Realloc the size of parameters and data we will return */
674 params = SMB_REALLOC(*pparams, 28);
675 if( params == NULL )
676 return(ERROR_DOS(ERRDOS,ERRnomem));
677 *pparams = params;
679 memset((char *)params,'\0',28);
680 SSVAL(params,0,fsp->fnum);
681 SSVAL(params,2,fmode);
682 put_dos_date2(params,4, mtime);
683 SIVAL(params,8, (uint32)size);
684 SSVAL(params,12,rmode);
686 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
687 smb_action |= EXTENDED_OPLOCK_GRANTED;
689 SSVAL(params,18,smb_action);
692 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
694 SIVAL(params,20,inode);
696 /* Send the required number of replies */
697 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
699 return -1;
702 /*********************************************************
703 Routine to check if a given string matches exactly.
704 as a special case a mask of "." does NOT match. That
705 is required for correct wildcard semantics
706 Case can be significant or not.
707 **********************************************************/
709 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
711 if (mask[0] == '.' && mask[1] == 0)
712 return False;
713 if (case_sig)
714 return strcmp(str,mask)==0;
715 if (StrCaseCmp(str,mask) != 0) {
716 return False;
718 if (ms_has_wild(str)) {
719 return False;
721 return True;
724 /****************************************************************************
725 Return the filetype for UNIX extensions.
726 ****************************************************************************/
728 static uint32 unix_filetype(mode_t mode)
730 if(S_ISREG(mode))
731 return UNIX_TYPE_FILE;
732 else if(S_ISDIR(mode))
733 return UNIX_TYPE_DIR;
734 #ifdef S_ISLNK
735 else if(S_ISLNK(mode))
736 return UNIX_TYPE_SYMLINK;
737 #endif
738 #ifdef S_ISCHR
739 else if(S_ISCHR(mode))
740 return UNIX_TYPE_CHARDEV;
741 #endif
742 #ifdef S_ISBLK
743 else if(S_ISBLK(mode))
744 return UNIX_TYPE_BLKDEV;
745 #endif
746 #ifdef S_ISFIFO
747 else if(S_ISFIFO(mode))
748 return UNIX_TYPE_FIFO;
749 #endif
750 #ifdef S_ISSOCK
751 else if(S_ISSOCK(mode))
752 return UNIX_TYPE_SOCKET;
753 #endif
755 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
756 return UNIX_TYPE_UNKNOWN;
759 /****************************************************************************
760 Map wire perms onto standard UNIX permissions. Obey share restrictions.
761 ****************************************************************************/
763 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
765 mode_t ret = 0;
767 if (perms == SMB_MODE_NO_CHANGE)
768 return pst->st_mode;
770 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
771 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
772 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
773 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
774 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
775 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
776 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
777 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
778 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
779 #ifdef S_ISVTX
780 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
781 #endif
782 #ifdef S_ISGID
783 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
784 #endif
785 #ifdef S_ISUID
786 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
787 #endif
789 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
790 ret &= lp_dir_mask(SNUM(conn));
791 /* Add in force bits */
792 ret |= lp_force_dir_mode(SNUM(conn));
793 } else {
794 /* Apply mode mask */
795 ret &= lp_create_mask(SNUM(conn));
796 /* Add in force bits */
797 ret |= lp_force_create_mode(SNUM(conn));
800 return ret;
803 /****************************************************************************
804 Get a level dependent lanman2 dir entry.
805 ****************************************************************************/
807 static BOOL get_lanman2_dir_entry(connection_struct *conn,
808 void *inbuf, void *outbuf,
809 char *path_mask,int dirtype,int info_level,
810 int requires_resume_key,
811 BOOL dont_descend,char **ppdata,
812 char *base_data, int space_remaining,
813 BOOL *out_of_space, BOOL *got_exact_match,
814 int *last_entry_off)
816 const char *dname;
817 BOOL found = False;
818 SMB_STRUCT_STAT sbuf;
819 pstring mask;
820 pstring pathreal;
821 pstring fname;
822 char *p, *q, *pdata = *ppdata;
823 uint32 reskey=0;
824 long prev_dirpos=0;
825 int mode=0;
826 SMB_OFF_T file_size = 0;
827 SMB_BIG_UINT allocation_size = 0;
828 uint32 len;
829 time_t mdate=0, adate=0, cdate=0;
830 char *nameptr;
831 char *last_entry_ptr;
832 BOOL was_8_3;
833 int nt_extmode; /* Used for NT connections instead of mode */
834 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
836 *fname = 0;
837 *out_of_space = False;
838 *got_exact_match = False;
840 if (!conn->dirptr)
841 return(False);
843 p = strrchr_m(path_mask,'/');
844 if(p != NULL) {
845 if(p[1] == '\0')
846 pstrcpy(mask,"*.*");
847 else
848 pstrcpy(mask, p+1);
849 } else
850 pstrcpy(mask, path_mask);
853 while (!found) {
854 BOOL got_match;
855 /* Needed if we run out of space */
856 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
857 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
860 * Due to bugs in NT client redirectors we are not using
861 * resume keys any more - set them to zero.
862 * Check out the related comments in findfirst/findnext.
863 * JRA.
866 reskey = 0;
868 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
869 (long)conn->dirptr,curr_dirpos));
871 if (!dname)
872 return(False);
874 pstrcpy(fname,dname);
876 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
877 got_match = mask_match(fname, mask, conn->case_sensitive);
879 if(!got_match && !mangle_is_8_3(fname, False)) {
882 * It turns out that NT matches wildcards against
883 * both long *and* short names. This may explain some
884 * of the wildcard wierdness from old DOS clients
885 * that some people have been seeing.... JRA.
888 pstring newname;
889 pstrcpy( newname, fname);
890 mangle_map( newname, True, False, SNUM(conn));
891 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
892 got_match = mask_match(newname, mask, conn->case_sensitive);
895 if(got_match) {
896 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
897 if (dont_descend && !isdots)
898 continue;
900 pstrcpy(pathreal,conn->dirpath);
901 if(needslash)
902 pstrcat(pathreal,"/");
903 pstrcat(pathreal,dname);
905 if (INFO_LEVEL_IS_UNIX(info_level)) {
906 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
907 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
908 pathreal,strerror(errno)));
909 continue;
911 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
913 /* Needed to show the msdfs symlinks as
914 * directories */
916 if(lp_host_msdfs() &&
917 lp_msdfs_root(SNUM(conn)) &&
918 is_msdfs_link(conn, pathreal, NULL, NULL,
919 &sbuf)) {
921 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
922 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
924 } else {
926 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
927 pathreal,strerror(errno)));
928 continue;
932 mode = dos_mode(conn,pathreal,&sbuf);
934 if (!dir_check_ftype(conn,mode,dirtype)) {
935 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
936 continue;
939 file_size = get_file_size(sbuf);
940 allocation_size = get_allocation_size(conn,NULL,&sbuf);
941 mdate = sbuf.st_mtime;
942 adate = sbuf.st_atime;
943 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
945 if (lp_dos_filetime_resolution(SNUM(conn))) {
946 cdate &= ~1;
947 mdate &= ~1;
948 adate &= ~1;
951 if(mode & aDIR) {
952 /* This is necessary, as otherwise the
953 * desktop.ini file in this folder is
954 * ignored */
955 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
956 file_size = 0;
959 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
961 found = True;
965 mangle_map(fname,False,True,SNUM(conn));
967 p = pdata;
968 last_entry_ptr = p;
970 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
972 switch (info_level) {
973 case SMB_INFO_STANDARD:
974 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
975 if(requires_resume_key) {
976 SIVAL(p,0,reskey);
977 p += 4;
979 put_dos_date2(p,l1_fdateCreation,cdate);
980 put_dos_date2(p,l1_fdateLastAccess,adate);
981 put_dos_date2(p,l1_fdateLastWrite,mdate);
982 SIVAL(p,l1_cbFile,(uint32)file_size);
983 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
984 SSVAL(p,l1_attrFile,mode);
985 p += l1_achName;
986 nameptr = p;
987 p += align_string(outbuf, p, 0);
988 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
989 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
990 if (len > 2) {
991 SCVAL(nameptr, -1, len - 2);
992 } else {
993 SCVAL(nameptr, -1, 0);
995 } else {
996 if (len > 1) {
997 SCVAL(nameptr, -1, len - 1);
998 } else {
999 SCVAL(nameptr, -1, 0);
1002 p += len;
1003 break;
1005 case SMB_INFO_QUERY_EA_SIZE:
1006 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1007 if(requires_resume_key) {
1008 SIVAL(p,0,reskey);
1009 p += 4;
1011 put_dos_date2(p,l2_fdateCreation,cdate);
1012 put_dos_date2(p,l2_fdateLastAccess,adate);
1013 put_dos_date2(p,l2_fdateLastWrite,mdate);
1014 SIVAL(p,l2_cbFile,(uint32)file_size);
1015 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1016 SSVAL(p,l2_attrFile,mode);
1018 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1019 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1021 p += l2_achName;
1022 nameptr = p - 1;
1023 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1024 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1025 if (len > 2) {
1026 len -= 2;
1027 } else {
1028 len = 0;
1030 } else {
1031 if (len > 1) {
1032 len -= 1;
1033 } else {
1034 len = 0;
1037 SCVAL(nameptr,0,len);
1038 p += len;
1039 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1040 break;
1042 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1043 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1044 was_8_3 = mangle_is_8_3(fname, True);
1045 p += 4;
1046 SIVAL(p,0,reskey); p += 4;
1047 put_long_date(p,cdate); p += 8;
1048 put_long_date(p,adate); p += 8;
1049 put_long_date(p,mdate); p += 8;
1050 put_long_date(p,mdate); p += 8;
1051 SOFF_T(p,0,file_size); p += 8;
1052 SOFF_T(p,0,allocation_size); p += 8;
1053 SIVAL(p,0,nt_extmode); p += 4;
1054 q = p; p += 4; /* q is placeholder for name length. */
1056 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1057 SIVAL(p,0,ea_size); /* Extended attributes */
1058 p += 4;
1060 /* Clear the short name buffer. This is
1061 * IMPORTANT as not doing so will trigger
1062 * a Win2k client bug. JRA.
1064 memset(p,'\0',26);
1065 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1066 pstring mangled_name;
1067 pstrcpy(mangled_name, fname);
1068 mangle_map(mangled_name,True,True,SNUM(conn));
1069 mangled_name[12] = 0;
1070 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1071 SSVAL(p, 0, len);
1072 } else {
1073 SSVAL(p,0,0);
1074 *(p+2) = 0;
1076 p += 2 + 24;
1077 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1078 SIVAL(q,0,len);
1079 p += len;
1080 len = PTR_DIFF(p, pdata);
1081 len = (len + 3) & ~3;
1082 SIVAL(pdata,0,len);
1083 p = pdata + len;
1084 break;
1086 case SMB_FIND_FILE_DIRECTORY_INFO:
1087 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1088 p += 4;
1089 SIVAL(p,0,reskey); p += 4;
1090 put_long_date(p,cdate); p += 8;
1091 put_long_date(p,adate); p += 8;
1092 put_long_date(p,mdate); p += 8;
1093 put_long_date(p,mdate); p += 8;
1094 SOFF_T(p,0,file_size); p += 8;
1095 SOFF_T(p,0,allocation_size); p += 8;
1096 SIVAL(p,0,nt_extmode); p += 4;
1097 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1098 SIVAL(p,0,len);
1099 p += 4 + len;
1100 len = PTR_DIFF(p, pdata);
1101 len = (len + 3) & ~3;
1102 SIVAL(pdata,0,len);
1103 p = pdata + len;
1104 break;
1106 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1107 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1108 p += 4;
1109 SIVAL(p,0,reskey); p += 4;
1110 put_long_date(p,cdate); p += 8;
1111 put_long_date(p,adate); p += 8;
1112 put_long_date(p,mdate); p += 8;
1113 put_long_date(p,mdate); p += 8;
1114 SOFF_T(p,0,file_size); p += 8;
1115 SOFF_T(p,0,allocation_size); p += 8;
1116 SIVAL(p,0,nt_extmode); p += 4;
1117 q = p; p += 4; /* q is placeholder for name length. */
1119 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1120 SIVAL(p,0,ea_size); /* Extended attributes */
1121 p +=4;
1123 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1124 SIVAL(q, 0, len);
1125 p += len;
1127 len = PTR_DIFF(p, pdata);
1128 len = (len + 3) & ~3;
1129 SIVAL(pdata,0,len);
1130 p = pdata + len;
1131 break;
1133 case SMB_FIND_FILE_NAMES_INFO:
1134 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1135 p += 4;
1136 SIVAL(p,0,reskey); p += 4;
1137 p += 4;
1138 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1139 acl on a dir (tridge) */
1140 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1141 SIVAL(p, -4, len);
1142 p += len;
1143 len = PTR_DIFF(p, pdata);
1144 len = (len + 3) & ~3;
1145 SIVAL(pdata,0,len);
1146 p = pdata + len;
1147 break;
1149 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1150 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1151 p += 4;
1152 SIVAL(p,0,reskey); p += 4;
1153 put_long_date(p,cdate); p += 8;
1154 put_long_date(p,adate); p += 8;
1155 put_long_date(p,mdate); p += 8;
1156 put_long_date(p,mdate); p += 8;
1157 SOFF_T(p,0,file_size); p += 8;
1158 SOFF_T(p,0,allocation_size); p += 8;
1159 SIVAL(p,0,nt_extmode); p += 4;
1160 q = p; p += 4; /* q is placeholder for name length. */
1162 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1163 SIVAL(p,0,ea_size); /* Extended attributes */
1164 p +=4;
1166 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1167 SIVAL(p,0,sbuf.st_dev); p += 4;
1168 SIVAL(p,0,sbuf.st_ino); p += 4;
1169 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1170 SIVAL(q, 0, len);
1171 p += len;
1172 len = PTR_DIFF(p, pdata);
1173 len = (len + 3) & ~3;
1174 SIVAL(pdata,0,len);
1175 p = pdata + len;
1176 break;
1178 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1179 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1180 was_8_3 = mangle_is_8_3(fname, True);
1181 p += 4;
1182 SIVAL(p,0,reskey); p += 4;
1183 put_long_date(p,cdate); p += 8;
1184 put_long_date(p,adate); p += 8;
1185 put_long_date(p,mdate); p += 8;
1186 put_long_date(p,mdate); p += 8;
1187 SOFF_T(p,0,file_size); p += 8;
1188 SOFF_T(p,0,allocation_size); p += 8;
1189 SIVAL(p,0,nt_extmode); p += 4;
1190 q = p; p += 4; /* q is placeholder for name length */
1192 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1193 SIVAL(p,0,ea_size); /* Extended attributes */
1194 p +=4;
1196 /* Clear the short name buffer. This is
1197 * IMPORTANT as not doing so will trigger
1198 * a Win2k client bug. JRA.
1200 memset(p,'\0',26);
1201 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1202 pstring mangled_name;
1203 pstrcpy(mangled_name, fname);
1204 mangle_map(mangled_name,True,True,SNUM(conn));
1205 mangled_name[12] = 0;
1206 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1207 SSVAL(p, 0, len);
1208 } else {
1209 SSVAL(p,0,0);
1210 *(p+2) = 0;
1212 p += 26;
1213 SSVAL(p,0,0); p += 2; /* Reserved ? */
1214 SIVAL(p,0,sbuf.st_dev); p += 4;
1215 SIVAL(p,0,sbuf.st_ino); p += 4;
1216 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1217 SIVAL(q,0,len);
1218 p += len;
1219 len = PTR_DIFF(p, pdata);
1220 len = (len + 3) & ~3;
1221 SIVAL(pdata,0,len);
1222 p = pdata + len;
1223 break;
1225 /* CIFS UNIX Extension. */
1227 case SMB_FIND_FILE_UNIX:
1228 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1229 p+= 4;
1230 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1232 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1233 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1234 p+= 8;
1236 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1237 p+= 8;
1239 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1240 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1241 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1242 p+= 24;
1244 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1245 SIVAL(p,4,0);
1246 p+= 8;
1248 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1249 SIVAL(p,4,0);
1250 p+= 8;
1252 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1253 p+= 4;
1255 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1256 SIVAL(p,4,0);
1257 p+= 8;
1259 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1260 SIVAL(p,4,0);
1261 p+= 8;
1263 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1264 p+= 8;
1266 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1267 SIVAL(p,4,0);
1268 p+= 8;
1270 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1271 SIVAL(p,4,0);
1272 p+= 8;
1274 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1275 p += len;
1277 len = PTR_DIFF(p, pdata);
1278 len = (len + 3) & ~3;
1279 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1280 p = pdata + len;
1281 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1283 break;
1285 default:
1286 return(False);
1290 if (PTR_DIFF(p,pdata) > space_remaining) {
1291 /* Move the dirptr back to prev_dirpos */
1292 dptr_SeekDir(conn->dirptr, prev_dirpos);
1293 *out_of_space = True;
1294 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1295 return False; /* Not finished - just out of space */
1298 /* Setup the last entry pointer, as an offset from base_data */
1299 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1300 /* Advance the data pointer to the next slot */
1301 *ppdata = p;
1303 return(found);
1306 /****************************************************************************
1307 Reply to a TRANS2_FINDFIRST.
1308 ****************************************************************************/
1310 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1311 char **pparams, int total_params, char **ppdata, int total_data,
1312 unsigned int max_data_bytes)
1314 /* We must be careful here that we don't return more than the
1315 allowed number of data bytes. If this means returning fewer than
1316 maxentries then so be it. We assume that the redirector has
1317 enough room for the fixed number of parameter bytes it has
1318 requested. */
1319 char *params = *pparams;
1320 char *pdata = *ppdata;
1321 int dirtype = SVAL(params,0);
1322 int maxentries = SVAL(params,2);
1323 uint16 findfirst_flags = SVAL(params,4);
1324 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1325 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1326 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1327 int info_level = SVAL(params,6);
1328 pstring directory;
1329 pstring mask;
1330 char *p;
1331 int last_entry_off=0;
1332 int dptr_num = -1;
1333 int numentries = 0;
1334 int i;
1335 BOOL finished = False;
1336 BOOL dont_descend = False;
1337 BOOL out_of_space = False;
1338 int space_remaining;
1339 BOOL bad_path = False;
1340 SMB_STRUCT_STAT sbuf;
1341 NTSTATUS ntstatus = NT_STATUS_OK;
1343 if (total_params < 12)
1344 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1346 *directory = *mask = 0;
1348 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1349 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1350 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1351 info_level, max_data_bytes));
1353 if (!maxentries) {
1354 /* W2K3 seems to treat zero as 1. */
1355 maxentries = 1;
1358 switch (info_level) {
1359 case SMB_INFO_STANDARD:
1360 case SMB_INFO_QUERY_EA_SIZE:
1361 case SMB_FIND_FILE_DIRECTORY_INFO:
1362 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1363 case SMB_FIND_FILE_NAMES_INFO:
1364 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1365 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1366 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1367 break;
1368 case SMB_FIND_FILE_UNIX:
1369 if (!lp_unix_extensions())
1370 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1371 break;
1372 default:
1373 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1376 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1377 if (!NT_STATUS_IS_OK(ntstatus)) {
1378 return ERROR_NT(ntstatus);
1381 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
1383 unix_convert(directory,conn,0,&bad_path,&sbuf);
1384 if (bad_path) {
1385 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1387 if(!check_name(directory,conn)) {
1388 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1391 p = strrchr_m(directory,'/');
1392 if(p == NULL) {
1393 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1394 if((directory[0] == '.') && (directory[1] == '\0'))
1395 pstrcpy(mask,"*");
1396 else
1397 pstrcpy(mask,directory);
1398 pstrcpy(directory,"./");
1399 } else {
1400 pstrcpy(mask,p+1);
1401 *p = 0;
1404 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1406 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1407 if( pdata == NULL )
1408 return(ERROR_DOS(ERRDOS,ERRnomem));
1410 *ppdata = pdata;
1411 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1413 /* Realloc the params space */
1414 params = SMB_REALLOC(*pparams, 10);
1415 if (params == NULL)
1416 return ERROR_DOS(ERRDOS,ERRnomem);
1417 *pparams = params;
1419 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1420 if (dptr_num < 0)
1421 return(UNIXERROR(ERRDOS,ERRbadfile));
1423 /* Save the wildcard match and attribs we are using on this directory -
1424 needed as lanman2 assumes these are being saved between calls */
1426 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1427 dptr_close(&dptr_num);
1428 return ERROR_DOS(ERRDOS,ERRnomem);
1431 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1433 /* We don't need to check for VOL here as this is returned by
1434 a different TRANS2 call. */
1436 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1437 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1438 dont_descend = True;
1440 p = pdata;
1441 space_remaining = max_data_bytes;
1442 out_of_space = False;
1444 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1445 BOOL got_exact_match = False;
1447 /* this is a heuristic to avoid seeking the dirptr except when
1448 absolutely necessary. It allows for a filename of about 40 chars */
1449 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1450 out_of_space = True;
1451 finished = False;
1452 } else {
1453 finished = !get_lanman2_dir_entry(conn,
1454 inbuf, outbuf,
1455 mask,dirtype,info_level,
1456 requires_resume_key,dont_descend,
1457 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1458 &last_entry_off);
1461 if (finished && out_of_space)
1462 finished = False;
1464 if (!finished && !out_of_space)
1465 numentries++;
1468 * As an optimisation if we know we aren't looking
1469 * for a wildcard name (ie. the name matches the wildcard exactly)
1470 * then we can finish on any (first) match.
1471 * This speeds up large directory searches. JRA.
1474 if(got_exact_match)
1475 finished = True;
1477 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1480 /* Check if we can close the dirptr */
1481 if(close_after_first || (finished && close_if_end)) {
1482 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1483 dptr_close(&dptr_num);
1487 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1488 * from observation of NT.
1491 if(numentries == 0) {
1492 dptr_close(&dptr_num);
1493 return ERROR_DOS(ERRDOS,ERRbadfile);
1496 /* At this point pdata points to numentries directory entries. */
1498 /* Set up the return parameter block */
1499 SSVAL(params,0,dptr_num);
1500 SSVAL(params,2,numentries);
1501 SSVAL(params,4,finished);
1502 SSVAL(params,6,0); /* Never an EA error */
1503 SSVAL(params,8,last_entry_off);
1505 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1507 if ((! *directory) && dptr_path(dptr_num))
1508 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1510 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1511 smb_fn_name(CVAL(inbuf,smb_com)),
1512 mask, directory, dirtype, numentries ) );
1515 * Force a name mangle here to ensure that the
1516 * mask as an 8.3 name is top of the mangled cache.
1517 * The reasons for this are subtle. Don't remove
1518 * this code unless you know what you are doing
1519 * (see PR#13758). JRA.
1522 if(!mangle_is_8_3_wildcards( mask, False))
1523 mangle_map(mask, True, True, SNUM(conn));
1525 return(-1);
1528 /****************************************************************************
1529 Reply to a TRANS2_FINDNEXT.
1530 ****************************************************************************/
1532 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1533 char **pparams, int total_params, char **ppdata, int total_data,
1534 unsigned int max_data_bytes)
1536 /* We must be careful here that we don't return more than the
1537 allowed number of data bytes. If this means returning fewer than
1538 maxentries then so be it. We assume that the redirector has
1539 enough room for the fixed number of parameter bytes it has
1540 requested. */
1541 char *params = *pparams;
1542 char *pdata = *ppdata;
1543 int dptr_num = SVAL(params,0);
1544 int maxentries = SVAL(params,2);
1545 uint16 info_level = SVAL(params,4);
1546 uint32 resume_key = IVAL(params,6);
1547 uint16 findnext_flags = SVAL(params,10);
1548 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1549 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1550 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1551 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1552 pstring resume_name;
1553 pstring mask;
1554 pstring directory;
1555 char *p;
1556 uint16 dirtype;
1557 int numentries = 0;
1558 int i, last_entry_off=0;
1559 BOOL finished = False;
1560 BOOL dont_descend = False;
1561 BOOL out_of_space = False;
1562 int space_remaining;
1563 NTSTATUS ntstatus = NT_STATUS_OK;
1565 if (total_params < 12)
1566 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1568 *mask = *directory = *resume_name = 0;
1570 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1571 if (!NT_STATUS_IS_OK(ntstatus)) {
1572 return ERROR_NT(ntstatus);
1575 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1576 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1577 resume_key = %d resume name = %s continue=%d level = %d\n",
1578 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1579 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1581 if (!maxentries) {
1582 /* W2K3 seems to treat zero as 1. */
1583 maxentries = 1;
1586 switch (info_level) {
1587 case SMB_INFO_STANDARD:
1588 case SMB_INFO_QUERY_EA_SIZE:
1589 case SMB_FIND_FILE_DIRECTORY_INFO:
1590 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1591 case SMB_FIND_FILE_NAMES_INFO:
1592 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1593 break;
1594 case SMB_FIND_FILE_UNIX:
1595 if (!lp_unix_extensions())
1596 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1597 break;
1598 default:
1599 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1602 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1603 if(pdata == NULL)
1604 return ERROR_DOS(ERRDOS,ERRnomem);
1606 *ppdata = pdata;
1607 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1609 /* Realloc the params space */
1610 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1611 if( params == NULL )
1612 return ERROR_DOS(ERRDOS,ERRnomem);
1614 *pparams = params;
1616 /* Check that the dptr is valid */
1617 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1618 return ERROR_DOS(ERRDOS,ERRnofiles);
1620 string_set(&conn->dirpath,dptr_path(dptr_num));
1622 /* Get the wildcard mask from the dptr */
1623 if((p = dptr_wcard(dptr_num))== NULL) {
1624 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1625 return ERROR_DOS(ERRDOS,ERRnofiles);
1628 pstrcpy(mask, p);
1629 pstrcpy(directory,conn->dirpath);
1631 /* Get the attr mask from the dptr */
1632 dirtype = dptr_attr(dptr_num);
1634 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1635 dptr_num, mask, dirtype,
1636 (long)conn->dirptr,
1637 dptr_TellDir(conn->dirptr)));
1639 /* We don't need to check for VOL here as this is returned by
1640 a different TRANS2 call. */
1642 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1643 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1644 dont_descend = True;
1646 p = pdata;
1647 space_remaining = max_data_bytes;
1648 out_of_space = False;
1651 * Seek to the correct position. We no longer use the resume key but
1652 * depend on the last file name instead.
1655 if(*resume_name && !continue_bit) {
1656 SMB_STRUCT_STAT st;
1658 long current_pos = 0;
1660 * Remember, mangle_map is called by
1661 * get_lanman2_dir_entry(), so the resume name
1662 * could be mangled. Ensure we check the unmangled name.
1665 if (mangle_is_mangled(resume_name)) {
1666 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1670 * Fix for NT redirector problem triggered by resume key indexes
1671 * changing between directory scans. We now return a resume key of 0
1672 * and instead look for the filename to continue from (also given
1673 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1674 * findfirst/findnext (as is usual) then the directory pointer
1675 * should already be at the correct place.
1678 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
1679 } /* end if resume_name && !continue_bit */
1681 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1682 BOOL got_exact_match = False;
1684 /* this is a heuristic to avoid seeking the dirptr except when
1685 absolutely necessary. It allows for a filename of about 40 chars */
1686 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1687 out_of_space = True;
1688 finished = False;
1689 } else {
1690 finished = !get_lanman2_dir_entry(conn,
1691 inbuf, outbuf,
1692 mask,dirtype,info_level,
1693 requires_resume_key,dont_descend,
1694 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1695 &last_entry_off);
1698 if (finished && out_of_space)
1699 finished = False;
1701 if (!finished && !out_of_space)
1702 numentries++;
1705 * As an optimisation if we know we aren't looking
1706 * for a wildcard name (ie. the name matches the wildcard exactly)
1707 * then we can finish on any (first) match.
1708 * This speeds up large directory searches. JRA.
1711 if(got_exact_match)
1712 finished = True;
1714 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1717 /* Check if we can close the dirptr */
1718 if(close_after_request || (finished && close_if_end)) {
1719 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1720 dptr_close(&dptr_num); /* This frees up the saved mask */
1723 /* Set up the return parameter block */
1724 SSVAL(params,0,numentries);
1725 SSVAL(params,2,finished);
1726 SSVAL(params,4,0); /* Never an EA error */
1727 SSVAL(params,6,last_entry_off);
1729 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1731 if ((! *directory) && dptr_path(dptr_num))
1732 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1734 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1735 smb_fn_name(CVAL(inbuf,smb_com)),
1736 mask, directory, dirtype, numentries ) );
1738 return(-1);
1741 /****************************************************************************
1742 Reply to a TRANS2_QFSINFO (query filesystem info).
1743 ****************************************************************************/
1745 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1746 char **pparams, int total_params, char **ppdata, int total_data,
1747 unsigned int max_data_bytes)
1749 char *pdata = *ppdata;
1750 char *params = *pparams;
1751 uint16 info_level = SVAL(params,0);
1752 int data_len, len;
1753 SMB_STRUCT_STAT st;
1754 char *vname = volume_label(SNUM(conn));
1755 int snum = SNUM(conn);
1756 char *fstype = lp_fstype(SNUM(conn));
1757 int quota_flag = 0;
1759 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1761 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1762 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1763 return ERROR_DOS(ERRSRV,ERRinvdevice);
1766 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1767 if ( pdata == NULL )
1768 return ERROR_DOS(ERRDOS,ERRnomem);
1770 *ppdata = pdata;
1771 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1773 switch (info_level) {
1774 case SMB_INFO_ALLOCATION:
1776 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1777 data_len = 18;
1778 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1779 block_size = lp_block_size(snum);
1780 if (bsize < block_size) {
1781 SMB_BIG_UINT factor = block_size/bsize;
1782 bsize = block_size;
1783 dsize /= factor;
1784 dfree /= factor;
1786 if (bsize > block_size) {
1787 SMB_BIG_UINT factor = bsize/block_size;
1788 bsize = block_size;
1789 dsize *= factor;
1790 dfree *= factor;
1792 bytes_per_sector = 512;
1793 sectors_per_unit = bsize/bytes_per_sector;
1795 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1796 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1797 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1799 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1800 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1801 SIVAL(pdata,l1_cUnit,dsize);
1802 SIVAL(pdata,l1_cUnitAvail,dfree);
1803 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1804 break;
1807 case SMB_INFO_VOLUME:
1808 /* Return volume name */
1810 * Add volume serial number - hash of a combination of
1811 * the called hostname and the service name.
1813 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
1814 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1815 SCVAL(pdata,l2_vol_cch,len);
1816 data_len = l2_vol_szVolLabel + len;
1817 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1818 (unsigned)st.st_ctime, len, vname));
1819 break;
1821 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1822 case SMB_FS_ATTRIBUTE_INFORMATION:
1825 #if defined(HAVE_SYS_QUOTAS)
1826 quota_flag = FILE_VOLUME_QUOTAS;
1827 #endif
1829 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1830 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1831 quota_flag); /* FS ATTRIBUTES */
1833 SIVAL(pdata,4,255); /* Max filename component length */
1834 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1835 and will think we can't do long filenames */
1836 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1837 SIVAL(pdata,8,len);
1838 data_len = 12 + len;
1839 break;
1841 case SMB_QUERY_FS_LABEL_INFO:
1842 case SMB_FS_LABEL_INFORMATION:
1843 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1844 data_len = 4 + len;
1845 SIVAL(pdata,0,len);
1846 break;
1848 case SMB_QUERY_FS_VOLUME_INFO:
1849 case SMB_FS_VOLUME_INFORMATION:
1852 * Add volume serial number - hash of a combination of
1853 * the called hostname and the service name.
1855 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1856 (str_checksum(get_local_machine_name())<<16));
1858 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1859 SIVAL(pdata,12,len);
1860 data_len = 18+len;
1861 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1862 (int)strlen(vname),vname, lp_servicename(snum)));
1863 break;
1865 case SMB_QUERY_FS_SIZE_INFO:
1866 case SMB_FS_SIZE_INFORMATION:
1868 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1869 data_len = 24;
1870 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1871 block_size = lp_block_size(snum);
1872 if (bsize < block_size) {
1873 SMB_BIG_UINT factor = block_size/bsize;
1874 bsize = block_size;
1875 dsize /= factor;
1876 dfree /= factor;
1878 if (bsize > block_size) {
1879 SMB_BIG_UINT factor = bsize/block_size;
1880 bsize = block_size;
1881 dsize *= factor;
1882 dfree *= factor;
1884 bytes_per_sector = 512;
1885 sectors_per_unit = bsize/bytes_per_sector;
1886 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1887 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1888 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1889 SBIG_UINT(pdata,0,dsize);
1890 SBIG_UINT(pdata,8,dfree);
1891 SIVAL(pdata,16,sectors_per_unit);
1892 SIVAL(pdata,20,bytes_per_sector);
1893 break;
1896 case SMB_FS_FULL_SIZE_INFORMATION:
1898 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1899 data_len = 32;
1900 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1901 block_size = lp_block_size(snum);
1902 if (bsize < block_size) {
1903 SMB_BIG_UINT factor = block_size/bsize;
1904 bsize = block_size;
1905 dsize /= factor;
1906 dfree /= factor;
1908 if (bsize > block_size) {
1909 SMB_BIG_UINT factor = bsize/block_size;
1910 bsize = block_size;
1911 dsize *= factor;
1912 dfree *= factor;
1914 bytes_per_sector = 512;
1915 sectors_per_unit = bsize/bytes_per_sector;
1916 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1917 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1918 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1919 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1920 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1921 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1922 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1923 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1924 break;
1927 case SMB_QUERY_FS_DEVICE_INFO:
1928 case SMB_FS_DEVICE_INFORMATION:
1929 data_len = 8;
1930 SIVAL(pdata,0,0); /* dev type */
1931 SIVAL(pdata,4,0); /* characteristics */
1932 break;
1934 #ifdef HAVE_SYS_QUOTAS
1935 case SMB_FS_QUOTA_INFORMATION:
1937 * what we have to send --metze:
1939 * Unknown1: 24 NULL bytes
1940 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1941 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1942 * Quota Flags: 2 byte :
1943 * Unknown3: 6 NULL bytes
1945 * 48 bytes total
1947 * details for Quota Flags:
1949 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1950 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1951 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1952 * 0x0001 Enable Quotas: enable quota for this fs
1956 /* we need to fake up a fsp here,
1957 * because its not send in this call
1959 files_struct fsp;
1960 SMB_NTQUOTA_STRUCT quotas;
1962 ZERO_STRUCT(fsp);
1963 ZERO_STRUCT(quotas);
1965 fsp.conn = conn;
1966 fsp.fnum = -1;
1967 fsp.fd = -1;
1969 /* access check */
1970 if (current_user.uid != 0) {
1971 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1972 lp_servicename(SNUM(conn)),conn->user));
1973 return ERROR_DOS(ERRDOS,ERRnoaccess);
1976 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1977 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1978 return ERROR_DOS(ERRSRV,ERRerror);
1981 data_len = 48;
1983 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1985 /* Unknown1 24 NULL bytes*/
1986 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1987 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1988 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1990 /* Default Soft Quota 8 bytes */
1991 SBIG_UINT(pdata,24,quotas.softlim);
1993 /* Default Hard Quota 8 bytes */
1994 SBIG_UINT(pdata,32,quotas.hardlim);
1996 /* Quota flag 2 bytes */
1997 SSVAL(pdata,40,quotas.qflags);
1999 /* Unknown3 6 NULL bytes */
2000 SSVAL(pdata,42,0);
2001 SIVAL(pdata,44,0);
2003 break;
2005 #endif /* HAVE_SYS_QUOTAS */
2006 case SMB_FS_OBJECTID_INFORMATION:
2007 data_len = 64;
2008 break;
2011 * Query the version and capabilities of the CIFS UNIX extensions
2012 * in use.
2015 case SMB_QUERY_CIFS_UNIX_INFO:
2016 if (!lp_unix_extensions())
2017 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2018 data_len = 12;
2019 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2020 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2021 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2022 break;
2024 case SMB_MAC_QUERY_FS_INFO:
2026 * Thursby MAC extension... ONLY on NTFS filesystems
2027 * once we do streams then we don't need this
2029 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2030 data_len = 88;
2031 SIVAL(pdata,84,0x100); /* Don't support mac... */
2032 break;
2034 /* drop through */
2035 default:
2036 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2040 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2042 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2044 return -1;
2047 #ifdef HAVE_SYS_QUOTAS
2048 /****************************************************************************
2049 Reply to a TRANS2_SETFSINFO (set filesystem info).
2050 ****************************************************************************/
2052 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2053 char **pparams, int total_params, char **ppdata, int total_data,
2054 unsigned int max_data_bytes)
2056 char *pdata = *ppdata;
2057 char *params = *pparams;
2058 files_struct *fsp = NULL;
2059 uint16 info_level;
2060 int outsize;
2061 SMB_NTQUOTA_STRUCT quotas;
2063 ZERO_STRUCT(quotas);
2065 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2067 /* access check */
2068 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2069 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2070 lp_servicename(SNUM(conn)),conn->user));
2071 return ERROR_DOS(ERRSRV,ERRaccess);
2074 /* */
2075 if (total_params < 4) {
2076 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2077 total_params));
2078 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2081 fsp = file_fsp(params,0);
2083 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2084 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2085 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2088 info_level = SVAL(params,2);
2090 switch(info_level) {
2091 case SMB_FS_QUOTA_INFORMATION:
2092 /* note: normaly there're 48 bytes,
2093 * but we didn't use the last 6 bytes for now
2094 * --metze
2096 if (total_data < 42) {
2097 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2098 total_data));
2099 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2102 /* unknown_1 24 NULL bytes in pdata*/
2104 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2105 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2106 #ifdef LARGE_SMB_OFF_T
2107 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2108 #else /* LARGE_SMB_OFF_T */
2109 if ((IVAL(pdata,28) != 0)&&
2110 ((quotas.softlim != 0xFFFFFFFF)||
2111 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2112 /* more than 32 bits? */
2113 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2115 #endif /* LARGE_SMB_OFF_T */
2117 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2118 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2119 #ifdef LARGE_SMB_OFF_T
2120 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2121 #else /* LARGE_SMB_OFF_T */
2122 if ((IVAL(pdata,36) != 0)&&
2123 ((quotas.hardlim != 0xFFFFFFFF)||
2124 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2125 /* more than 32 bits? */
2126 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2128 #endif /* LARGE_SMB_OFF_T */
2130 /* quota_flags 2 bytes **/
2131 quotas.qflags = SVAL(pdata,40);
2133 /* unknown_2 6 NULL bytes follow*/
2135 /* now set the quotas */
2136 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2137 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2138 return ERROR_DOS(ERRSRV,ERRerror);
2141 break;
2142 default:
2143 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2144 info_level));
2145 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2146 break;
2150 * sending this reply works fine,
2151 * but I'm not sure it's the same
2152 * like windows do...
2153 * --metze
2155 outsize = set_message(outbuf,10,0,True);
2157 return outsize;
2159 #endif /* HAVE_SYS_QUOTAS */
2161 /****************************************************************************
2162 Utility function to set bad path error.
2163 ****************************************************************************/
2165 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2167 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2168 err, (int)bad_path ));
2170 if(err == ENOENT) {
2171 if (bad_path) {
2172 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2173 } else {
2174 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2177 return UNIXERROR(def_class,def_code);
2180 #if defined(HAVE_POSIX_ACLS)
2181 /****************************************************************************
2182 Utility function to count the number of entries in a POSIX acl.
2183 ****************************************************************************/
2185 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2187 unsigned int ace_count = 0;
2188 int entry_id = SMB_ACL_FIRST_ENTRY;
2189 SMB_ACL_ENTRY_T entry;
2191 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2192 /* get_next... */
2193 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2194 entry_id = SMB_ACL_NEXT_ENTRY;
2196 ace_count++;
2198 return ace_count;
2201 /****************************************************************************
2202 Utility function to marshall a POSIX acl into wire format.
2203 ****************************************************************************/
2205 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2207 int entry_id = SMB_ACL_FIRST_ENTRY;
2208 SMB_ACL_ENTRY_T entry;
2210 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2211 SMB_ACL_TAG_T tagtype;
2212 SMB_ACL_PERMSET_T permset;
2213 unsigned char perms = 0;
2214 unsigned int own_grp;
2216 /* get_next... */
2217 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2218 entry_id = SMB_ACL_NEXT_ENTRY;
2221 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2222 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2223 return False;
2226 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2227 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2228 return False;
2231 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2232 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2233 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2235 SCVAL(pdata,1,perms);
2237 switch (tagtype) {
2238 case SMB_ACL_USER_OBJ:
2239 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2240 own_grp = (unsigned int)pst->st_uid;
2241 SIVAL(pdata,2,own_grp);
2242 SIVAL(pdata,6,0);
2243 break;
2244 case SMB_ACL_USER:
2246 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2247 if (!puid) {
2248 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2250 own_grp = (unsigned int)*puid;
2251 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2252 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2253 SIVAL(pdata,2,own_grp);
2254 SIVAL(pdata,6,0);
2255 break;
2257 case SMB_ACL_GROUP_OBJ:
2258 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2259 own_grp = (unsigned int)pst->st_gid;
2260 SIVAL(pdata,2,own_grp);
2261 SIVAL(pdata,6,0);
2262 break;
2263 case SMB_ACL_GROUP:
2265 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2266 if (!pgid) {
2267 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2269 own_grp = (unsigned int)*pgid;
2270 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2271 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2272 SIVAL(pdata,2,own_grp);
2273 SIVAL(pdata,6,0);
2274 break;
2276 case SMB_ACL_MASK:
2277 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2278 SIVAL(pdata,2,0xFFFFFFFF);
2279 SIVAL(pdata,6,0xFFFFFFFF);
2280 break;
2281 case SMB_ACL_OTHER:
2282 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2283 SIVAL(pdata,2,0xFFFFFFFF);
2284 SIVAL(pdata,6,0xFFFFFFFF);
2285 break;
2286 default:
2287 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2288 return False;
2290 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2293 return True;
2295 #endif
2297 /****************************************************************************
2298 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2299 file name or file id).
2300 ****************************************************************************/
2302 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2303 char **pparams, int total_params, char **ppdata, int total_data,
2304 unsigned int max_data_bytes)
2306 char *params = *pparams;
2307 char *pdata = *ppdata;
2308 uint16 tran_call = SVAL(inbuf, smb_setup0);
2309 uint16 info_level;
2310 int mode=0;
2311 SMB_OFF_T file_size=0;
2312 SMB_BIG_UINT allocation_size=0;
2313 unsigned int data_size;
2314 unsigned int param_size = 2;
2315 SMB_STRUCT_STAT sbuf;
2316 pstring fname, dos_fname;
2317 char *fullpathname;
2318 char *base_name;
2319 char *p;
2320 SMB_OFF_T pos = 0;
2321 BOOL bad_path = False;
2322 BOOL delete_pending = False;
2323 int len;
2324 time_t c_time;
2325 files_struct *fsp = NULL;
2326 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2328 if (!params)
2329 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2331 ZERO_STRUCT(sbuf);
2333 if (tran_call == TRANSACT2_QFILEINFO) {
2334 if (total_params < 4)
2335 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2337 fsp = file_fsp(params,0);
2338 info_level = SVAL(params,2);
2340 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2342 if(fsp && (fsp->fake_file_handle)) {
2344 * This is actually for the QUOTA_FAKE_FILE --metze
2347 pstrcpy(fname, fsp->fsp_name);
2348 /* We know this name is ok, it's already passed the checks. */
2350 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2352 * This is actually a QFILEINFO on a directory
2353 * handle (returned from an NT SMB). NT5.0 seems
2354 * to do this call. JRA.
2356 /* We know this name is ok, it's already passed the checks. */
2357 pstrcpy(fname, fsp->fsp_name);
2359 if (INFO_LEVEL_IS_UNIX(info_level)) {
2360 /* Always do lstat for UNIX calls. */
2361 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2362 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2363 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2365 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2366 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2367 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2370 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2371 } else {
2373 * Original code - this is an open file.
2375 CHECK_FSP(fsp,conn);
2377 pstrcpy(fname, fsp->fsp_name);
2378 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2379 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2380 return(UNIXERROR(ERRDOS,ERRbadfid));
2382 pos = fsp->position_information;
2383 delete_pending = fsp->delete_on_close;
2384 desired_access = fsp->desired_access;
2386 } else {
2387 NTSTATUS status = NT_STATUS_OK;
2389 /* qpathinfo */
2390 if (total_params < 6)
2391 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2393 info_level = SVAL(params,0);
2395 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2397 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2398 if (!NT_STATUS_IS_OK(status)) {
2399 return ERROR_NT(status);
2402 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2404 unix_convert(fname,conn,0,&bad_path,&sbuf);
2405 if (bad_path) {
2406 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2408 if (!check_name(fname,conn)) {
2409 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2410 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2413 if (INFO_LEVEL_IS_UNIX(info_level)) {
2414 /* Always do lstat for UNIX calls. */
2415 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2416 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2417 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2419 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2420 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2421 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2425 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2426 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2428 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2429 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2431 p = strrchr_m(fname,'/');
2432 if (!p)
2433 base_name = fname;
2434 else
2435 base_name = p+1;
2437 mode = dos_mode(conn,fname,&sbuf);
2438 if (!mode)
2439 mode = FILE_ATTRIBUTE_NORMAL;
2441 fullpathname = fname;
2442 file_size = get_file_size(sbuf);
2443 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2444 if (mode & aDIR) {
2445 /* This is necessary, as otherwise the desktop.ini file in
2446 * this folder is ignored */
2447 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2448 file_size = 0;
2451 params = SMB_REALLOC(*pparams,2);
2452 if (params == NULL)
2453 return ERROR_DOS(ERRDOS,ERRnomem);
2454 *pparams = params;
2455 memset((char *)params,'\0',2);
2456 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2457 pdata = SMB_REALLOC(*ppdata, data_size);
2458 if ( pdata == NULL )
2459 return ERROR_DOS(ERRDOS,ERRnomem);
2460 *ppdata = pdata;
2462 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2463 /* uggh, EAs for OS2 */
2464 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2465 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2468 memset((char *)pdata,'\0',data_size);
2470 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2472 if (fsp) {
2473 if (fsp->pending_modtime) {
2474 /* the pending modtime overrides the current modtime */
2475 sbuf.st_mtime = fsp->pending_modtime;
2477 } else {
2478 /* Do we have this path open ? */
2479 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2480 if (fsp1 && fsp1->pending_modtime) {
2481 /* the pending modtime overrides the current modtime */
2482 sbuf.st_mtime = fsp1->pending_modtime;
2486 if (lp_dos_filetime_resolution(SNUM(conn))) {
2487 c_time &= ~1;
2488 sbuf.st_atime &= ~1;
2489 sbuf.st_ctime &= ~1;
2490 sbuf.st_mtime &= ~1;
2493 /* NT expects the name to be in an exact form of the *full*
2494 filename. See the trans2 torture test */
2495 if (strequal(base_name,".")) {
2496 pstrcpy(dos_fname, "\\");
2497 } else {
2498 pstr_sprintf(dos_fname, "\\%s", fname);
2499 string_replace(dos_fname, '/', '\\');
2502 switch (info_level) {
2503 case SMB_INFO_STANDARD:
2504 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2505 data_size = 22;
2506 put_dos_date2(pdata,l1_fdateCreation,c_time);
2507 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2508 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2509 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2510 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2511 SSVAL(pdata,l1_attrFile,mode);
2512 break;
2514 case SMB_INFO_QUERY_EA_SIZE:
2516 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2517 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2518 data_size = 26;
2519 put_dos_date2(pdata,l1_fdateCreation,c_time);
2520 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2521 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2522 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2523 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2524 SSVAL(pdata,l1_attrFile,mode);
2525 SIVAL(pdata,l1_attrFile+2,ea_size);
2526 break;
2529 case SMB_INFO_IS_NAME_VALID:
2530 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2531 if (tran_call == TRANSACT2_QFILEINFO) {
2532 /* os/2 needs this ? really ?*/
2533 return ERROR_DOS(ERRDOS,ERRbadfunc);
2535 data_size = 0;
2536 param_size = 0;
2537 break;
2539 case SMB_INFO_QUERY_EAS_FROM_LIST:
2540 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2541 data_size = 24;
2542 put_dos_date2(pdata,0,c_time);
2543 put_dos_date2(pdata,4,sbuf.st_atime);
2544 put_dos_date2(pdata,8,sbuf.st_mtime);
2545 SIVAL(pdata,12,(uint32)file_size);
2546 SIVAL(pdata,16,(uint32)allocation_size);
2547 SIVAL(pdata,20,mode);
2548 break;
2550 case SMB_INFO_QUERY_ALL_EAS:
2551 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2552 /* We have data_size bytes to put EA's into. */
2553 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2554 break;
2556 case SMB_FILE_BASIC_INFORMATION:
2557 case SMB_QUERY_FILE_BASIC_INFO:
2559 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2560 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2561 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2562 } else {
2563 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2564 data_size = 40;
2565 SIVAL(pdata,36,0);
2567 put_long_date(pdata,c_time);
2568 put_long_date(pdata+8,sbuf.st_atime);
2569 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2570 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2571 SIVAL(pdata,32,mode);
2573 DEBUG(5,("SMB_QFBI - "));
2575 time_t create_time = c_time;
2576 DEBUG(5,("create: %s ", ctime(&create_time)));
2578 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2579 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2580 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2581 DEBUG(5,("mode: %x\n", mode));
2583 break;
2585 case SMB_FILE_STANDARD_INFORMATION:
2586 case SMB_QUERY_FILE_STANDARD_INFO:
2588 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2589 data_size = 24;
2590 SOFF_T(pdata,0,allocation_size);
2591 SOFF_T(pdata,8,file_size);
2592 if (delete_pending & sbuf.st_nlink)
2593 SIVAL(pdata,16,sbuf.st_nlink - 1);
2594 else
2595 SIVAL(pdata,16,sbuf.st_nlink);
2596 SCVAL(pdata,20,0);
2597 SCVAL(pdata,21,(mode&aDIR)?1:0);
2598 break;
2600 case SMB_FILE_EA_INFORMATION:
2601 case SMB_QUERY_FILE_EA_INFO:
2603 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2604 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2605 data_size = 4;
2606 SIVAL(pdata,0,ea_size);
2607 break;
2610 /* Get the 8.3 name - used if NT SMB was negotiated. */
2611 case SMB_QUERY_FILE_ALT_NAME_INFO:
2612 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2614 pstring short_name;
2616 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2617 pstrcpy(short_name,base_name);
2618 /* Mangle if not already 8.3 */
2619 if(!mangle_is_8_3(short_name, True)) {
2620 mangle_map(short_name,True,True,SNUM(conn));
2622 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2623 data_size = 4 + len;
2624 SIVAL(pdata,0,len);
2625 break;
2628 case SMB_QUERY_FILE_NAME_INFO:
2630 this must be *exactly* right for ACLs on mapped drives to work
2632 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2633 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2634 data_size = 4 + len;
2635 SIVAL(pdata,0,len);
2636 break;
2638 case SMB_FILE_ALLOCATION_INFORMATION:
2639 case SMB_QUERY_FILE_ALLOCATION_INFO:
2640 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2641 data_size = 8;
2642 SOFF_T(pdata,0,allocation_size);
2643 break;
2645 case SMB_FILE_END_OF_FILE_INFORMATION:
2646 case SMB_QUERY_FILE_END_OF_FILEINFO:
2647 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2648 data_size = 8;
2649 SOFF_T(pdata,0,file_size);
2650 break;
2652 case SMB_QUERY_FILE_ALL_INFO:
2653 case SMB_FILE_ALL_INFORMATION:
2655 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2656 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2657 put_long_date(pdata,c_time);
2658 put_long_date(pdata+8,sbuf.st_atime);
2659 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2660 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2661 SIVAL(pdata,32,mode);
2662 pdata += 40;
2663 SOFF_T(pdata,0,allocation_size);
2664 SOFF_T(pdata,8,file_size);
2665 if (delete_pending && sbuf.st_nlink)
2666 SIVAL(pdata,16,sbuf.st_nlink - 1);
2667 else
2668 SIVAL(pdata,16,sbuf.st_nlink);
2669 SCVAL(pdata,20,delete_pending);
2670 SCVAL(pdata,21,(mode&aDIR)?1:0);
2671 pdata += 24;
2672 SIVAL(pdata,0,ea_size);
2673 pdata += 4; /* EA info */
2674 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2675 SIVAL(pdata,0,len);
2676 pdata += 4 + len;
2677 data_size = PTR_DIFF(pdata,(*ppdata));
2678 break;
2680 case SMB_FILE_INTERNAL_INFORMATION:
2681 /* This should be an index number - looks like
2682 dev/ino to me :-)
2684 I think this causes us to fail the IFSKIT
2685 BasicFileInformationTest. -tpot */
2687 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2688 SIVAL(pdata,0,sbuf.st_dev);
2689 SIVAL(pdata,4,sbuf.st_ino);
2690 data_size = 8;
2691 break;
2693 case SMB_FILE_ACCESS_INFORMATION:
2694 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2695 SIVAL(pdata,0,desired_access);
2696 data_size = 4;
2697 break;
2699 case SMB_FILE_NAME_INFORMATION:
2700 /* Pathname with leading '\'. */
2702 size_t byte_len;
2703 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2704 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2705 SIVAL(pdata,0,byte_len);
2706 data_size = 4 + byte_len;
2707 break;
2710 case SMB_FILE_DISPOSITION_INFORMATION:
2711 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2712 data_size = 1;
2713 SCVAL(pdata,0,delete_pending);
2714 break;
2716 case SMB_FILE_POSITION_INFORMATION:
2717 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2718 data_size = 8;
2719 SOFF_T(pdata,0,pos);
2720 break;
2722 case SMB_FILE_MODE_INFORMATION:
2723 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2724 SIVAL(pdata,0,mode);
2725 data_size = 4;
2726 break;
2728 case SMB_FILE_ALIGNMENT_INFORMATION:
2729 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2730 SIVAL(pdata,0,0); /* No alignment needed. */
2731 data_size = 4;
2732 break;
2734 #if 0
2736 * NT4 server just returns "invalid query" to this - if we try to answer
2737 * it then NTws gets a BSOD! (tridge).
2738 * W2K seems to want this. JRA.
2740 case SMB_QUERY_FILE_STREAM_INFO:
2741 #endif
2742 case SMB_FILE_STREAM_INFORMATION:
2743 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2744 if (mode & aDIR) {
2745 data_size = 0;
2746 } else {
2747 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2748 SIVAL(pdata,0,0); /* ??? */
2749 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2750 SOFF_T(pdata,8,file_size);
2751 SIVAL(pdata,16,allocation_size);
2752 SIVAL(pdata,20,0); /* ??? */
2753 data_size = 24 + byte_len;
2755 break;
2757 case SMB_QUERY_COMPRESSION_INFO:
2758 case SMB_FILE_COMPRESSION_INFORMATION:
2759 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2760 SOFF_T(pdata,0,file_size);
2761 SIVAL(pdata,8,0); /* ??? */
2762 SIVAL(pdata,12,0); /* ??? */
2763 data_size = 16;
2764 break;
2766 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2767 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2768 put_long_date(pdata,c_time);
2769 put_long_date(pdata+8,sbuf.st_atime);
2770 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2771 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2772 SIVAL(pdata,32,allocation_size);
2773 SOFF_T(pdata,40,file_size);
2774 SIVAL(pdata,48,mode);
2775 SIVAL(pdata,52,0); /* ??? */
2776 data_size = 56;
2777 break;
2779 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2780 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2781 SIVAL(pdata,0,mode);
2782 SIVAL(pdata,4,0);
2783 data_size = 8;
2784 break;
2787 * CIFS UNIX Extensions.
2790 case SMB_QUERY_FILE_UNIX_BASIC:
2792 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2793 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2795 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2796 pdata += 8;
2798 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2799 pdata += 8;
2801 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2802 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2803 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2804 pdata += 24;
2806 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2807 SIVAL(pdata,4,0);
2808 pdata += 8;
2810 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2811 SIVAL(pdata,4,0);
2812 pdata += 8;
2814 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2815 pdata += 4;
2817 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2818 SIVAL(pdata,4,0);
2819 pdata += 8;
2821 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2822 SIVAL(pdata,4,0);
2823 pdata += 8;
2825 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2826 pdata += 8;
2828 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2829 SIVAL(pdata,4,0);
2830 pdata += 8;
2832 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2833 SIVAL(pdata,4,0);
2834 pdata += 8+1;
2835 data_size = PTR_DIFF(pdata,(*ppdata));
2838 int i;
2839 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2841 for (i=0; i<100; i++)
2842 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2843 DEBUG(4,("\n"));
2846 break;
2848 case SMB_QUERY_FILE_UNIX_LINK:
2850 pstring buffer;
2852 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2853 #ifdef S_ISLNK
2854 if(!S_ISLNK(sbuf.st_mode))
2855 return(UNIXERROR(ERRSRV,ERRbadlink));
2856 #else
2857 return(UNIXERROR(ERRDOS,ERRbadlink));
2858 #endif
2859 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2860 if (len == -1)
2861 return(UNIXERROR(ERRDOS,ERRnoaccess));
2862 buffer[len] = 0;
2863 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2864 pdata += len;
2865 data_size = PTR_DIFF(pdata,(*ppdata));
2867 break;
2870 #if defined(HAVE_POSIX_ACLS)
2871 case SMB_QUERY_POSIX_ACL:
2873 SMB_ACL_T file_acl = NULL;
2874 SMB_ACL_T def_acl = NULL;
2875 uint16 num_file_acls = 0;
2876 uint16 num_def_acls = 0;
2878 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
2879 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
2880 } else {
2881 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
2884 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2885 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
2886 fname ));
2887 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
2890 if (S_ISDIR(sbuf.st_mode)) {
2891 if (fsp && fsp->is_directory) {
2892 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2893 } else {
2894 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
2896 def_acl = free_empty_sys_acl(conn, def_acl);
2899 num_file_acls = count_acl_entries(conn, file_acl);
2900 num_def_acls = count_acl_entries(conn, def_acl);
2902 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
2903 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
2904 data_size,
2905 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
2906 SMB_POSIX_ACL_HEADER_SIZE) ));
2907 if (file_acl) {
2908 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2910 if (def_acl) {
2911 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2913 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2916 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2917 SSVAL(pdata,2,num_file_acls);
2918 SSVAL(pdata,4,num_def_acls);
2919 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
2920 if (file_acl) {
2921 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2923 if (def_acl) {
2924 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2926 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2928 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
2929 if (file_acl) {
2930 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2932 if (def_acl) {
2933 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2935 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2938 if (file_acl) {
2939 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2941 if (def_acl) {
2942 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2944 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
2945 break;
2947 #endif
2949 default:
2950 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2953 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2955 return(-1);
2958 /****************************************************************************
2959 Deal with the internal needs of setting the delete on close flag. Note that
2960 as the tdb locking is recursive, it is safe to call this from within
2961 open_file_shared. JRA.
2962 ****************************************************************************/
2964 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
2966 if (delete_on_close) {
2968 * Only allow delete on close for writable files.
2971 if (!lp_delete_readonly(SNUM(fsp->conn))) {
2972 if (dosmode & aRONLY) {
2973 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
2974 fsp->fsp_name ));
2975 return NT_STATUS_CANNOT_DELETE;
2980 * Only allow delete on close for writable shares.
2983 if (!CAN_WRITE(fsp->conn)) {
2984 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2985 fsp->fsp_name ));
2986 return NT_STATUS_ACCESS_DENIED;
2990 * Only allow delete on close for files/directories opened with delete intent.
2993 if (!(fsp->desired_access & DELETE_ACCESS)) {
2994 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2995 fsp->fsp_name ));
2996 return NT_STATUS_ACCESS_DENIED;
3000 if(fsp->is_directory) {
3001 fsp->directory_delete_on_close = delete_on_close;
3002 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3003 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3004 } else {
3005 fsp->delete_on_close = delete_on_close;
3006 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3007 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3010 return NT_STATUS_OK;
3013 /****************************************************************************
3014 Sets the delete on close flag over all share modes on this file.
3015 Modify the share mode entry for all files open
3016 on this device and inode to tell other smbds we have
3017 changed the delete on close flag. This will be noticed
3018 in the close code, the last closer will delete the file
3019 if flag is set.
3020 ****************************************************************************/
3022 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3024 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3025 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3027 if (fsp->is_directory || fsp->is_stat)
3028 return NT_STATUS_OK;
3030 if (lock_share_entry_fsp(fsp) == False)
3031 return NT_STATUS_ACCESS_DENIED;
3033 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3034 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3035 fsp->fsp_name ));
3036 unlock_share_entry_fsp(fsp);
3037 return NT_STATUS_ACCESS_DENIED;
3040 unlock_share_entry_fsp(fsp);
3041 return NT_STATUS_OK;
3044 /****************************************************************************
3045 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3046 code.
3047 ****************************************************************************/
3049 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3051 BOOL bad_path_oldname = False;
3052 BOOL bad_path_newname = False;
3053 SMB_STRUCT_STAT sbuf1, sbuf2;
3054 pstring last_component_oldname;
3055 pstring last_component_newname;
3056 NTSTATUS status = NT_STATUS_OK;
3058 ZERO_STRUCT(sbuf1);
3059 ZERO_STRUCT(sbuf2);
3061 /* No wildcards. */
3062 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3063 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3066 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3067 if (bad_path_oldname) {
3068 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3071 /* Quick check for "." and ".." */
3072 if (last_component_oldname[0] == '.') {
3073 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3074 return NT_STATUS_OBJECT_NAME_INVALID;
3078 /* source must already exist. */
3079 if (!VALID_STAT(sbuf1)) {
3080 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3083 if (!check_name(oldname,conn)) {
3084 return NT_STATUS_ACCESS_DENIED;
3087 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3088 if (bad_path_newname) {
3089 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3092 /* Quick check for "." and ".." */
3093 if (last_component_newname[0] == '.') {
3094 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3095 return NT_STATUS_OBJECT_NAME_INVALID;
3099 /* Disallow if newname already exists. */
3100 if (VALID_STAT(sbuf2)) {
3101 return NT_STATUS_OBJECT_NAME_COLLISION;
3104 if (!check_name(newname,conn)) {
3105 return NT_STATUS_ACCESS_DENIED;
3108 /* No links from a directory. */
3109 if (S_ISDIR(sbuf1.st_mode)) {
3110 return NT_STATUS_FILE_IS_A_DIRECTORY;
3113 /* Ensure this is within the share. */
3114 if (!reduce_name(conn, oldname) != 0)
3115 return NT_STATUS_ACCESS_DENIED;
3117 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3119 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3120 status = map_nt_error_from_unix(errno);
3121 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3122 nt_errstr(status), newname, oldname));
3125 return status;
3128 /****************************************************************************
3129 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3130 ****************************************************************************/
3132 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3133 char **pparams, int total_params, char **ppdata, int total_data,
3134 unsigned int max_data_bytes)
3136 char *params = *pparams;
3137 char *pdata = *ppdata;
3138 uint16 tran_call = SVAL(inbuf, smb_setup0);
3139 uint16 info_level;
3140 int dosmode=0;
3141 SMB_OFF_T size=0;
3142 struct utimbuf tvs;
3143 SMB_STRUCT_STAT sbuf;
3144 pstring fname;
3145 int fd = -1;
3146 BOOL bad_path = False;
3147 files_struct *fsp = NULL;
3148 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3149 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3150 mode_t unixmode = 0;
3151 NTSTATUS status = NT_STATUS_OK;
3153 if (!params)
3154 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3156 ZERO_STRUCT(sbuf);
3158 if (tran_call == TRANSACT2_SETFILEINFO) {
3159 if (total_params < 4)
3160 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3162 fsp = file_fsp(params,0);
3163 info_level = SVAL(params,2);
3165 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3167 * This is actually a SETFILEINFO on a directory
3168 * handle (returned from an NT SMB). NT5.0 seems
3169 * to do this call. JRA.
3171 pstrcpy(fname, fsp->fsp_name);
3172 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3173 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3174 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3176 } else if (fsp && fsp->print_file) {
3178 * Doing a DELETE_ON_CLOSE should cancel a print job.
3180 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3181 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3183 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3185 SSVAL(params,0,0);
3186 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3187 return(-1);
3188 } else
3189 return (UNIXERROR(ERRDOS,ERRbadpath));
3190 } else {
3192 * Original code - this is an open file.
3194 CHECK_FSP(fsp,conn);
3196 pstrcpy(fname, fsp->fsp_name);
3197 fd = fsp->fd;
3199 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3200 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3201 return(UNIXERROR(ERRDOS,ERRbadfid));
3204 } else {
3205 /* set path info */
3206 if (total_params < 6)
3207 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3209 info_level = SVAL(params,0);
3210 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3211 if (!NT_STATUS_IS_OK(status)) {
3212 return ERROR_NT(status);
3214 unix_convert(fname,conn,0,&bad_path,&sbuf);
3215 if (bad_path) {
3216 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3220 * For CIFS UNIX extensions the target name may not exist.
3223 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3224 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3225 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3228 if(!check_name(fname, conn)) {
3229 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3234 if (!CAN_WRITE(conn))
3235 return ERROR_DOS(ERRSRV,ERRaccess);
3237 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3238 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3240 if (VALID_STAT(sbuf))
3241 unixmode = sbuf.st_mode;
3243 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3244 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3246 /* Realloc the parameter and data sizes */
3247 params = SMB_REALLOC(*pparams,2);
3248 if(params == NULL)
3249 return ERROR_DOS(ERRDOS,ERRnomem);
3250 *pparams = params;
3252 SSVAL(params,0,0);
3254 if (fsp && fsp->pending_modtime) {
3255 /* the pending modtime overrides the current modtime */
3256 sbuf.st_mtime = fsp->pending_modtime;
3259 size = get_file_size(sbuf);
3260 tvs.modtime = sbuf.st_mtime;
3261 tvs.actime = sbuf.st_atime;
3262 dosmode = dos_mode(conn,fname,&sbuf);
3263 unixmode = sbuf.st_mode;
3265 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3266 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3268 switch (info_level) {
3269 case SMB_INFO_STANDARD:
3271 if (total_data < 12)
3272 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3274 /* access time */
3275 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3276 /* write time */
3277 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3278 break;
3281 case SMB_INFO_SET_EA:
3282 status = set_ea(conn, fsp, fname, pdata, total_data);
3283 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3284 return ERROR_NT(status);
3285 break;
3287 /* XXXX um, i don't think this is right.
3288 it's also not in the cifs6.txt spec.
3290 case SMB_INFO_QUERY_EAS_FROM_LIST:
3291 if (total_data < 28)
3292 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3294 tvs.actime = make_unix_date2(pdata+8);
3295 tvs.modtime = make_unix_date2(pdata+12);
3296 size = IVAL(pdata,16);
3297 dosmode = IVAL(pdata,24);
3298 break;
3300 /* XXXX nor this. not in cifs6.txt, either. */
3301 case SMB_INFO_QUERY_ALL_EAS:
3302 if (total_data < 28)
3303 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3305 tvs.actime = make_unix_date2(pdata+8);
3306 tvs.modtime = make_unix_date2(pdata+12);
3307 size = IVAL(pdata,16);
3308 dosmode = IVAL(pdata,24);
3309 break;
3311 case SMB_SET_FILE_BASIC_INFO:
3312 case SMB_FILE_BASIC_INFORMATION:
3314 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3315 time_t write_time;
3316 time_t changed_time;
3318 if (total_data < 36)
3319 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3321 /* Ignore create time at offset pdata. */
3323 /* access time */
3324 tvs.actime = interpret_long_date(pdata+8);
3326 write_time = interpret_long_date(pdata+16);
3327 changed_time = interpret_long_date(pdata+24);
3329 tvs.modtime = MIN(write_time, changed_time);
3331 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3332 tvs.modtime = write_time;
3334 /* Prefer a defined time to an undefined one. */
3335 if (null_mtime(tvs.modtime)) {
3336 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3339 /* attributes */
3340 dosmode = IVAL(pdata,32);
3341 break;
3344 case SMB_FILE_ALLOCATION_INFORMATION:
3345 case SMB_SET_FILE_ALLOCATION_INFO:
3347 int ret = -1;
3348 SMB_BIG_UINT allocation_size;
3350 if (total_data < 8)
3351 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3353 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3354 #ifdef LARGE_SMB_OFF_T
3355 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3356 #else /* LARGE_SMB_OFF_T */
3357 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3358 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3359 #endif /* LARGE_SMB_OFF_T */
3360 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3361 fname, (double)allocation_size ));
3363 if (allocation_size) {
3364 allocation_size = smb_roundup(conn, allocation_size);
3367 if(allocation_size != get_file_size(sbuf)) {
3368 SMB_STRUCT_STAT new_sbuf;
3370 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3371 fname, (double)allocation_size ));
3373 if (fd == -1) {
3374 files_struct *new_fsp = NULL;
3375 int access_mode = 0;
3376 int action = 0;
3378 if(global_oplock_break) {
3379 /* Queue this file modify as we are the process of an oplock break. */
3381 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3382 DEBUGADD(2,( "in oplock break state.\n"));
3384 push_oplock_pending_smb_message(inbuf, length);
3385 return -1;
3388 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3389 SET_OPEN_MODE(DOS_OPEN_RDWR),
3390 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3391 FILE_ATTRIBUTE_NORMAL,
3392 INTERNAL_OPEN_ONLY, &access_mode, &action);
3394 if (new_fsp == NULL)
3395 return(UNIXERROR(ERRDOS,ERRbadpath));
3396 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3397 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3398 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3399 new_fsp->fnum, strerror(errno)));
3400 ret = -1;
3402 close_file(new_fsp,True);
3403 } else {
3404 ret = vfs_allocate_file_space(fsp, allocation_size);
3405 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3406 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3407 fsp->fnum, strerror(errno)));
3408 ret = -1;
3411 if (ret == -1)
3412 return ERROR_NT(NT_STATUS_DISK_FULL);
3414 /* Allocate can truncate size... */
3415 size = get_file_size(new_sbuf);
3418 break;
3421 case SMB_FILE_END_OF_FILE_INFORMATION:
3422 case SMB_SET_FILE_END_OF_FILE_INFO:
3424 if (total_data < 8)
3425 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3427 size = IVAL(pdata,0);
3428 #ifdef LARGE_SMB_OFF_T
3429 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3430 #else /* LARGE_SMB_OFF_T */
3431 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3432 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3433 #endif /* LARGE_SMB_OFF_T */
3434 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3435 break;
3438 case SMB_FILE_DISPOSITION_INFORMATION:
3439 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3441 BOOL delete_on_close;
3443 if (total_data < 1)
3444 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3446 delete_on_close = (CVAL(pdata,0) ? True : False);
3448 /* Just ignore this set on a path. */
3449 if (tran_call != TRANSACT2_SETFILEINFO)
3450 break;
3452 if (fsp == NULL)
3453 return(UNIXERROR(ERRDOS,ERRbadfid));
3455 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3457 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3458 return ERROR_NT(status);
3460 /* The set is across all open files on this dev/inode pair. */
3461 status =set_delete_on_close_over_all(fsp, delete_on_close);
3462 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3463 return ERROR_NT(status);
3465 break;
3468 case SMB_FILE_POSITION_INFORMATION:
3470 SMB_BIG_UINT position_information;
3472 if (total_data < 8)
3473 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3475 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3476 #ifdef LARGE_SMB_OFF_T
3477 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3478 #else /* LARGE_SMB_OFF_T */
3479 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3480 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3481 #endif /* LARGE_SMB_OFF_T */
3482 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3483 fname, (double)position_information ));
3484 if (fsp)
3485 fsp->position_information = position_information;
3486 break;
3490 * CIFS UNIX extensions.
3493 case SMB_SET_FILE_UNIX_BASIC:
3495 uint32 raw_unixmode;
3497 if (total_data < 100)
3498 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3500 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3501 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3502 size=IVAL(pdata,0); /* first 8 Bytes are size */
3503 #ifdef LARGE_SMB_OFF_T
3504 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3505 #else /* LARGE_SMB_OFF_T */
3506 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3507 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3508 #endif /* LARGE_SMB_OFF_T */
3510 pdata+=24; /* ctime & st_blocks are not changed */
3511 tvs.actime = interpret_long_date(pdata); /* access_time */
3512 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3513 pdata+=16;
3514 set_owner = (uid_t)IVAL(pdata,0);
3515 pdata += 8;
3516 set_grp = (gid_t)IVAL(pdata,0);
3517 pdata += 8;
3518 raw_unixmode = IVAL(pdata,28);
3519 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3520 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3522 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3523 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3524 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3526 if (!VALID_STAT(sbuf)) {
3529 * The only valid use of this is to create character and block
3530 * devices, and named pipes. This is deprecated (IMHO) and
3531 * a new info level should be used for mknod. JRA.
3534 uint32 file_type = IVAL(pdata,0);
3535 #if defined(HAVE_MAKEDEV)
3536 uint32 dev_major = IVAL(pdata,4);
3537 uint32 dev_minor = IVAL(pdata,12);
3538 #endif
3540 uid_t myuid = geteuid();
3541 gid_t mygid = getegid();
3542 SMB_DEV_T dev = (SMB_DEV_T)0;
3544 if (tran_call == TRANSACT2_SETFILEINFO)
3545 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3547 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3548 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3550 #if defined(HAVE_MAKEDEV)
3551 dev = makedev(dev_major, dev_minor);
3552 #endif
3554 /* We can only create as the owner/group we are. */
3556 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3557 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3558 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3559 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3561 switch (file_type) {
3562 #if defined(S_IFIFO)
3563 case UNIX_TYPE_FIFO:
3564 unixmode |= S_IFIFO;
3565 break;
3566 #endif
3567 #if defined(S_IFSOCK)
3568 case UNIX_TYPE_SOCKET:
3569 unixmode |= S_IFSOCK;
3570 break;
3571 #endif
3572 #if defined(S_IFCHR)
3573 case UNIX_TYPE_CHARDEV:
3574 unixmode |= S_IFCHR;
3575 break;
3576 #endif
3577 #if defined(S_IFBLK)
3578 case UNIX_TYPE_BLKDEV:
3579 unixmode |= S_IFBLK;
3580 break;
3581 #endif
3582 default:
3583 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3586 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3587 0%o for file %s\n", (double)dev, unixmode, fname ));
3589 /* Ok - do the mknod. */
3590 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3591 return(UNIXERROR(ERRDOS,ERRnoaccess));
3593 inherit_access_acl(conn, fname, unixmode);
3595 SSVAL(params,0,0);
3596 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3597 return(-1);
3601 * Deal with the UNIX specific mode set.
3604 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3605 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3606 (unsigned int)unixmode, fname ));
3607 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3608 return(UNIXERROR(ERRDOS,ERRnoaccess));
3612 * Deal with the UNIX specific uid set.
3615 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3616 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3617 (unsigned int)set_owner, fname ));
3618 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3619 return(UNIXERROR(ERRDOS,ERRnoaccess));
3623 * Deal with the UNIX specific gid set.
3626 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3627 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3628 (unsigned int)set_owner, fname ));
3629 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3630 return(UNIXERROR(ERRDOS,ERRnoaccess));
3632 break;
3635 case SMB_SET_FILE_UNIX_LINK:
3637 pstring link_target;
3638 char *newname = fname;
3640 /* Set a symbolic link. */
3641 /* Don't allow this if follow links is false. */
3643 if (!lp_symlinks(SNUM(conn)))
3644 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3646 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3648 /* !widelinks forces the target path to be within the share. */
3649 /* This means we can interpret the target as a pathname. */
3650 if (!lp_widelinks(SNUM(conn))) {
3651 pstring rel_name;
3652 char *last_dirp = NULL;
3654 unix_format(link_target);
3655 if (*link_target == '/') {
3656 /* No absolute paths allowed. */
3657 return(UNIXERROR(ERRDOS,ERRnoaccess));
3659 pstrcpy(rel_name, newname);
3660 last_dirp = strrchr_m(rel_name, '/');
3661 if (last_dirp) {
3662 last_dirp[1] = '\0';
3663 } else {
3664 pstrcpy(rel_name, "./");
3666 pstrcat(rel_name, link_target);
3668 if (!check_name(rel_name, conn)) {
3669 return(UNIXERROR(ERRDOS,ERRnoaccess));
3673 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3674 fname, link_target ));
3676 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3677 return(UNIXERROR(ERRDOS,ERRnoaccess));
3678 SSVAL(params,0,0);
3679 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3680 return(-1);
3683 case SMB_SET_FILE_UNIX_HLINK:
3685 pstring oldname;
3686 char *newname = fname;
3688 /* Set a hard link. */
3689 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3690 if (!NT_STATUS_IS_OK(status)) {
3691 return ERROR_NT(status);
3694 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3695 fname, oldname));
3697 status = hardlink_internals(conn, oldname, newname);
3698 if (!NT_STATUS_IS_OK(status)) {
3699 return ERROR_NT(status);
3702 SSVAL(params,0,0);
3703 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3704 return(-1);
3707 case SMB_FILE_RENAME_INFORMATION:
3709 BOOL overwrite;
3710 uint32 root_fid;
3711 uint32 len;
3712 pstring newname;
3713 pstring base_name;
3714 char *p;
3716 if (total_data < 12)
3717 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3719 overwrite = (CVAL(pdata,0) ? True : False);
3720 root_fid = IVAL(pdata,4);
3721 len = IVAL(pdata,8);
3722 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3723 if (!NT_STATUS_IS_OK(status)) {
3724 return ERROR_NT(status);
3727 /* Check the new name has no '/' characters. */
3728 if (strchr_m(newname, '/'))
3729 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3731 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3733 /* Create the base directory. */
3734 pstrcpy(base_name, fname);
3735 p = strrchr_m(base_name, '/');
3736 if (p)
3737 *p = '\0';
3738 /* Append the new name. */
3739 pstrcat(base_name, "/");
3740 pstrcat(base_name, newname);
3742 if (fsp) {
3743 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3744 fsp->fnum, fsp->fsp_name, base_name ));
3745 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3746 } else {
3747 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3748 fname, newname ));
3749 status = rename_internals(conn, fname, base_name, 0, overwrite);
3751 if (!NT_STATUS_IS_OK(status)) {
3752 return ERROR_NT(status);
3754 process_pending_change_notify_queue((time_t)0);
3755 SSVAL(params,0,0);
3756 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3757 return(-1);
3760 #if defined(HAVE_POSIX_ACLS)
3761 case SMB_SET_POSIX_ACL:
3763 uint16 posix_acl_version;
3764 uint16 num_file_acls;
3765 uint16 num_def_acls;
3766 BOOL valid_file_acls = True;
3767 BOOL valid_def_acls = True;
3769 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3770 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3772 posix_acl_version = SVAL(pdata,0);
3773 num_file_acls = SVAL(pdata,2);
3774 num_def_acls = SVAL(pdata,4);
3776 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3777 valid_file_acls = False;
3778 num_file_acls = 0;
3781 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3782 valid_def_acls = False;
3783 num_def_acls = 0;
3786 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3787 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3790 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3791 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3792 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3795 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3796 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3797 return(UNIXERROR(ERRDOS,ERRnoaccess));
3800 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3801 pdata + SMB_POSIX_ACL_HEADER_SIZE +
3802 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3803 return(UNIXERROR(ERRDOS,ERRnoaccess));
3806 SSVAL(params,0,0);
3807 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3808 return(-1);
3810 #endif
3812 default:
3813 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3816 /* get some defaults (no modifications) if any info is zero or -1. */
3817 if (null_mtime(tvs.actime)) {
3818 tvs.actime = sbuf.st_atime;
3821 if (null_mtime(tvs.modtime)) {
3822 tvs.modtime = sbuf.st_mtime;
3825 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3826 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3827 DEBUG(6,("size: %.0f ", (double)size));
3829 if (dosmode) {
3830 if (S_ISDIR(sbuf.st_mode))
3831 dosmode |= aDIR;
3832 else
3833 dosmode &= ~aDIR;
3836 DEBUG(6,("dosmode: %x\n" , dosmode));
3838 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3839 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3840 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3841 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3844 * Only do this test if we are not explicitly
3845 * changing the size of a file.
3847 if (!size)
3848 size = get_file_size(sbuf);
3852 * Try and set the times, size and mode of this file -
3853 * if they are different from the current values
3856 /* check the mode isn't different, before changing it */
3857 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3859 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3861 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
3862 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3863 return(UNIXERROR(ERRDOS,ERRnoaccess));
3867 /* Now the size. */
3868 if (size != get_file_size(sbuf)) {
3870 int ret;
3872 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3873 fname, (double)size ));
3875 if (fd == -1) {
3876 files_struct *new_fsp = NULL;
3877 int access_mode = 0;
3878 int action = 0;
3880 if(global_oplock_break) {
3881 /* Queue this file modify as we are the process of an oplock break. */
3883 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3884 DEBUGADD(2,( "in oplock break state.\n"));
3886 push_oplock_pending_smb_message(inbuf, length);
3887 return -1;
3890 new_fsp = open_file_shared(conn, fname, &sbuf,
3891 SET_OPEN_MODE(DOS_OPEN_RDWR),
3892 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3893 FILE_ATTRIBUTE_NORMAL,
3894 INTERNAL_OPEN_ONLY, &access_mode, &action);
3896 if (new_fsp == NULL)
3897 return(UNIXERROR(ERRDOS,ERRbadpath));
3898 ret = vfs_set_filelen(new_fsp, size);
3899 close_file(new_fsp,True);
3900 } else {
3901 ret = vfs_set_filelen(fsp, size);
3904 if (ret == -1)
3905 return (UNIXERROR(ERRHRD,ERRdiskfull));
3909 * Finally the times.
3911 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3912 if(fsp != NULL) {
3914 * This was a setfileinfo on an open file.
3915 * NT does this a lot. We also need to
3916 * set the time here, as it can be read by
3917 * FindFirst/FindNext and with the patch for bug #2045
3918 * in smbd/fileio.c it ensures that this timestamp is
3919 * kept sticky even after a write. We save the request
3920 * away and will set it on file close and after a write. JRA.
3923 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3924 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3925 fsp_set_pending_modtime(fsp, tvs.modtime);
3929 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3931 if(file_utime(conn, fname, &tvs)!=0) {
3932 return(UNIXERROR(ERRDOS,ERRnoaccess));
3936 SSVAL(params,0,0);
3937 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3939 return(-1);
3942 /****************************************************************************
3943 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3944 ****************************************************************************/
3946 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3947 char **pparams, int total_params, char **ppdata, int total_data,
3948 unsigned int max_data_bytes)
3950 char *params = *pparams;
3951 pstring directory;
3952 int ret = -1;
3953 SMB_STRUCT_STAT sbuf;
3954 BOOL bad_path = False;
3955 NTSTATUS status = NT_STATUS_OK;
3957 if (!CAN_WRITE(conn))
3958 return ERROR_DOS(ERRSRV,ERRaccess);
3960 if (total_params < 4)
3961 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3963 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
3964 if (!NT_STATUS_IS_OK(status)) {
3965 return ERROR_NT(status);
3968 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3970 unix_convert(directory,conn,0,&bad_path,&sbuf);
3971 if (bad_path) {
3972 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3974 if (check_name(directory,conn))
3975 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3977 if(ret < 0) {
3978 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3979 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3982 /* Realloc the parameter and data sizes */
3983 params = SMB_REALLOC(*pparams,2);
3984 if(params == NULL)
3985 return ERROR_DOS(ERRDOS,ERRnomem);
3986 *pparams = params;
3988 SSVAL(params,0,0);
3990 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3992 return(-1);
3995 /****************************************************************************
3996 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3997 We don't actually do this - we just send a null response.
3998 ****************************************************************************/
4000 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4001 char **pparams, int total_params, char **ppdata, int total_data,
4002 unsigned int max_data_bytes)
4004 static uint16 fnf_handle = 257;
4005 char *params = *pparams;
4006 uint16 info_level;
4008 if (total_params < 6)
4009 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4011 info_level = SVAL(params,4);
4012 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4014 switch (info_level) {
4015 case 1:
4016 case 2:
4017 break;
4018 default:
4019 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4022 /* Realloc the parameter and data sizes */
4023 params = SMB_REALLOC(*pparams,6);
4024 if(params == NULL)
4025 return ERROR_DOS(ERRDOS,ERRnomem);
4026 *pparams = params;
4028 SSVAL(params,0,fnf_handle);
4029 SSVAL(params,2,0); /* No changes */
4030 SSVAL(params,4,0); /* No EA errors */
4032 fnf_handle++;
4034 if(fnf_handle == 0)
4035 fnf_handle = 257;
4037 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4039 return(-1);
4042 /****************************************************************************
4043 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4044 changes). Currently this does nothing.
4045 ****************************************************************************/
4047 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4048 char **pparams, int total_params, char **ppdata, int total_data,
4049 unsigned int max_data_bytes)
4051 char *params = *pparams;
4053 DEBUG(3,("call_trans2findnotifynext\n"));
4055 /* Realloc the parameter and data sizes */
4056 params = SMB_REALLOC(*pparams,4);
4057 if(params == NULL)
4058 return ERROR_DOS(ERRDOS,ERRnomem);
4059 *pparams = params;
4061 SSVAL(params,0,0); /* No changes */
4062 SSVAL(params,2,0); /* No EA errors */
4064 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4066 return(-1);
4069 /****************************************************************************
4070 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4071 ****************************************************************************/
4073 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4074 char **pparams, int total_params, char **ppdata, int total_data,
4075 unsigned int max_data_bytes)
4077 char *params = *pparams;
4078 pstring pathname;
4079 int reply_size = 0;
4080 int max_referral_level;
4082 DEBUG(10,("call_trans2getdfsreferral\n"));
4084 if (total_params < 2)
4085 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4087 max_referral_level = SVAL(params,0);
4089 if(!lp_host_msdfs())
4090 return ERROR_DOS(ERRDOS,ERRbadfunc);
4092 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4093 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4094 return UNIXERROR(ERRDOS,ERRbadfile);
4096 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4097 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4099 return(-1);
4102 #define LMCAT_SPL 0x53
4103 #define LMFUNC_GETJOBID 0x60
4105 /****************************************************************************
4106 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4107 ****************************************************************************/
4109 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4110 char **pparams, int total_params, char **ppdata, int total_data,
4111 unsigned int max_data_bytes)
4113 char *pdata = *ppdata;
4114 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4116 /* check for an invalid fid before proceeding */
4118 if (!fsp)
4119 return(ERROR_DOS(ERRDOS,ERRbadfid));
4121 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4122 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4123 pdata = SMB_REALLOC(*ppdata, 32);
4124 if(pdata == NULL)
4125 return ERROR_DOS(ERRDOS,ERRnomem);
4126 *ppdata = pdata;
4128 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4129 CAN ACCEPT THIS IN UNICODE. JRA. */
4131 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4132 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4133 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4134 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4135 return(-1);
4136 } else {
4137 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4138 return ERROR_DOS(ERRSRV,ERRerror);
4142 /****************************************************************************
4143 Reply to a SMBfindclose (stop trans2 directory search).
4144 ****************************************************************************/
4146 int reply_findclose(connection_struct *conn,
4147 char *inbuf,char *outbuf,int length,int bufsize)
4149 int outsize = 0;
4150 int dptr_num=SVALS(inbuf,smb_vwv0);
4151 START_PROFILE(SMBfindclose);
4153 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4155 dptr_close(&dptr_num);
4157 outsize = set_message(outbuf,0,0,True);
4159 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4161 END_PROFILE(SMBfindclose);
4162 return(outsize);
4165 /****************************************************************************
4166 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4167 ****************************************************************************/
4169 int reply_findnclose(connection_struct *conn,
4170 char *inbuf,char *outbuf,int length,int bufsize)
4172 int outsize = 0;
4173 int dptr_num= -1;
4174 START_PROFILE(SMBfindnclose);
4176 dptr_num = SVAL(inbuf,smb_vwv0);
4178 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4180 /* We never give out valid handles for a
4181 findnotifyfirst - so any dptr_num is ok here.
4182 Just ignore it. */
4184 outsize = set_message(outbuf,0,0,True);
4186 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4188 END_PROFILE(SMBfindnclose);
4189 return(outsize);
4192 /****************************************************************************
4193 Reply to a SMBtranss2 - just ignore it!
4194 ****************************************************************************/
4196 int reply_transs2(connection_struct *conn,
4197 char *inbuf,char *outbuf,int length,int bufsize)
4199 START_PROFILE(SMBtranss2);
4200 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4201 END_PROFILE(SMBtranss2);
4202 return(-1);
4205 /****************************************************************************
4206 Reply to a SMBtrans2.
4207 ****************************************************************************/
4209 int reply_trans2(connection_struct *conn,
4210 char *inbuf,char *outbuf,int length,int bufsize)
4212 int outsize = 0;
4213 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4214 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4215 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4216 #if 0
4217 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4218 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4219 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4220 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4221 int32 timeout = IVALS(inbuf,smb_timeout);
4222 #endif
4223 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4224 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4225 char *params = NULL, *data = NULL;
4226 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4227 START_PROFILE(SMBtrans2);
4229 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4230 /* Queue this open message as we are the process of an
4231 * oplock break. */
4233 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4234 DEBUGADD(2,( "in oplock break state.\n"));
4236 push_oplock_pending_smb_message(inbuf, length);
4237 END_PROFILE(SMBtrans2);
4238 return -1;
4241 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4242 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4243 END_PROFILE(SMBtrans2);
4244 return ERROR_DOS(ERRSRV,ERRaccess);
4247 outsize = set_message(outbuf,0,0,True);
4249 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4250 is so as a sanity check */
4251 if (suwcnt != 1) {
4253 * Need to have rc=0 for ioctl to get job id for OS/2.
4254 * Network printing will fail if function is not successful.
4255 * Similar function in reply.c will be used if protocol
4256 * is LANMAN1.0 instead of LM1.2X002.
4257 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4258 * outbuf doesn't have to be set(only job id is used).
4260 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4261 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4262 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4263 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4264 } else {
4265 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4266 DEBUG(2,("Transaction is %d\n",tran_call));
4267 END_PROFILE(SMBtrans2);
4268 ERROR_DOS(ERRDOS,ERRinvalidparam);
4272 /* Allocate the space for the maximum needed parameters and data */
4273 if (total_params > 0)
4274 params = (char *)SMB_MALLOC(total_params);
4275 if (total_data > 0)
4276 data = (char *)SMB_MALLOC(total_data);
4278 if ((total_params && !params) || (total_data && !data)) {
4279 DEBUG(2,("Out of memory in reply_trans2\n"));
4280 SAFE_FREE(params);
4281 SAFE_FREE(data);
4282 END_PROFILE(SMBtrans2);
4283 return ERROR_DOS(ERRDOS,ERRnomem);
4286 /* Copy the param and data bytes sent with this request into
4287 the params buffer */
4288 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4289 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4291 if (num_params > total_params || num_data > total_data)
4292 exit_server("invalid params in reply_trans2");
4294 if(params) {
4295 unsigned int psoff = SVAL(inbuf, smb_psoff);
4296 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4297 goto bad_param;
4298 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4299 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4300 goto bad_param;
4301 memcpy( params, smb_base(inbuf) + psoff, num_params);
4303 if(data) {
4304 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4305 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4306 goto bad_param;
4307 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4308 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4309 goto bad_param;
4310 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4313 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4315 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4316 /* We need to send an interim response then receive the rest
4317 of the parameter/data bytes */
4318 outsize = set_message(outbuf,0,0,True);
4319 srv_signing_trans_stop();
4320 if (!send_smb(smbd_server_fd(),outbuf))
4321 exit_server("reply_trans2: send_smb failed.");
4323 while (num_data_sofar < total_data ||
4324 num_params_sofar < total_params) {
4325 BOOL ret;
4326 unsigned int param_disp;
4327 unsigned int param_off;
4328 unsigned int data_disp;
4329 unsigned int data_off;
4331 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4334 * The sequence number for the trans reply is always
4335 * based on the last secondary received.
4338 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4340 if ((ret &&
4341 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4342 outsize = set_message(outbuf,0,0,True);
4343 if(ret)
4344 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4345 else
4346 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4347 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4348 goto bad_param;
4351 /* Revise total_params and total_data in case
4352 they have changed downwards */
4353 if (SVAL(inbuf, smb_tpscnt) < total_params)
4354 total_params = SVAL(inbuf, smb_tpscnt);
4355 if (SVAL(inbuf, smb_tdscnt) < total_data)
4356 total_data = SVAL(inbuf, smb_tdscnt);
4358 num_params = SVAL(inbuf,smb_spscnt);
4359 param_off = SVAL(inbuf, smb_spsoff);
4360 param_disp = SVAL(inbuf, smb_spsdisp);
4361 num_params_sofar += num_params;
4363 num_data = SVAL(inbuf, smb_sdscnt);
4364 data_off = SVAL(inbuf, smb_sdsoff);
4365 data_disp = SVAL(inbuf, smb_sdsdisp);
4366 num_data_sofar += num_data;
4368 if (num_params_sofar > total_params || num_data_sofar > total_data)
4369 goto bad_param;
4371 if (num_params) {
4372 if (param_disp + num_params > total_params)
4373 goto bad_param;
4374 if ((param_disp + num_params < param_disp) ||
4375 (param_disp + num_params < num_params))
4376 goto bad_param;
4377 if (param_disp > total_params)
4378 goto bad_param;
4379 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4380 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4381 goto bad_param;
4382 if (params + param_disp < params)
4383 goto bad_param;
4385 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4387 if (num_data) {
4388 if (data_disp + num_data > total_data)
4389 goto bad_param;
4390 if ((data_disp + num_data < data_disp) ||
4391 (data_disp + num_data < num_data))
4392 goto bad_param;
4393 if (data_disp > total_data)
4394 goto bad_param;
4395 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4396 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4397 goto bad_param;
4398 if (data + data_disp < data)
4399 goto bad_param;
4401 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4406 if (Protocol >= PROTOCOL_NT1) {
4407 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4410 /* Now we must call the relevant TRANS2 function */
4411 switch(tran_call) {
4412 case TRANSACT2_OPEN:
4413 START_PROFILE_NESTED(Trans2_open);
4414 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4415 &params, total_params, &data, total_data, max_data_bytes);
4416 END_PROFILE_NESTED(Trans2_open);
4417 break;
4419 case TRANSACT2_FINDFIRST:
4420 START_PROFILE_NESTED(Trans2_findfirst);
4421 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4422 &params, total_params, &data, total_data, max_data_bytes);
4423 END_PROFILE_NESTED(Trans2_findfirst);
4424 break;
4426 case TRANSACT2_FINDNEXT:
4427 START_PROFILE_NESTED(Trans2_findnext);
4428 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4429 &params, total_params, &data, total_data, max_data_bytes);
4430 END_PROFILE_NESTED(Trans2_findnext);
4431 break;
4433 case TRANSACT2_QFSINFO:
4434 START_PROFILE_NESTED(Trans2_qfsinfo);
4435 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4436 &params, total_params, &data, total_data, max_data_bytes);
4437 END_PROFILE_NESTED(Trans2_qfsinfo);
4438 break;
4440 #ifdef HAVE_SYS_QUOTAS
4441 case TRANSACT2_SETFSINFO:
4442 START_PROFILE_NESTED(Trans2_setfsinfo);
4443 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4444 &params, total_params, &data, total_data, max_data_bytes);
4445 END_PROFILE_NESTED(Trans2_setfsinfo);
4446 break;
4447 #endif
4448 case TRANSACT2_QPATHINFO:
4449 case TRANSACT2_QFILEINFO:
4450 START_PROFILE_NESTED(Trans2_qpathinfo);
4451 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4452 &params, total_params, &data, total_data, max_data_bytes);
4453 END_PROFILE_NESTED(Trans2_qpathinfo);
4454 break;
4455 case TRANSACT2_SETPATHINFO:
4456 case TRANSACT2_SETFILEINFO:
4457 START_PROFILE_NESTED(Trans2_setpathinfo);
4458 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4459 &params, total_params, &data, total_data, max_data_bytes);
4460 END_PROFILE_NESTED(Trans2_setpathinfo);
4461 break;
4463 case TRANSACT2_FINDNOTIFYFIRST:
4464 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4465 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4466 &params, total_params, &data, total_data, max_data_bytes);
4467 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4468 break;
4470 case TRANSACT2_FINDNOTIFYNEXT:
4471 START_PROFILE_NESTED(Trans2_findnotifynext);
4472 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4473 &params, total_params, &data, total_data, max_data_bytes);
4474 END_PROFILE_NESTED(Trans2_findnotifynext);
4475 break;
4476 case TRANSACT2_MKDIR:
4477 START_PROFILE_NESTED(Trans2_mkdir);
4478 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4479 &params, total_params, &data, total_data, max_data_bytes);
4480 END_PROFILE_NESTED(Trans2_mkdir);
4481 break;
4483 case TRANSACT2_GET_DFS_REFERRAL:
4484 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4485 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4486 &params, total_params, &data, total_data, max_data_bytes);
4487 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4488 break;
4489 case TRANSACT2_IOCTL:
4490 START_PROFILE_NESTED(Trans2_ioctl);
4491 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4492 &params, total_params, &data, total_data, max_data_bytes);
4493 END_PROFILE_NESTED(Trans2_ioctl);
4494 break;
4495 default:
4496 /* Error in request */
4497 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4498 SAFE_FREE(params);
4499 SAFE_FREE(data);
4500 END_PROFILE(SMBtrans2);
4501 srv_signing_trans_stop();
4502 return ERROR_DOS(ERRSRV,ERRerror);
4505 /* As we do not know how many data packets will need to be
4506 returned here the various call_trans2xxxx calls
4507 must send their own. Thus a call_trans2xxx routine only
4508 returns a value other than -1 when it wants to send
4509 an error packet.
4512 srv_signing_trans_stop();
4514 SAFE_FREE(params);
4515 SAFE_FREE(data);
4516 END_PROFILE(SMBtrans2);
4517 return outsize; /* If a correct response was needed the
4518 call_trans2xxx calls have already sent
4519 it. If outsize != -1 then it is returning */
4521 bad_param:
4523 srv_signing_trans_stop();
4524 SAFE_FREE(params);
4525 SAFE_FREE(data);
4526 END_PROFILE(SMBtrans2);
4527 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);