r4348: syncing up for 3.0.11pre1
[Samba.git] / source / smbd / trans2.c
blob7269ab91579a16ae8e0e924ab02b83ffaa696858
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 fstring local_machine;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 /********************************************************************
37 Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary.
38 Only do this for Windows clients.
39 ********************************************************************/
41 SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val)
43 /* Only roundup for Windows clients. */
44 enum remote_arch_types ra_type = get_remote_arch();
45 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
46 val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE);
48 return val;
51 /********************************************************************
52 Given a stat buffer return the allocated size on disk, taking into
53 account sparse files.
54 ********************************************************************/
56 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
58 SMB_BIG_UINT ret;
60 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
61 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
62 #else
63 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
64 #endif
66 if (!ret && fsp && fsp->initial_allocation_size)
67 ret = fsp->initial_allocation_size;
69 ret = smb_roundup(ret);
71 return ret;
74 /****************************************************************************
75 Utility functions for dealing with extended attributes.
76 ****************************************************************************/
78 static const char *prohibited_ea_names[] = {
79 SAMBA_POSIX_INHERITANCE_EA_NAME,
80 SAMBA_XATTR_DOS_ATTRIB,
81 NULL
84 /****************************************************************************
85 Refuse to allow clients to overwrite our private xattrs.
86 ****************************************************************************/
88 static BOOL samba_private_attr_name(const char *unix_ea_name)
90 int i;
92 for (i = 0; prohibited_ea_names[i]; i++) {
93 if (strequal( prohibited_ea_names[i], unix_ea_name))
94 return True;
96 return False;
99 struct ea_list {
100 struct ea_list *next, *prev;
101 struct ea_struct ea;
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
113 char *val = NULL;
114 ssize_t sizeret;
116 again:
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
119 if (!val) {
120 return False;
123 if (fsp && fsp->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
125 } else {
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130 attr_size = 65536;
131 goto again;
134 if (sizeret == -1) {
135 return False;
138 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
139 dump_data(10, val, sizeret);
141 pea->flags = 0;
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
144 } else {
145 pea->name = ea_name;
147 pea->value.data = val;
148 pea->value.length = (size_t)sizeret;
149 return True;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
158 /* Get a list of all xattrs. Max namesize is 64k. */
159 size_t ea_namelist_size = 1024;
160 char *ea_namelist;
161 char *p;
162 ssize_t sizeret;
163 int i;
164 struct ea_list *ea_list_head = NULL;
166 *pea_total_len = 0;
168 if (!lp_ea_support(SNUM(conn))) {
169 return NULL;
172 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
173 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
174 if (fsp && fsp->fd != -1) {
175 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
176 } else {
177 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
180 if (sizeret == -1 && errno == ERANGE) {
181 ea_namelist_size *= 2;
182 } else {
183 break;
187 if (sizeret == -1)
188 return NULL;
190 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
192 if (sizeret) {
193 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
194 struct ea_list *listp, *tmp;
196 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
197 continue;
199 listp = TALLOC_P(mem_ctx, struct ea_list);
200 if (!listp)
201 return NULL;
203 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
204 return NULL;
208 fstring dos_ea_name;
209 push_ascii_fstring(dos_ea_name, listp->ea.name);
210 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
211 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
212 *pea_total_len, dos_ea_name,
213 (unsigned int)listp->ea.value.length ));
215 DLIST_ADD_END(ea_list_head, listp, tmp);
217 /* Add on 4 for total length. */
218 if (*pea_total_len) {
219 *pea_total_len += 4;
223 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
224 return ea_list_head;
227 /****************************************************************************
228 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
229 that was filled.
230 ****************************************************************************/
232 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
233 connection_struct *conn, files_struct *fsp, const char *fname)
235 unsigned int ret_data_size = 4;
236 char *p = pdata;
237 size_t total_ea_len;
238 TALLOC_CTX *mem_ctx;
239 struct ea_list *ea_list;
241 SMB_ASSERT(total_data_size >= 4);
243 SIVAL(pdata,0,0);
244 if (!lp_ea_support(SNUM(conn))) {
245 return 4;
247 mem_ctx = talloc_init("fill_ea_buffer");
248 if (!mem_ctx) {
249 return 4;
252 ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
253 if (!ea_list) {
254 talloc_destroy(mem_ctx);
255 return 4;
258 if (total_ea_len > total_data_size) {
259 talloc_destroy(mem_ctx);
260 return 4;
263 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
264 size_t dos_namelen;
265 fstring dos_ea_name;
266 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
267 dos_namelen = strlen(dos_ea_name);
268 if (dos_namelen > 255 || dos_namelen == 0) {
269 break;
271 if (ea_list->ea.value.length > 65535) {
272 break;
274 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
275 break;
278 /* We know we have room. */
279 SCVAL(p,0,ea_list->ea.flags);
280 SCVAL(p,1,dos_namelen);
281 SSVAL(p,2,ea_list->ea.value.length);
282 fstrcpy(p+4, dos_ea_name);
283 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
285 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
286 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
289 ret_data_size = PTR_DIFF(p, pdata);
290 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
291 ret_data_size, total_ea_len ));
292 talloc_destroy(mem_ctx);
293 SIVAL(pdata,0,ret_data_size);
294 return ret_data_size;
297 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
299 size_t total_ea_len = 0;
300 TALLOC_CTX *mem_ctx = NULL;
302 if (!lp_ea_support(SNUM(conn))) {
303 return 0;
305 mem_ctx = talloc_init("estimate_ea_size");
306 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
307 talloc_destroy(mem_ctx);
308 return total_ea_len;
311 /****************************************************************************
312 Ensure the EA name is case insensitive by matching any existing EA name.
313 ****************************************************************************/
315 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
317 size_t total_ea_len;
318 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
319 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
321 for (; ea_list; ea_list = ea_list->next) {
322 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
323 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
324 &unix_ea_name[5], ea_list->ea.name));
325 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
326 break;
329 talloc_destroy(mem_ctx);
332 /****************************************************************************
333 Set or delete an extended attribute.
334 ****************************************************************************/
336 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
337 char *pdata, int total_data)
339 unsigned int namelen;
340 unsigned int ealen;
341 int ret;
342 fstring unix_ea_name;
344 if (!lp_ea_support(SNUM(conn))) {
345 return NT_STATUS_EAS_NOT_SUPPORTED;
348 if (total_data < 8) {
349 return NT_STATUS_INVALID_PARAMETER;
352 if (IVAL(pdata,0) > total_data) {
353 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
354 return NT_STATUS_INVALID_PARAMETER;
357 pdata += 4;
358 namelen = CVAL(pdata,1);
359 ealen = SVAL(pdata,2);
360 pdata += 4;
361 if (total_data < 8 + namelen + 1 + ealen) {
362 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
363 (unsigned int)total_data, namelen, ealen));
364 return NT_STATUS_INVALID_PARAMETER;
367 if (pdata[namelen] != '\0') {
368 DEBUG(10,("set_ea: ea name not null terminated\n"));
369 return NT_STATUS_INVALID_PARAMETER;
372 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
373 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
374 pdata += (namelen + 1);
376 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
378 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
379 if (ealen) {
380 DEBUG(10,("set_ea: data :\n"));
381 dump_data(10, pdata, ealen);
384 if (samba_private_attr_name(unix_ea_name)) {
385 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
386 return NT_STATUS_ACCESS_DENIED;
389 if (ealen == 0) {
390 /* Remove the attribute. */
391 if (fsp && (fsp->fd != -1)) {
392 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
393 unix_ea_name, fsp->fsp_name));
394 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
395 } else {
396 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
397 unix_ea_name, fname));
398 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
400 #ifdef ENOATTR
401 /* Removing a non existent attribute always succeeds. */
402 if (ret == -1 && errno == ENOATTR) {
403 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
404 ret = 0;
406 #endif
407 } else {
408 if (fsp && (fsp->fd != -1)) {
409 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
410 unix_ea_name, fsp->fsp_name));
411 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
412 } else {
413 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
414 unix_ea_name, fname));
415 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
419 if (ret == -1) {
420 #ifdef ENOTSUP
421 if (errno == ENOTSUP) {
422 return NT_STATUS_EAS_NOT_SUPPORTED;
424 #endif
425 return map_nt_error_from_unix(errno);
428 return NT_STATUS_OK;
431 /****************************************************************************
432 Send the required number of replies back.
433 We assume all fields other than the data fields are
434 set correctly for the type of call.
435 HACK ! Always assumes smb_setup field is zero.
436 ****************************************************************************/
438 static int send_trans2_replies(char *outbuf,
439 int bufsize,
440 char *params,
441 int paramsize,
442 char *pdata,
443 int datasize)
445 /* As we are using a protocol > LANMAN1 then the max_send
446 variable must have been set in the sessetupX call.
447 This takes precedence over the max_xmit field in the
448 global struct. These different max_xmit variables should
449 be merged as this is now too confusing */
451 extern int max_send;
452 int data_to_send = datasize;
453 int params_to_send = paramsize;
454 int useable_space;
455 char *pp = params;
456 char *pd = pdata;
457 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
458 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
459 int data_alignment_offset = 0;
461 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
463 set_message(outbuf,10,0,True);
465 /* If there genuinely are no parameters or data to send just send the empty packet */
467 if(params_to_send == 0 && data_to_send == 0) {
468 if (!send_smb(smbd_server_fd(),outbuf))
469 exit_server("send_trans2_replies: send_smb failed.");
470 return 0;
473 /* When sending params and data ensure that both are nicely aligned */
474 /* Only do this alignment when there is also data to send - else
475 can cause NT redirector problems. */
477 if (((params_to_send % 4) != 0) && (data_to_send != 0))
478 data_alignment_offset = 4 - (params_to_send % 4);
480 /* Space is bufsize minus Netbios over TCP header minus SMB header */
481 /* The alignment_offset is to align the param bytes on an even byte
482 boundary. NT 4.0 Beta needs this to work correctly. */
484 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
486 /* useable_space can never be more than max_send minus the alignment offset. */
488 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
490 while (params_to_send || data_to_send) {
491 /* Calculate whether we will totally or partially fill this packet */
493 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
495 /* We can never send more than useable_space */
497 * Note that 'useable_space' does not include the alignment offsets,
498 * but we must include the alignment offsets in the calculation of
499 * the length of the data we send over the wire, as the alignment offsets
500 * are sent here. Fix from Marc_Jacobsen@hp.com.
503 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
505 set_message(outbuf, 10, total_sent_thistime, True);
507 /* Set total params and data to be sent */
508 SSVAL(outbuf,smb_tprcnt,paramsize);
509 SSVAL(outbuf,smb_tdrcnt,datasize);
511 /* Calculate how many parameters and data we can fit into
512 * this packet. Parameters get precedence
515 params_sent_thistime = MIN(params_to_send,useable_space);
516 data_sent_thistime = useable_space - params_sent_thistime;
517 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
519 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
521 /* smb_proff is the offset from the start of the SMB header to the
522 parameter bytes, however the first 4 bytes of outbuf are
523 the Netbios over TCP header. Thus use smb_base() to subtract
524 them from the calculation */
526 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
528 if(params_sent_thistime == 0)
529 SSVAL(outbuf,smb_prdisp,0);
530 else
531 /* Absolute displacement of param bytes sent in this packet */
532 SSVAL(outbuf,smb_prdisp,pp - params);
534 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
535 if(data_sent_thistime == 0) {
536 SSVAL(outbuf,smb_droff,0);
537 SSVAL(outbuf,smb_drdisp, 0);
538 } else {
539 /* The offset of the data bytes is the offset of the
540 parameter bytes plus the number of parameters being sent this time */
541 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
542 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
543 SSVAL(outbuf,smb_drdisp, pd - pdata);
546 /* Copy the param bytes into the packet */
548 if(params_sent_thistime)
549 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
551 /* Copy in the data bytes */
552 if(data_sent_thistime)
553 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
554 data_alignment_offset,pd,data_sent_thistime);
556 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
557 params_sent_thistime, data_sent_thistime, useable_space));
558 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
559 params_to_send, data_to_send, paramsize, datasize));
561 /* Send the packet */
562 if (!send_smb(smbd_server_fd(),outbuf))
563 exit_server("send_trans2_replies: send_smb failed.");
565 pp += params_sent_thistime;
566 pd += data_sent_thistime;
568 params_to_send -= params_sent_thistime;
569 data_to_send -= data_sent_thistime;
571 /* Sanity check */
572 if(params_to_send < 0 || data_to_send < 0) {
573 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
574 params_to_send, data_to_send));
575 return -1;
579 return 0;
582 /****************************************************************************
583 Reply to a TRANSACT2_OPEN.
584 ****************************************************************************/
586 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
587 char **pparams, int total_params, char **ppdata, int total_data,
588 unsigned int max_data_bytes)
590 char *params = *pparams;
591 int16 open_mode;
592 int16 open_attr;
593 BOOL oplock_request;
594 #if 0
595 BOOL return_additional_info;
596 int16 open_sattr;
597 time_t open_time;
598 #endif
599 int16 open_ofun;
600 int32 open_size;
601 char *pname;
602 pstring fname;
603 SMB_OFF_T size=0;
604 int fmode=0,mtime=0,rmode;
605 SMB_INO_T inode = 0;
606 SMB_STRUCT_STAT sbuf;
607 int smb_action = 0;
608 BOOL bad_path = False;
609 files_struct *fsp;
610 NTSTATUS status;
613 * Ensure we have enough parameters to perform the operation.
616 if (total_params < 29)
617 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
619 open_mode = SVAL(params, 2);
620 open_attr = SVAL(params,6);
621 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
622 #if 0
623 return_additional_info = BITSETW(params,0);
624 open_sattr = SVAL(params, 4);
625 open_time = make_unix_date3(params+8);
626 #endif
627 open_ofun = SVAL(params,12);
628 open_size = IVAL(params,14);
629 pname = &params[28];
631 if (IS_IPC(conn))
632 return(ERROR_DOS(ERRSRV,ERRaccess));
634 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
635 if (!NT_STATUS_IS_OK(status)) {
636 return ERROR_NT(status);
639 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
640 fname,open_mode, open_attr, open_ofun, open_size));
642 /* XXXX we need to handle passed times, sattr and flags */
644 unix_convert(fname,conn,0,&bad_path,&sbuf);
645 if (bad_path) {
646 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
649 if (!check_name(fname,conn)) {
650 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
653 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
654 oplock_request, &rmode,&smb_action);
656 if (!fsp) {
657 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
658 /* We have re-scheduled this call. */
659 clear_cached_errors();
660 return -1;
662 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
665 size = get_file_size(sbuf);
666 fmode = dos_mode(conn,fname,&sbuf);
667 mtime = sbuf.st_mtime;
668 inode = sbuf.st_ino;
669 if (fmode & aDIR) {
670 close_file(fsp,False);
671 return(ERROR_DOS(ERRDOS,ERRnoaccess));
674 /* Realloc the size of parameters and data we will return */
675 params = SMB_REALLOC(*pparams, 28);
676 if( params == NULL )
677 return(ERROR_DOS(ERRDOS,ERRnomem));
678 *pparams = params;
680 memset((char *)params,'\0',28);
681 SSVAL(params,0,fsp->fnum);
682 SSVAL(params,2,fmode);
683 put_dos_date2(params,4, mtime);
684 SIVAL(params,8, (uint32)size);
685 SSVAL(params,12,rmode);
687 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
688 smb_action |= EXTENDED_OPLOCK_GRANTED;
690 SSVAL(params,18,smb_action);
693 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
695 SIVAL(params,20,inode);
697 /* Send the required number of replies */
698 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
700 return -1;
703 /*********************************************************
704 Routine to check if a given string matches exactly.
705 as a special case a mask of "." does NOT match. That
706 is required for correct wildcard semantics
707 Case can be significant or not.
708 **********************************************************/
710 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
712 if (mask[0] == '.' && mask[1] == 0)
713 return False;
714 if (case_sig)
715 return strcmp(str,mask)==0;
716 if (StrCaseCmp(str,mask) != 0) {
717 return False;
719 if (ms_has_wild(str)) {
720 return False;
722 return True;
725 /****************************************************************************
726 Return the filetype for UNIX extensions.
727 ****************************************************************************/
729 static uint32 unix_filetype(mode_t mode)
731 if(S_ISREG(mode))
732 return UNIX_TYPE_FILE;
733 else if(S_ISDIR(mode))
734 return UNIX_TYPE_DIR;
735 #ifdef S_ISLNK
736 else if(S_ISLNK(mode))
737 return UNIX_TYPE_SYMLINK;
738 #endif
739 #ifdef S_ISCHR
740 else if(S_ISCHR(mode))
741 return UNIX_TYPE_CHARDEV;
742 #endif
743 #ifdef S_ISBLK
744 else if(S_ISBLK(mode))
745 return UNIX_TYPE_BLKDEV;
746 #endif
747 #ifdef S_ISFIFO
748 else if(S_ISFIFO(mode))
749 return UNIX_TYPE_FIFO;
750 #endif
751 #ifdef S_ISSOCK
752 else if(S_ISSOCK(mode))
753 return UNIX_TYPE_SOCKET;
754 #endif
756 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
757 return UNIX_TYPE_UNKNOWN;
760 /****************************************************************************
761 Map wire perms onto standard UNIX permissions. Obey share restrictions.
762 ****************************************************************************/
764 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
766 mode_t ret = 0;
768 if (perms == SMB_MODE_NO_CHANGE)
769 return pst->st_mode;
771 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
772 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
773 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
774 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
775 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
776 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
777 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
778 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
779 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
780 #ifdef S_ISVTX
781 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
782 #endif
783 #ifdef S_ISGID
784 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
785 #endif
786 #ifdef S_ISUID
787 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
788 #endif
790 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
791 ret &= lp_dir_mask(SNUM(conn));
792 /* Add in force bits */
793 ret |= lp_force_dir_mode(SNUM(conn));
794 } else {
795 /* Apply mode mask */
796 ret &= lp_create_mask(SNUM(conn));
797 /* Add in force bits */
798 ret |= lp_force_create_mode(SNUM(conn));
801 return ret;
804 /****************************************************************************
805 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
806 ****************************************************************************/
808 time_t interpret_long_unix_date(char *p)
810 DEBUG(10,("interpret_long_unix_date\n"));
811 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
812 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
813 return -1;
814 } else {
815 return interpret_long_date(p);
819 /****************************************************************************
820 Get a level dependent lanman2 dir entry.
821 ****************************************************************************/
823 static BOOL get_lanman2_dir_entry(connection_struct *conn,
824 void *inbuf, void *outbuf,
825 char *path_mask,int dirtype,int info_level,
826 int requires_resume_key,
827 BOOL dont_descend,char **ppdata,
828 char *base_data, int space_remaining,
829 BOOL *out_of_space, BOOL *got_exact_match,
830 int *last_name_off)
832 const char *dname;
833 BOOL found = False;
834 SMB_STRUCT_STAT sbuf;
835 pstring mask;
836 pstring pathreal;
837 pstring fname;
838 char *p, *q, *pdata = *ppdata;
839 uint32 reskey=0;
840 int prev_dirpos=0;
841 int mode=0;
842 SMB_OFF_T file_size = 0;
843 SMB_BIG_UINT allocation_size = 0;
844 uint32 len;
845 time_t mdate=0, adate=0, cdate=0;
846 char *nameptr;
847 BOOL was_8_3;
848 int nt_extmode; /* Used for NT connections instead of mode */
849 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
851 *fname = 0;
852 *out_of_space = False;
853 *got_exact_match = False;
855 if (!conn->dirptr)
856 return(False);
858 p = strrchr_m(path_mask,'/');
859 if(p != NULL) {
860 if(p[1] == '\0')
861 pstrcpy(mask,"*.*");
862 else
863 pstrcpy(mask, p+1);
864 } else
865 pstrcpy(mask, path_mask);
867 while (!found) {
868 BOOL got_match;
870 /* Needed if we run out of space */
871 prev_dirpos = TellDir(conn->dirptr);
872 dname = ReadDirName(conn->dirptr);
875 * Due to bugs in NT client redirectors we are not using
876 * resume keys any more - set them to zero.
877 * Check out the related comments in findfirst/findnext.
878 * JRA.
881 reskey = 0;
883 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
884 (long)conn->dirptr,TellDir(conn->dirptr)));
886 if (!dname)
887 return(False);
889 pstrcpy(fname,dname);
891 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
892 got_match = mask_match(fname, mask, conn->case_sensitive);
894 if(!got_match && !mangle_is_8_3(fname, False)) {
897 * It turns out that NT matches wildcards against
898 * both long *and* short names. This may explain some
899 * of the wildcard wierdness from old DOS clients
900 * that some people have been seeing.... JRA.
903 pstring newname;
904 pstrcpy( newname, fname);
905 mangle_map( newname, True, False, SNUM(conn));
906 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
907 got_match = mask_match(newname, mask, conn->case_sensitive);
910 if(got_match) {
911 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
912 if (dont_descend && !isdots)
913 continue;
915 pstrcpy(pathreal,conn->dirpath);
916 if(needslash)
917 pstrcat(pathreal,"/");
918 pstrcat(pathreal,dname);
920 if (INFO_LEVEL_IS_UNIX(info_level)) {
921 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
922 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
923 pathreal,strerror(errno)));
924 continue;
926 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
928 /* Needed to show the msdfs symlinks as
929 * directories */
931 if(lp_host_msdfs() &&
932 lp_msdfs_root(SNUM(conn)) &&
933 is_msdfs_link(conn, pathreal, NULL, NULL,
934 &sbuf)) {
936 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
937 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
939 } else {
941 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
942 pathreal,strerror(errno)));
943 continue;
947 mode = dos_mode(conn,pathreal,&sbuf);
949 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
950 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
951 continue;
954 file_size = get_file_size(sbuf);
955 allocation_size = get_allocation_size(NULL,&sbuf);
956 mdate = sbuf.st_mtime;
957 adate = sbuf.st_atime;
958 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
960 if (lp_dos_filetime_resolution(SNUM(conn))) {
961 cdate &= ~1;
962 mdate &= ~1;
963 adate &= ~1;
966 if(mode & aDIR) {
967 /* This is necessary, as otherwise the
968 * desktop.ini file in this folder is
969 * ignored */
970 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
971 file_size = 0;
974 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
976 found = True;
980 mangle_map(fname,False,True,SNUM(conn));
982 p = pdata;
983 nameptr = p;
985 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
987 switch (info_level) {
988 case SMB_INFO_STANDARD:
989 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
990 if(requires_resume_key) {
991 SIVAL(p,0,reskey);
992 p += 4;
994 put_dos_date2(p,l1_fdateCreation,cdate);
995 put_dos_date2(p,l1_fdateLastAccess,adate);
996 put_dos_date2(p,l1_fdateLastWrite,mdate);
997 SIVAL(p,l1_cbFile,(uint32)file_size);
998 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
999 SSVAL(p,l1_attrFile,mode);
1000 p += l1_achName;
1001 nameptr = p;
1002 p += align_string(outbuf, p, 0);
1003 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1004 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1005 if (len > 2) {
1006 SCVAL(nameptr, -1, len - 2);
1007 } else {
1008 SCVAL(nameptr, -1, 0);
1010 } else {
1011 if (len > 1) {
1012 SCVAL(nameptr, -1, len - 1);
1013 } else {
1014 SCVAL(nameptr, -1, 0);
1017 p += len;
1018 break;
1020 case SMB_INFO_QUERY_EA_SIZE:
1021 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1022 if(requires_resume_key) {
1023 SIVAL(p,0,reskey);
1024 p += 4;
1026 put_dos_date2(p,l2_fdateCreation,cdate);
1027 put_dos_date2(p,l2_fdateLastAccess,adate);
1028 put_dos_date2(p,l2_fdateLastWrite,mdate);
1029 SIVAL(p,l2_cbFile,(uint32)file_size);
1030 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1031 SSVAL(p,l2_attrFile,mode);
1033 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1034 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1036 p += l2_achName;
1037 nameptr = p - 1;
1038 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1039 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1040 if (len > 2) {
1041 len -= 2;
1042 } else {
1043 len = 0;
1045 } else {
1046 if (len > 1) {
1047 len -= 1;
1048 } else {
1049 len = 0;
1052 SCVAL(nameptr,0,len);
1053 p += len;
1054 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1055 break;
1057 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1058 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1059 was_8_3 = mangle_is_8_3(fname, True);
1060 p += 4;
1061 SIVAL(p,0,reskey); p += 4;
1062 put_long_date(p,cdate); p += 8;
1063 put_long_date(p,adate); p += 8;
1064 put_long_date(p,mdate); p += 8;
1065 put_long_date(p,mdate); p += 8;
1066 SOFF_T(p,0,file_size); p += 8;
1067 SOFF_T(p,0,allocation_size); p += 8;
1068 SIVAL(p,0,nt_extmode); p += 4;
1069 q = p; p += 4; /* q is placeholder for name length. */
1071 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1072 SIVAL(p,0,ea_size); /* Extended attributes */
1073 p += 4;
1075 /* Clear the short name buffer. This is
1076 * IMPORTANT as not doing so will trigger
1077 * a Win2k client bug. JRA.
1079 memset(p,'\0',26);
1080 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1081 pstring mangled_name;
1082 pstrcpy(mangled_name, fname);
1083 mangle_map(mangled_name,True,True,SNUM(conn));
1084 mangled_name[12] = 0;
1085 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1086 SSVAL(p, 0, len);
1087 } else {
1088 SSVAL(p,0,0);
1089 *(p+2) = 0;
1091 p += 2 + 24;
1092 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1093 SIVAL(q,0,len);
1094 p += len;
1095 len = PTR_DIFF(p, pdata);
1096 len = (len + 3) & ~3;
1097 SIVAL(pdata,0,len);
1098 p = pdata + len;
1099 break;
1101 case SMB_FIND_FILE_DIRECTORY_INFO:
1102 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1103 p += 4;
1104 SIVAL(p,0,reskey); p += 4;
1105 put_long_date(p,cdate); p += 8;
1106 put_long_date(p,adate); p += 8;
1107 put_long_date(p,mdate); p += 8;
1108 put_long_date(p,mdate); p += 8;
1109 SOFF_T(p,0,file_size); p += 8;
1110 SOFF_T(p,0,allocation_size); p += 8;
1111 SIVAL(p,0,nt_extmode); p += 4;
1112 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1113 SIVAL(p,0,len);
1114 p += 4 + len;
1115 len = PTR_DIFF(p, pdata);
1116 len = (len + 3) & ~3;
1117 SIVAL(pdata,0,len);
1118 p = pdata + len;
1119 break;
1121 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1122 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1123 p += 4;
1124 SIVAL(p,0,reskey); p += 4;
1125 put_long_date(p,cdate); p += 8;
1126 put_long_date(p,adate); p += 8;
1127 put_long_date(p,mdate); p += 8;
1128 put_long_date(p,mdate); p += 8;
1129 SOFF_T(p,0,file_size); p += 8;
1130 SOFF_T(p,0,allocation_size); p += 8;
1131 SIVAL(p,0,nt_extmode); p += 4;
1132 q = p; p += 4; /* q is placeholder for name length. */
1134 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1135 SIVAL(p,0,ea_size); /* Extended attributes */
1136 p +=4;
1138 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1139 SIVAL(q, 0, len);
1140 p += len;
1142 len = PTR_DIFF(p, pdata);
1143 len = (len + 3) & ~3;
1144 SIVAL(pdata,0,len);
1145 p = pdata + len;
1146 break;
1148 case SMB_FIND_FILE_NAMES_INFO:
1149 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1150 p += 4;
1151 SIVAL(p,0,reskey); p += 4;
1152 p += 4;
1153 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1154 acl on a dir (tridge) */
1155 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1156 SIVAL(p, -4, len);
1157 p += len;
1158 len = PTR_DIFF(p, pdata);
1159 len = (len + 3) & ~3;
1160 SIVAL(pdata,0,len);
1161 p = pdata + len;
1162 break;
1164 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1165 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1166 p += 4;
1167 SIVAL(p,0,reskey); p += 4;
1168 put_long_date(p,cdate); p += 8;
1169 put_long_date(p,adate); p += 8;
1170 put_long_date(p,mdate); p += 8;
1171 put_long_date(p,mdate); p += 8;
1172 SOFF_T(p,0,file_size); p += 8;
1173 SOFF_T(p,0,allocation_size); p += 8;
1174 SIVAL(p,0,nt_extmode); p += 4;
1175 q = p; p += 4; /* q is placeholder for name length. */
1177 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1178 SIVAL(p,0,ea_size); /* Extended attributes */
1179 p +=4;
1181 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1182 SIVAL(p,0,sbuf.st_dev); p += 4;
1183 SIVAL(p,0,sbuf.st_ino); p += 4;
1184 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1185 SIVAL(q, 0, len);
1186 p += len;
1187 len = PTR_DIFF(p, pdata);
1188 len = (len + 3) & ~3;
1189 SIVAL(pdata,0,len);
1190 p = pdata + len;
1191 break;
1193 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1194 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1195 was_8_3 = mangle_is_8_3(fname, True);
1196 p += 4;
1197 SIVAL(p,0,reskey); p += 4;
1198 put_long_date(p,cdate); p += 8;
1199 put_long_date(p,adate); p += 8;
1200 put_long_date(p,mdate); p += 8;
1201 put_long_date(p,mdate); p += 8;
1202 SOFF_T(p,0,file_size); p += 8;
1203 SOFF_T(p,0,allocation_size); p += 8;
1204 SIVAL(p,0,nt_extmode); p += 4;
1205 q = p; p += 4; /* q is placeholder for name length */
1207 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1208 SIVAL(p,0,ea_size); /* Extended attributes */
1209 p +=4;
1211 /* Clear the short name buffer. This is
1212 * IMPORTANT as not doing so will trigger
1213 * a Win2k client bug. JRA.
1215 memset(p,'\0',26);
1216 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1217 pstring mangled_name;
1218 pstrcpy(mangled_name, fname);
1219 mangle_map(mangled_name,True,True,SNUM(conn));
1220 mangled_name[12] = 0;
1221 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1222 SSVAL(p, 0, len);
1223 } else {
1224 SSVAL(p,0,0);
1225 *(p+2) = 0;
1227 p += 26;
1228 SSVAL(p,0,0); p += 2; /* Reserved ? */
1229 SIVAL(p,0,sbuf.st_dev); p += 4;
1230 SIVAL(p,0,sbuf.st_ino); p += 4;
1231 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1232 SIVAL(q,0,len);
1233 p += len;
1234 len = PTR_DIFF(p, pdata);
1235 len = (len + 3) & ~3;
1236 SIVAL(pdata,0,len);
1237 p = pdata + len;
1238 break;
1240 /* CIFS UNIX Extension. */
1242 case SMB_FIND_FILE_UNIX:
1243 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1244 p+= 4;
1245 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1247 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1248 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1249 p+= 8;
1251 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1252 p+= 8;
1254 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1255 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1256 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1257 p+= 24;
1259 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1260 SIVAL(p,4,0);
1261 p+= 8;
1263 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1264 SIVAL(p,4,0);
1265 p+= 8;
1267 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1268 p+= 4;
1270 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1271 SIVAL(p,4,0);
1272 p+= 8;
1274 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1275 SIVAL(p,4,0);
1276 p+= 8;
1278 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1279 p+= 8;
1281 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1282 SIVAL(p,4,0);
1283 p+= 8;
1285 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1286 SIVAL(p,4,0);
1287 p+= 8;
1289 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1290 p += len;
1292 len = PTR_DIFF(p, pdata);
1293 len = (len + 3) & ~3;
1294 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1295 p = pdata + len;
1296 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1298 break;
1300 default:
1301 return(False);
1305 if (PTR_DIFF(p,pdata) > space_remaining) {
1306 /* Move the dirptr back to prev_dirpos */
1307 SeekDir(conn->dirptr, prev_dirpos);
1308 *out_of_space = True;
1309 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1310 return False; /* Not finished - just out of space */
1313 /* Setup the last_filename pointer, as an offset from base_data */
1314 *last_name_off = PTR_DIFF(nameptr,base_data);
1315 /* Advance the data pointer to the next slot */
1316 *ppdata = p;
1318 return(found);
1321 /****************************************************************************
1322 Reply to a TRANS2_FINDFIRST.
1323 ****************************************************************************/
1325 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1326 char **pparams, int total_params, char **ppdata, int total_data,
1327 unsigned int max_data_bytes)
1329 /* We must be careful here that we don't return more than the
1330 allowed number of data bytes. If this means returning fewer than
1331 maxentries then so be it. We assume that the redirector has
1332 enough room for the fixed number of parameter bytes it has
1333 requested. */
1334 char *params = *pparams;
1335 char *pdata = *ppdata;
1336 int dirtype = SVAL(params,0);
1337 int maxentries = SVAL(params,2);
1338 uint16 findfirst_flags = SVAL(params,4);
1339 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1340 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1341 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1342 int info_level = SVAL(params,6);
1343 pstring directory;
1344 pstring mask;
1345 char *p, *wcard;
1346 int last_name_off=0;
1347 int dptr_num = -1;
1348 int numentries = 0;
1349 int i;
1350 BOOL finished = False;
1351 BOOL dont_descend = False;
1352 BOOL out_of_space = False;
1353 int space_remaining;
1354 BOOL bad_path = False;
1355 SMB_STRUCT_STAT sbuf;
1356 NTSTATUS ntstatus = NT_STATUS_OK;
1358 if (total_params < 12)
1359 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1361 *directory = *mask = 0;
1363 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1364 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1365 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1366 info_level, max_data_bytes));
1368 if (!maxentries) {
1369 /* W2K3 seems to treat zero as 1. */
1370 maxentries = 1;
1373 switch (info_level) {
1374 case SMB_INFO_STANDARD:
1375 case SMB_INFO_QUERY_EA_SIZE:
1376 case SMB_FIND_FILE_DIRECTORY_INFO:
1377 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1378 case SMB_FIND_FILE_NAMES_INFO:
1379 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1380 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1381 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1382 break;
1383 case SMB_FIND_FILE_UNIX:
1384 if (!lp_unix_extensions())
1385 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1386 break;
1387 default:
1388 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1391 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1392 if (!NT_STATUS_IS_OK(ntstatus)) {
1393 return ERROR_NT(ntstatus);
1396 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1398 unix_convert(directory,conn,0,&bad_path,&sbuf);
1399 if (bad_path) {
1400 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1402 if(!check_name(directory,conn)) {
1403 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1406 p = strrchr_m(directory,'/');
1407 if(p == NULL) {
1408 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1409 if((directory[0] == '.') && (directory[1] == '\0'))
1410 pstrcpy(mask,"*");
1411 else
1412 pstrcpy(mask,directory);
1413 pstrcpy(directory,"./");
1414 } else {
1415 pstrcpy(mask,p+1);
1416 *p = 0;
1419 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1421 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1422 if( pdata == NULL )
1423 return(ERROR_DOS(ERRDOS,ERRnomem));
1425 *ppdata = pdata;
1426 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1428 /* Realloc the params space */
1429 params = SMB_REALLOC(*pparams, 10);
1430 if (params == NULL)
1431 return ERROR_DOS(ERRDOS,ERRnomem);
1432 *pparams = params;
1434 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1435 if (dptr_num < 0)
1436 return(UNIXERROR(ERRDOS,ERRbadfile));
1438 /* Save the wildcard match and attribs we are using on this directory -
1439 needed as lanman2 assumes these are being saved between calls */
1441 if(!(wcard = SMB_STRDUP(mask))) {
1442 dptr_close(&dptr_num);
1443 return ERROR_DOS(ERRDOS,ERRnomem);
1446 dptr_set_wcard(dptr_num, wcard);
1447 dptr_set_attr(dptr_num, dirtype);
1449 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1451 /* We don't need to check for VOL here as this is returned by
1452 a different TRANS2 call. */
1454 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1455 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1456 dont_descend = True;
1458 p = pdata;
1459 space_remaining = max_data_bytes;
1460 out_of_space = False;
1462 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1463 BOOL got_exact_match = False;
1465 /* this is a heuristic to avoid seeking the dirptr except when
1466 absolutely necessary. It allows for a filename of about 40 chars */
1467 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1468 out_of_space = True;
1469 finished = False;
1470 } else {
1471 finished = !get_lanman2_dir_entry(conn,
1472 inbuf, outbuf,
1473 mask,dirtype,info_level,
1474 requires_resume_key,dont_descend,
1475 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1476 &last_name_off);
1479 if (finished && out_of_space)
1480 finished = False;
1482 if (!finished && !out_of_space)
1483 numentries++;
1486 * As an optimisation if we know we aren't looking
1487 * for a wildcard name (ie. the name matches the wildcard exactly)
1488 * then we can finish on any (first) match.
1489 * This speeds up large directory searches. JRA.
1492 if(got_exact_match)
1493 finished = True;
1495 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1498 /* Check if we can close the dirptr */
1499 if(close_after_first || (finished && close_if_end)) {
1500 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1501 dptr_close(&dptr_num);
1505 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1506 * from observation of NT.
1509 if(numentries == 0) {
1510 dptr_close(&dptr_num);
1511 return ERROR_DOS(ERRDOS,ERRbadfile);
1514 /* At this point pdata points to numentries directory entries. */
1516 /* Set up the return parameter block */
1517 SSVAL(params,0,dptr_num);
1518 SSVAL(params,2,numentries);
1519 SSVAL(params,4,finished);
1520 SSVAL(params,6,0); /* Never an EA error */
1521 SSVAL(params,8,last_name_off);
1523 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1525 if ((! *directory) && dptr_path(dptr_num))
1526 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1528 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1529 smb_fn_name(CVAL(inbuf,smb_com)),
1530 mask, directory, dirtype, numentries ) );
1533 * Force a name mangle here to ensure that the
1534 * mask as an 8.3 name is top of the mangled cache.
1535 * The reasons for this are subtle. Don't remove
1536 * this code unless you know what you are doing
1537 * (see PR#13758). JRA.
1540 if(!mangle_is_8_3_wildcards( mask, False))
1541 mangle_map(mask, True, True, SNUM(conn));
1543 return(-1);
1546 /****************************************************************************
1547 Reply to a TRANS2_FINDNEXT.
1548 ****************************************************************************/
1550 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1551 char **pparams, int total_params, char **ppdata, int total_data,
1552 unsigned int max_data_bytes)
1554 /* We must be careful here that we don't return more than the
1555 allowed number of data bytes. If this means returning fewer than
1556 maxentries then so be it. We assume that the redirector has
1557 enough room for the fixed number of parameter bytes it has
1558 requested. */
1559 char *params = *pparams;
1560 char *pdata = *ppdata;
1561 int dptr_num = SVAL(params,0);
1562 int maxentries = SVAL(params,2);
1563 uint16 info_level = SVAL(params,4);
1564 uint32 resume_key = IVAL(params,6);
1565 uint16 findnext_flags = SVAL(params,10);
1566 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1567 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1568 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1569 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1570 pstring resume_name;
1571 pstring mask;
1572 pstring directory;
1573 char *p;
1574 uint16 dirtype;
1575 int numentries = 0;
1576 int i, last_name_off=0;
1577 BOOL finished = False;
1578 BOOL dont_descend = False;
1579 BOOL out_of_space = False;
1580 int space_remaining;
1581 NTSTATUS ntstatus = NT_STATUS_OK;
1583 if (total_params < 12)
1584 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1586 *mask = *directory = *resume_name = 0;
1588 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1589 if (!NT_STATUS_IS_OK(ntstatus)) {
1590 return ERROR_NT(ntstatus);
1593 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1594 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1595 resume_key = %d resume name = %s continue=%d level = %d\n",
1596 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1597 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1599 if (!maxentries) {
1600 /* W2K3 seems to treat zero as 1. */
1601 maxentries = 1;
1604 switch (info_level) {
1605 case SMB_INFO_STANDARD:
1606 case SMB_INFO_QUERY_EA_SIZE:
1607 case SMB_FIND_FILE_DIRECTORY_INFO:
1608 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1609 case SMB_FIND_FILE_NAMES_INFO:
1610 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1611 break;
1612 case SMB_FIND_FILE_UNIX:
1613 if (!lp_unix_extensions())
1614 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1615 break;
1616 default:
1617 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1620 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1621 if(pdata == NULL)
1622 return ERROR_DOS(ERRDOS,ERRnomem);
1624 *ppdata = pdata;
1625 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1627 /* Realloc the params space */
1628 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1629 if( params == NULL )
1630 return ERROR_DOS(ERRDOS,ERRnomem);
1632 *pparams = params;
1634 /* Check that the dptr is valid */
1635 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1636 return ERROR_DOS(ERRDOS,ERRnofiles);
1638 string_set(&conn->dirpath,dptr_path(dptr_num));
1640 /* Get the wildcard mask from the dptr */
1641 if((p = dptr_wcard(dptr_num))== NULL) {
1642 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1643 return ERROR_DOS(ERRDOS,ERRnofiles);
1646 pstrcpy(mask, p);
1647 pstrcpy(directory,conn->dirpath);
1649 /* Get the attr mask from the dptr */
1650 dirtype = dptr_attr(dptr_num);
1652 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1653 dptr_num, mask, dirtype,
1654 (long)conn->dirptr,
1655 TellDir(conn->dirptr)));
1657 /* We don't need to check for VOL here as this is returned by
1658 a different TRANS2 call. */
1660 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1661 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1662 dont_descend = True;
1664 p = pdata;
1665 space_remaining = max_data_bytes;
1666 out_of_space = False;
1669 * Seek to the correct position. We no longer use the resume key but
1670 * depend on the last file name instead.
1673 if(*resume_name && !continue_bit) {
1676 * Fix for NT redirector problem triggered by resume key indexes
1677 * changing between directory scans. We now return a resume key of 0
1678 * and instead look for the filename to continue from (also given
1679 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1680 * findfirst/findnext (as is usual) then the directory pointer
1681 * should already be at the correct place. Check this by scanning
1682 * backwards looking for an exact (ie. case sensitive) filename match.
1683 * If we get to the beginning of the directory and haven't found it then scan
1684 * forwards again looking for a match. JRA.
1687 int current_pos, start_pos;
1688 const char *dname = NULL;
1689 pstring dname_pstring;
1690 void *dirptr = conn->dirptr;
1691 start_pos = TellDir(dirptr);
1692 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1693 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1695 SeekDir(dirptr, current_pos);
1696 dname = ReadDirName(dirptr);
1697 if (dname) {
1699 * Remember, mangle_map is called by
1700 * get_lanman2_dir_entry(), so the resume name
1701 * could be mangled. Ensure we do the same
1702 * here.
1705 /* make sure we get a copy that mangle_map can modify */
1707 pstrcpy(dname_pstring, dname);
1708 mangle_map( dname_pstring, False, True, SNUM(conn));
1710 if(strcsequal( resume_name, dname_pstring)) {
1711 SeekDir(dirptr, current_pos+1);
1712 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1713 break;
1719 * Scan forward from start if not found going backwards.
1722 if(current_pos < 0) {
1723 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1724 SeekDir(dirptr, start_pos);
1725 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; ++current_pos) {
1728 * Remember, mangle_map is called by
1729 * get_lanman2_dir_entry(), so the resume name
1730 * could be mangled. Ensure we do the same
1731 * here.
1734 if(dname) {
1735 /* make sure we get a copy that mangle_map can modify */
1737 pstrcpy(dname_pstring, dname);
1738 mangle_map(dname_pstring, False, True, SNUM(conn));
1740 if(strcsequal( resume_name, dname_pstring)) {
1741 SeekDir(dirptr, current_pos+1);
1742 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1743 break;
1746 } /* end for */
1747 } /* end if current_pos */
1748 /* Can't find the name. Just resume from where we were... */
1749 if (dname == 0) {
1750 SeekDir(dirptr, start_pos);
1752 } /* end if resume_name && !continue_bit */
1754 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1755 BOOL got_exact_match = False;
1757 /* this is a heuristic to avoid seeking the dirptr except when
1758 absolutely necessary. It allows for a filename of about 40 chars */
1759 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1760 out_of_space = True;
1761 finished = False;
1762 } else {
1763 finished = !get_lanman2_dir_entry(conn,
1764 inbuf, outbuf,
1765 mask,dirtype,info_level,
1766 requires_resume_key,dont_descend,
1767 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1768 &last_name_off);
1771 if (finished && out_of_space)
1772 finished = False;
1774 if (!finished && !out_of_space)
1775 numentries++;
1778 * As an optimisation if we know we aren't looking
1779 * for a wildcard name (ie. the name matches the wildcard exactly)
1780 * then we can finish on any (first) match.
1781 * This speeds up large directory searches. JRA.
1784 if(got_exact_match)
1785 finished = True;
1787 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1790 /* Check if we can close the dirptr */
1791 if(close_after_request || (finished && close_if_end)) {
1792 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1793 dptr_close(&dptr_num); /* This frees up the saved mask */
1796 /* Set up the return parameter block */
1797 SSVAL(params,0,numentries);
1798 SSVAL(params,2,finished);
1799 SSVAL(params,4,0); /* Never an EA error */
1800 SSVAL(params,6,last_name_off);
1802 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1804 if ((! *directory) && dptr_path(dptr_num))
1805 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1807 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1808 smb_fn_name(CVAL(inbuf,smb_com)),
1809 mask, directory, dirtype, numentries ) );
1811 return(-1);
1814 /****************************************************************************
1815 Reply to a TRANS2_QFSINFO (query filesystem info).
1816 ****************************************************************************/
1818 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1819 char **pparams, int total_params, char **ppdata, int total_data,
1820 unsigned int max_data_bytes)
1822 char *pdata = *ppdata;
1823 char *params = *pparams;
1824 uint16 info_level = SVAL(params,0);
1825 int data_len, len;
1826 SMB_STRUCT_STAT st;
1827 char *vname = volume_label(SNUM(conn));
1828 int snum = SNUM(conn);
1829 char *fstype = lp_fstype(SNUM(conn));
1830 int quota_flag = 0;
1832 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1834 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1835 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1836 return ERROR_DOS(ERRSRV,ERRinvdevice);
1839 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1840 if ( pdata == NULL )
1841 return ERROR_DOS(ERRDOS,ERRnomem);
1843 *ppdata = pdata;
1844 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1846 switch (info_level) {
1847 case SMB_INFO_ALLOCATION:
1849 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1850 data_len = 18;
1851 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1852 block_size = lp_block_size(snum);
1853 if (bsize < block_size) {
1854 SMB_BIG_UINT factor = block_size/bsize;
1855 bsize = block_size;
1856 dsize /= factor;
1857 dfree /= factor;
1859 if (bsize > block_size) {
1860 SMB_BIG_UINT factor = bsize/block_size;
1861 bsize = block_size;
1862 dsize *= factor;
1863 dfree *= factor;
1865 bytes_per_sector = 512;
1866 sectors_per_unit = bsize/bytes_per_sector;
1868 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1869 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1870 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1872 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1873 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1874 SIVAL(pdata,l1_cUnit,dsize);
1875 SIVAL(pdata,l1_cUnitAvail,dfree);
1876 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1877 break;
1880 case SMB_INFO_VOLUME:
1881 /* Return volume name */
1883 * Add volume serial number - hash of a combination of
1884 * the called hostname and the service name.
1886 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1887 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1888 SCVAL(pdata,l2_vol_cch,len);
1889 data_len = l2_vol_szVolLabel + len;
1890 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1891 (unsigned)st.st_ctime, len, vname));
1892 break;
1894 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1895 case SMB_FS_ATTRIBUTE_INFORMATION:
1898 #if defined(HAVE_SYS_QUOTAS)
1899 quota_flag = FILE_VOLUME_QUOTAS;
1900 #endif
1902 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1903 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1904 quota_flag); /* FS ATTRIBUTES */
1906 SIVAL(pdata,4,255); /* Max filename component length */
1907 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1908 and will think we can't do long filenames */
1909 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1910 SIVAL(pdata,8,len);
1911 data_len = 12 + len;
1912 break;
1914 case SMB_QUERY_FS_LABEL_INFO:
1915 case SMB_FS_LABEL_INFORMATION:
1916 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1917 data_len = 4 + len;
1918 SIVAL(pdata,0,len);
1919 break;
1921 case SMB_QUERY_FS_VOLUME_INFO:
1922 case SMB_FS_VOLUME_INFORMATION:
1925 * Add volume serial number - hash of a combination of
1926 * the called hostname and the service name.
1928 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1929 (str_checksum(local_machine)<<16));
1931 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1932 SIVAL(pdata,12,len);
1933 data_len = 18+len;
1934 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1935 (int)strlen(vname),vname, lp_servicename(snum)));
1936 break;
1938 case SMB_QUERY_FS_SIZE_INFO:
1939 case SMB_FS_SIZE_INFORMATION:
1941 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1942 data_len = 24;
1943 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1944 block_size = lp_block_size(snum);
1945 if (bsize < block_size) {
1946 SMB_BIG_UINT factor = block_size/bsize;
1947 bsize = block_size;
1948 dsize /= factor;
1949 dfree /= factor;
1951 if (bsize > block_size) {
1952 SMB_BIG_UINT factor = bsize/block_size;
1953 bsize = block_size;
1954 dsize *= factor;
1955 dfree *= factor;
1957 bytes_per_sector = 512;
1958 sectors_per_unit = bsize/bytes_per_sector;
1959 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1960 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1961 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1962 SBIG_UINT(pdata,0,dsize);
1963 SBIG_UINT(pdata,8,dfree);
1964 SIVAL(pdata,16,sectors_per_unit);
1965 SIVAL(pdata,20,bytes_per_sector);
1966 break;
1969 case SMB_FS_FULL_SIZE_INFORMATION:
1971 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1972 data_len = 32;
1973 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1974 block_size = lp_block_size(snum);
1975 if (bsize < block_size) {
1976 SMB_BIG_UINT factor = block_size/bsize;
1977 bsize = block_size;
1978 dsize /= factor;
1979 dfree /= factor;
1981 if (bsize > block_size) {
1982 SMB_BIG_UINT factor = bsize/block_size;
1983 bsize = block_size;
1984 dsize *= factor;
1985 dfree *= factor;
1987 bytes_per_sector = 512;
1988 sectors_per_unit = bsize/bytes_per_sector;
1989 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1990 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1991 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1992 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1993 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1994 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1995 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1996 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1997 break;
2000 case SMB_QUERY_FS_DEVICE_INFO:
2001 case SMB_FS_DEVICE_INFORMATION:
2002 data_len = 8;
2003 SIVAL(pdata,0,0); /* dev type */
2004 SIVAL(pdata,4,0); /* characteristics */
2005 break;
2007 #ifdef HAVE_SYS_QUOTAS
2008 case SMB_FS_QUOTA_INFORMATION:
2010 * what we have to send --metze:
2012 * Unknown1: 24 NULL bytes
2013 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2014 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2015 * Quota Flags: 2 byte :
2016 * Unknown3: 6 NULL bytes
2018 * 48 bytes total
2020 * details for Quota Flags:
2022 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2023 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2024 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2025 * 0x0001 Enable Quotas: enable quota for this fs
2029 /* we need to fake up a fsp here,
2030 * because its not send in this call
2032 files_struct fsp;
2033 SMB_NTQUOTA_STRUCT quotas;
2035 ZERO_STRUCT(fsp);
2036 ZERO_STRUCT(quotas);
2038 fsp.conn = conn;
2039 fsp.fnum = -1;
2040 fsp.fd = -1;
2042 /* access check */
2043 if (current_user.uid != 0) {
2044 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2045 lp_servicename(SNUM(conn)),conn->user));
2046 return ERROR_DOS(ERRDOS,ERRnoaccess);
2049 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2050 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2051 return ERROR_DOS(ERRSRV,ERRerror);
2054 data_len = 48;
2056 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2058 /* Unknown1 24 NULL bytes*/
2059 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2060 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2061 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2063 /* Default Soft Quota 8 bytes */
2064 SBIG_UINT(pdata,24,quotas.softlim);
2066 /* Default Hard Quota 8 bytes */
2067 SBIG_UINT(pdata,32,quotas.hardlim);
2069 /* Quota flag 2 bytes */
2070 SSVAL(pdata,40,quotas.qflags);
2072 /* Unknown3 6 NULL bytes */
2073 SSVAL(pdata,42,0);
2074 SIVAL(pdata,44,0);
2076 break;
2078 #endif /* HAVE_SYS_QUOTAS */
2079 case SMB_FS_OBJECTID_INFORMATION:
2080 data_len = 64;
2081 break;
2084 * Query the version and capabilities of the CIFS UNIX extensions
2085 * in use.
2088 case SMB_QUERY_CIFS_UNIX_INFO:
2089 if (!lp_unix_extensions())
2090 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2091 data_len = 12;
2092 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2093 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2094 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2095 break;
2097 case SMB_MAC_QUERY_FS_INFO:
2099 * Thursby MAC extension... ONLY on NTFS filesystems
2100 * once we do streams then we don't need this
2102 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2103 data_len = 88;
2104 SIVAL(pdata,84,0x100); /* Don't support mac... */
2105 break;
2107 /* drop through */
2108 default:
2109 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2113 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2115 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2117 return -1;
2120 #ifdef HAVE_SYS_QUOTAS
2121 /****************************************************************************
2122 Reply to a TRANS2_SETFSINFO (set filesystem info).
2123 ****************************************************************************/
2125 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2126 char **pparams, int total_params, char **ppdata, int total_data,
2127 unsigned int max_data_bytes)
2129 char *pdata = *ppdata;
2130 char *params = *pparams;
2131 files_struct *fsp = NULL;
2132 uint16 info_level;
2133 int outsize;
2134 SMB_NTQUOTA_STRUCT quotas;
2136 ZERO_STRUCT(quotas);
2138 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2140 /* access check */
2141 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2142 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2143 lp_servicename(SNUM(conn)),conn->user));
2144 return ERROR_DOS(ERRSRV,ERRaccess);
2147 /* */
2148 if (total_params < 4) {
2149 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2150 total_params));
2151 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2154 fsp = file_fsp(params,0);
2156 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2157 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2158 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2161 info_level = SVAL(params,2);
2163 switch(info_level) {
2164 case SMB_FS_QUOTA_INFORMATION:
2165 /* note: normaly there're 48 bytes,
2166 * but we didn't use the last 6 bytes for now
2167 * --metze
2169 if (total_data < 42) {
2170 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2171 total_data));
2172 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2175 /* unknown_1 24 NULL bytes in pdata*/
2177 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2178 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2179 #ifdef LARGE_SMB_OFF_T
2180 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2181 #else /* LARGE_SMB_OFF_T */
2182 if ((IVAL(pdata,28) != 0)&&
2183 ((quotas.softlim != 0xFFFFFFFF)||
2184 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2185 /* more than 32 bits? */
2186 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2188 #endif /* LARGE_SMB_OFF_T */
2190 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2191 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2192 #ifdef LARGE_SMB_OFF_T
2193 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2194 #else /* LARGE_SMB_OFF_T */
2195 if ((IVAL(pdata,36) != 0)&&
2196 ((quotas.hardlim != 0xFFFFFFFF)||
2197 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2198 /* more than 32 bits? */
2199 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2201 #endif /* LARGE_SMB_OFF_T */
2203 /* quota_flags 2 bytes **/
2204 quotas.qflags = SVAL(pdata,40);
2206 /* unknown_2 6 NULL bytes follow*/
2208 /* now set the quotas */
2209 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2210 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2211 return ERROR_DOS(ERRSRV,ERRerror);
2214 break;
2215 default:
2216 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2217 info_level));
2218 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2219 break;
2223 * sending this reply works fine,
2224 * but I'm not sure it's the same
2225 * like windows do...
2226 * --metze
2228 outsize = set_message(outbuf,10,0,True);
2230 return outsize;
2232 #endif /* HAVE_SYS_QUOTAS */
2234 /****************************************************************************
2235 Utility function to set bad path error.
2236 ****************************************************************************/
2238 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2240 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2241 err, (int)bad_path ));
2243 if(err == ENOENT) {
2244 if (bad_path) {
2245 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2246 } else {
2247 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2250 return UNIXERROR(def_class,def_code);
2253 /****************************************************************************
2254 Utility function to count the number of entries in a POSIX acl.
2255 ****************************************************************************/
2257 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2259 unsigned int ace_count = 0;
2260 int entry_id = SMB_ACL_FIRST_ENTRY;
2261 SMB_ACL_ENTRY_T entry;
2263 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2264 /* get_next... */
2265 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2266 entry_id = SMB_ACL_NEXT_ENTRY;
2268 ace_count++;
2270 return ace_count;
2273 /****************************************************************************
2274 Utility function to marshall a POSIX acl into wire format.
2275 ****************************************************************************/
2277 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2279 int entry_id = SMB_ACL_FIRST_ENTRY;
2280 SMB_ACL_ENTRY_T entry;
2282 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2283 SMB_ACL_TAG_T tagtype;
2284 SMB_ACL_PERMSET_T permset;
2285 unsigned char perms = 0;
2286 unsigned int own_grp;
2288 /* get_next... */
2289 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2290 entry_id = SMB_ACL_NEXT_ENTRY;
2293 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2294 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2295 return False;
2298 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2299 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2300 return False;
2303 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2304 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2305 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2307 SCVAL(pdata,1,perms);
2309 switch (tagtype) {
2310 case SMB_ACL_USER_OBJ:
2311 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2312 own_grp = (unsigned int)pst->st_uid;
2313 SIVAL(pdata,2,own_grp);
2314 SIVAL(pdata,6,0);
2315 break;
2316 case SMB_ACL_USER:
2318 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2319 if (!puid) {
2320 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2322 own_grp = (unsigned int)*puid;
2323 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2324 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2325 SIVAL(pdata,2,own_grp);
2326 SIVAL(pdata,6,0);
2327 break;
2329 case SMB_ACL_GROUP_OBJ:
2330 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2331 own_grp = (unsigned int)pst->st_gid;
2332 SIVAL(pdata,2,own_grp);
2333 SIVAL(pdata,6,0);
2334 break;
2335 case SMB_ACL_GROUP:
2337 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2338 if (!pgid) {
2339 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2341 own_grp = (unsigned int)*pgid;
2342 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2343 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2344 SIVAL(pdata,2,own_grp);
2345 SIVAL(pdata,6,0);
2346 break;
2348 case SMB_ACL_MASK:
2349 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2350 SIVAL(pdata,2,0xFFFFFFFF);
2351 SIVAL(pdata,6,0xFFFFFFFF);
2352 break;
2353 case SMB_ACL_OTHER:
2354 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2355 SIVAL(pdata,2,0xFFFFFFFF);
2356 SIVAL(pdata,6,0xFFFFFFFF);
2357 break;
2358 default:
2359 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2360 return False;
2362 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2365 return True;
2368 /****************************************************************************
2369 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2370 file name or file id).
2371 ****************************************************************************/
2373 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2374 char **pparams, int total_params, char **ppdata, int total_data,
2375 unsigned int max_data_bytes)
2377 char *params = *pparams;
2378 char *pdata = *ppdata;
2379 uint16 tran_call = SVAL(inbuf, smb_setup0);
2380 uint16 info_level;
2381 int mode=0;
2382 SMB_OFF_T file_size=0;
2383 SMB_BIG_UINT allocation_size=0;
2384 unsigned int data_size;
2385 unsigned int param_size = 2;
2386 SMB_STRUCT_STAT sbuf;
2387 pstring fname, dos_fname;
2388 char *fullpathname;
2389 char *base_name;
2390 char *p;
2391 SMB_OFF_T pos = 0;
2392 BOOL bad_path = False;
2393 BOOL delete_pending = False;
2394 int len;
2395 time_t c_time;
2396 files_struct *fsp = NULL;
2397 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2399 if (!params)
2400 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2402 ZERO_STRUCT(sbuf);
2404 if (tran_call == TRANSACT2_QFILEINFO) {
2405 if (total_params < 4)
2406 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2408 fsp = file_fsp(params,0);
2409 info_level = SVAL(params,2);
2411 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2413 if(fsp && (fsp->fake_file_handle)) {
2415 * This is actually for the QUOTA_FAKE_FILE --metze
2418 pstrcpy(fname, fsp->fsp_name);
2419 /* We know this name is ok, it's already passed the checks. */
2421 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2423 * This is actually a QFILEINFO on a directory
2424 * handle (returned from an NT SMB). NT5.0 seems
2425 * to do this call. JRA.
2427 /* We know this name is ok, it's already passed the checks. */
2428 pstrcpy(fname, fsp->fsp_name);
2430 if (INFO_LEVEL_IS_UNIX(info_level)) {
2431 /* Always do lstat for UNIX calls. */
2432 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2433 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2434 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2436 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2437 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2438 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2441 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2442 } else {
2444 * Original code - this is an open file.
2446 CHECK_FSP(fsp,conn);
2448 pstrcpy(fname, fsp->fsp_name);
2449 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2450 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2451 return(UNIXERROR(ERRDOS,ERRbadfid));
2453 pos = fsp->position_information;
2454 delete_pending = fsp->delete_on_close;
2455 desired_access = fsp->desired_access;
2457 } else {
2458 NTSTATUS status = NT_STATUS_OK;
2460 /* qpathinfo */
2461 if (total_params < 6)
2462 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2464 info_level = SVAL(params,0);
2466 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2468 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2469 if (!NT_STATUS_IS_OK(status)) {
2470 return ERROR_NT(status);
2473 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2475 unix_convert(fname,conn,0,&bad_path,&sbuf);
2476 if (bad_path) {
2477 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2479 if (!check_name(fname,conn)) {
2480 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2481 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2484 if (INFO_LEVEL_IS_UNIX(info_level)) {
2485 /* Always do lstat for UNIX calls. */
2486 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2487 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2488 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2490 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2491 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2492 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2496 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2497 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2499 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2500 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2502 p = strrchr_m(fname,'/');
2503 if (!p)
2504 base_name = fname;
2505 else
2506 base_name = p+1;
2508 mode = dos_mode(conn,fname,&sbuf);
2509 if (!mode)
2510 mode = FILE_ATTRIBUTE_NORMAL;
2512 fullpathname = fname;
2513 file_size = get_file_size(sbuf);
2514 allocation_size = get_allocation_size(fsp,&sbuf);
2515 if (mode & aDIR) {
2516 /* This is necessary, as otherwise the desktop.ini file in
2517 * this folder is ignored */
2518 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2519 file_size = 0;
2522 params = SMB_REALLOC(*pparams,2);
2523 if (params == NULL)
2524 return ERROR_DOS(ERRDOS,ERRnomem);
2525 *pparams = params;
2526 memset((char *)params,'\0',2);
2527 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2528 pdata = SMB_REALLOC(*ppdata, data_size);
2529 if ( pdata == NULL )
2530 return ERROR_DOS(ERRDOS,ERRnomem);
2531 *ppdata = pdata;
2533 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2534 /* uggh, EAs for OS2 */
2535 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2536 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2539 memset((char *)pdata,'\0',data_size);
2541 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2543 if (fsp && fsp->pending_modtime) {
2544 /* the pending modtime overrides the current modtime */
2545 sbuf.st_mtime = fsp->pending_modtime;
2548 if (lp_dos_filetime_resolution(SNUM(conn))) {
2549 c_time &= ~1;
2550 sbuf.st_atime &= ~1;
2551 sbuf.st_ctime &= ~1;
2552 sbuf.st_mtime &= ~1;
2555 /* NT expects the name to be in an exact form of the *full*
2556 filename. See the trans2 torture test */
2557 if (strequal(base_name,".")) {
2558 pstrcpy(dos_fname, "\\");
2559 } else {
2560 pstr_sprintf(dos_fname, "\\%s", fname);
2561 string_replace(dos_fname, '/', '\\');
2564 switch (info_level) {
2565 case SMB_INFO_STANDARD:
2566 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2567 data_size = 22;
2568 put_dos_date2(pdata,l1_fdateCreation,c_time);
2569 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2570 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2571 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2572 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2573 SSVAL(pdata,l1_attrFile,mode);
2574 break;
2576 case SMB_INFO_QUERY_EA_SIZE:
2578 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2579 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2580 data_size = 26;
2581 put_dos_date2(pdata,l1_fdateCreation,c_time);
2582 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2583 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2584 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2585 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2586 SSVAL(pdata,l1_attrFile,mode);
2587 SIVAL(pdata,l1_attrFile+2,ea_size);
2588 break;
2591 case SMB_INFO_IS_NAME_VALID:
2592 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2593 if (tran_call == TRANSACT2_QFILEINFO) {
2594 /* os/2 needs this ? really ?*/
2595 return ERROR_DOS(ERRDOS,ERRbadfunc);
2597 data_size = 0;
2598 param_size = 0;
2599 break;
2601 case SMB_INFO_QUERY_EAS_FROM_LIST:
2602 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2603 data_size = 24;
2604 put_dos_date2(pdata,0,c_time);
2605 put_dos_date2(pdata,4,sbuf.st_atime);
2606 put_dos_date2(pdata,8,sbuf.st_mtime);
2607 SIVAL(pdata,12,(uint32)file_size);
2608 SIVAL(pdata,16,(uint32)allocation_size);
2609 SIVAL(pdata,20,mode);
2610 break;
2612 case SMB_INFO_QUERY_ALL_EAS:
2613 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2614 /* We have data_size bytes to put EA's into. */
2615 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2616 break;
2618 case SMB_FILE_BASIC_INFORMATION:
2619 case SMB_QUERY_FILE_BASIC_INFO:
2621 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2622 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2623 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2624 } else {
2625 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2626 data_size = 40;
2627 SIVAL(pdata,36,0);
2629 put_long_date(pdata,c_time);
2630 put_long_date(pdata+8,sbuf.st_atime);
2631 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2632 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2633 SIVAL(pdata,32,mode);
2635 DEBUG(5,("SMB_QFBI - "));
2637 time_t create_time = c_time;
2638 DEBUG(5,("create: %s ", ctime(&create_time)));
2640 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2641 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2642 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2643 DEBUG(5,("mode: %x\n", mode));
2645 break;
2647 case SMB_FILE_STANDARD_INFORMATION:
2648 case SMB_QUERY_FILE_STANDARD_INFO:
2650 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2651 data_size = 24;
2652 SOFF_T(pdata,0,allocation_size);
2653 SOFF_T(pdata,8,file_size);
2654 if (delete_pending & sbuf.st_nlink)
2655 SIVAL(pdata,16,sbuf.st_nlink - 1);
2656 else
2657 SIVAL(pdata,16,sbuf.st_nlink);
2658 SCVAL(pdata,20,0);
2659 SCVAL(pdata,21,(mode&aDIR)?1:0);
2660 break;
2662 case SMB_FILE_EA_INFORMATION:
2663 case SMB_QUERY_FILE_EA_INFO:
2665 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2666 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2667 data_size = 4;
2668 SIVAL(pdata,0,ea_size);
2669 break;
2672 /* Get the 8.3 name - used if NT SMB was negotiated. */
2673 case SMB_QUERY_FILE_ALT_NAME_INFO:
2674 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2676 pstring short_name;
2678 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2679 pstrcpy(short_name,base_name);
2680 /* Mangle if not already 8.3 */
2681 if(!mangle_is_8_3(short_name, True)) {
2682 mangle_map(short_name,True,True,SNUM(conn));
2684 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2685 data_size = 4 + len;
2686 SIVAL(pdata,0,len);
2687 break;
2690 case SMB_QUERY_FILE_NAME_INFO:
2692 this must be *exactly* right for ACLs on mapped drives to work
2694 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2695 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2696 data_size = 4 + len;
2697 SIVAL(pdata,0,len);
2698 break;
2700 case SMB_FILE_ALLOCATION_INFORMATION:
2701 case SMB_QUERY_FILE_ALLOCATION_INFO:
2702 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2703 data_size = 8;
2704 SOFF_T(pdata,0,allocation_size);
2705 break;
2707 case SMB_FILE_END_OF_FILE_INFORMATION:
2708 case SMB_QUERY_FILE_END_OF_FILEINFO:
2709 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2710 data_size = 8;
2711 SOFF_T(pdata,0,file_size);
2712 break;
2714 case SMB_QUERY_FILE_ALL_INFO:
2715 case SMB_FILE_ALL_INFORMATION:
2717 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2718 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2719 put_long_date(pdata,c_time);
2720 put_long_date(pdata+8,sbuf.st_atime);
2721 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2722 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2723 SIVAL(pdata,32,mode);
2724 pdata += 40;
2725 SOFF_T(pdata,0,allocation_size);
2726 SOFF_T(pdata,8,file_size);
2727 if (delete_pending && sbuf.st_nlink)
2728 SIVAL(pdata,16,sbuf.st_nlink - 1);
2729 else
2730 SIVAL(pdata,16,sbuf.st_nlink);
2731 SCVAL(pdata,20,delete_pending);
2732 SCVAL(pdata,21,(mode&aDIR)?1:0);
2733 pdata += 24;
2734 SIVAL(pdata,0,ea_size);
2735 pdata += 4; /* EA info */
2736 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2737 SIVAL(pdata,0,len);
2738 pdata += 4 + len;
2739 data_size = PTR_DIFF(pdata,(*ppdata));
2740 break;
2742 case SMB_FILE_INTERNAL_INFORMATION:
2743 /* This should be an index number - looks like
2744 dev/ino to me :-)
2746 I think this causes us to fail the IFSKIT
2747 BasicFileInformationTest. -tpot */
2749 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2750 SIVAL(pdata,0,sbuf.st_dev);
2751 SIVAL(pdata,4,sbuf.st_ino);
2752 data_size = 8;
2753 break;
2755 case SMB_FILE_ACCESS_INFORMATION:
2756 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2757 SIVAL(pdata,0,desired_access);
2758 data_size = 4;
2759 break;
2761 case SMB_FILE_NAME_INFORMATION:
2762 /* Pathname with leading '\'. */
2764 size_t byte_len;
2765 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2766 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2767 SIVAL(pdata,0,byte_len);
2768 data_size = 4 + byte_len;
2769 break;
2772 case SMB_FILE_DISPOSITION_INFORMATION:
2773 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2774 data_size = 1;
2775 SCVAL(pdata,0,delete_pending);
2776 break;
2778 case SMB_FILE_POSITION_INFORMATION:
2779 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2780 data_size = 8;
2781 SOFF_T(pdata,0,pos);
2782 break;
2784 case SMB_FILE_MODE_INFORMATION:
2785 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2786 SIVAL(pdata,0,mode);
2787 data_size = 4;
2788 break;
2790 case SMB_FILE_ALIGNMENT_INFORMATION:
2791 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2792 SIVAL(pdata,0,0); /* No alignment needed. */
2793 data_size = 4;
2794 break;
2796 #if 0
2798 * NT4 server just returns "invalid query" to this - if we try to answer
2799 * it then NTws gets a BSOD! (tridge).
2800 * W2K seems to want this. JRA.
2802 case SMB_QUERY_FILE_STREAM_INFO:
2803 #endif
2804 case SMB_FILE_STREAM_INFORMATION:
2805 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2806 if (mode & aDIR) {
2807 data_size = 0;
2808 } else {
2809 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2810 SIVAL(pdata,0,0); /* ??? */
2811 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2812 SOFF_T(pdata,8,file_size);
2813 SIVAL(pdata,16,allocation_size);
2814 SIVAL(pdata,20,0); /* ??? */
2815 data_size = 24 + byte_len;
2817 break;
2819 case SMB_QUERY_COMPRESSION_INFO:
2820 case SMB_FILE_COMPRESSION_INFORMATION:
2821 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2822 SOFF_T(pdata,0,file_size);
2823 SIVAL(pdata,8,0); /* ??? */
2824 SIVAL(pdata,12,0); /* ??? */
2825 data_size = 16;
2826 break;
2828 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2829 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2830 put_long_date(pdata,c_time);
2831 put_long_date(pdata+8,sbuf.st_atime);
2832 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2833 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2834 SIVAL(pdata,32,allocation_size);
2835 SOFF_T(pdata,40,file_size);
2836 SIVAL(pdata,48,mode);
2837 SIVAL(pdata,52,0); /* ??? */
2838 data_size = 56;
2839 break;
2841 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2842 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2843 SIVAL(pdata,0,mode);
2844 SIVAL(pdata,4,0);
2845 data_size = 8;
2846 break;
2849 * CIFS UNIX Extensions.
2852 case SMB_QUERY_FILE_UNIX_BASIC:
2854 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2855 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2857 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2858 pdata += 8;
2860 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2861 pdata += 8;
2863 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2864 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2865 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2866 pdata += 24;
2868 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2869 SIVAL(pdata,4,0);
2870 pdata += 8;
2872 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2873 SIVAL(pdata,4,0);
2874 pdata += 8;
2876 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2877 pdata += 4;
2879 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2880 SIVAL(pdata,4,0);
2881 pdata += 8;
2883 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2884 SIVAL(pdata,4,0);
2885 pdata += 8;
2887 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2888 pdata += 8;
2890 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2891 SIVAL(pdata,4,0);
2892 pdata += 8;
2894 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2895 SIVAL(pdata,4,0);
2896 pdata += 8+1;
2897 data_size = PTR_DIFF(pdata,(*ppdata));
2900 int i;
2901 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2903 for (i=0; i<100; i++)
2904 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2905 DEBUG(4,("\n"));
2908 break;
2910 case SMB_QUERY_FILE_UNIX_LINK:
2912 pstring buffer;
2914 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2915 #ifdef S_ISLNK
2916 if(!S_ISLNK(sbuf.st_mode))
2917 return(UNIXERROR(ERRSRV,ERRbadlink));
2918 #else
2919 return(UNIXERROR(ERRDOS,ERRbadlink));
2920 #endif
2921 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2922 if (len == -1)
2923 return(UNIXERROR(ERRDOS,ERRnoaccess));
2924 buffer[len] = 0;
2925 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2926 pdata += len;
2927 data_size = PTR_DIFF(pdata,(*ppdata));
2929 break;
2932 case SMB_QUERY_POSIX_ACL:
2934 SMB_ACL_T file_acl = NULL;
2935 SMB_ACL_T def_acl = NULL;
2936 uint16 num_file_acls = 0;
2937 uint16 num_def_acls = 0;
2939 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
2940 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
2941 } else {
2942 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
2945 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2946 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
2947 fname ));
2948 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
2951 if (S_ISDIR(sbuf.st_mode)) {
2952 if (fsp && fsp->is_directory) {
2953 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2954 } else {
2955 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
2957 def_acl = free_empty_sys_acl(conn, def_acl);
2960 num_file_acls = count_acl_entries(conn, file_acl);
2961 num_def_acls = count_acl_entries(conn, def_acl);
2963 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
2964 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
2965 data_size,
2966 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
2967 SMB_POSIX_ACL_HEADER_SIZE) ));
2968 if (file_acl) {
2969 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2971 if (def_acl) {
2972 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2974 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2977 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2978 SSVAL(pdata,2,num_file_acls);
2979 SSVAL(pdata,4,num_def_acls);
2980 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
2981 if (file_acl) {
2982 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2984 if (def_acl) {
2985 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2987 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2989 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
2990 if (file_acl) {
2991 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2993 if (def_acl) {
2994 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2996 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2999 if (file_acl) {
3000 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3002 if (def_acl) {
3003 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3005 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3006 break;
3009 default:
3010 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3013 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3015 return(-1);
3018 /****************************************************************************
3019 Deal with the internal needs of setting the delete on close flag. Note that
3020 as the tdb locking is recursive, it is safe to call this from within
3021 open_file_shared. JRA.
3022 ****************************************************************************/
3024 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3026 if (delete_on_close) {
3028 * Only allow delete on close for writable files.
3031 if (dosmode & aRONLY) {
3032 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3033 fsp->fsp_name ));
3034 return NT_STATUS_CANNOT_DELETE;
3038 * Only allow delete on close for writable shares.
3041 if (!CAN_WRITE(fsp->conn)) {
3042 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3043 fsp->fsp_name ));
3044 return NT_STATUS_ACCESS_DENIED;
3048 * Only allow delete on close for files/directories opened with delete intent.
3051 if (!(fsp->desired_access & DELETE_ACCESS)) {
3052 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3053 fsp->fsp_name ));
3054 return NT_STATUS_ACCESS_DENIED;
3058 if(fsp->is_directory) {
3059 fsp->directory_delete_on_close = delete_on_close;
3060 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3061 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3062 } else {
3063 fsp->delete_on_close = delete_on_close;
3064 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3065 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3068 return NT_STATUS_OK;
3071 /****************************************************************************
3072 Sets the delete on close flag over all share modes on this file.
3073 Modify the share mode entry for all files open
3074 on this device and inode to tell other smbds we have
3075 changed the delete on close flag. This will be noticed
3076 in the close code, the last closer will delete the file
3077 if flag is set.
3078 ****************************************************************************/
3080 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3082 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3083 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3085 if (fsp->is_directory || fsp->is_stat)
3086 return NT_STATUS_OK;
3088 if (lock_share_entry_fsp(fsp) == False)
3089 return NT_STATUS_ACCESS_DENIED;
3091 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3092 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3093 fsp->fsp_name ));
3094 unlock_share_entry_fsp(fsp);
3095 return NT_STATUS_ACCESS_DENIED;
3098 unlock_share_entry_fsp(fsp);
3099 return NT_STATUS_OK;
3102 /****************************************************************************
3103 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3104 code.
3105 ****************************************************************************/
3107 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3109 BOOL bad_path_oldname = False;
3110 BOOL bad_path_newname = False;
3111 SMB_STRUCT_STAT sbuf1, sbuf2;
3112 pstring last_component_oldname;
3113 pstring last_component_newname;
3114 NTSTATUS status = NT_STATUS_OK;
3116 ZERO_STRUCT(sbuf1);
3117 ZERO_STRUCT(sbuf2);
3119 /* No wildcards. */
3120 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3121 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3124 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3125 if (bad_path_oldname) {
3126 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3129 /* Quick check for "." and ".." */
3130 if (last_component_oldname[0] == '.') {
3131 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3132 return NT_STATUS_OBJECT_NAME_INVALID;
3136 /* source must already exist. */
3137 if (!VALID_STAT(sbuf1)) {
3138 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3141 if (!check_name(oldname,conn)) {
3142 return NT_STATUS_ACCESS_DENIED;
3145 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3146 if (bad_path_newname) {
3147 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3150 /* Quick check for "." and ".." */
3151 if (last_component_newname[0] == '.') {
3152 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3153 return NT_STATUS_OBJECT_NAME_INVALID;
3157 /* Disallow if newname already exists. */
3158 if (VALID_STAT(sbuf2)) {
3159 return NT_STATUS_OBJECT_NAME_COLLISION;
3162 if (!check_name(newname,conn)) {
3163 return NT_STATUS_ACCESS_DENIED;
3166 /* No links from a directory. */
3167 if (S_ISDIR(sbuf1.st_mode)) {
3168 return NT_STATUS_FILE_IS_A_DIRECTORY;
3171 /* Ensure this is within the share. */
3172 if (!reduce_name(conn, oldname) != 0)
3173 return NT_STATUS_ACCESS_DENIED;
3175 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3177 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3178 status = map_nt_error_from_unix(errno);
3179 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3180 nt_errstr(status), newname, oldname));
3183 return status;
3186 /****************************************************************************
3187 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3188 ****************************************************************************/
3190 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3191 char **pparams, int total_params, char **ppdata, int total_data,
3192 unsigned int max_data_bytes)
3194 char *params = *pparams;
3195 char *pdata = *ppdata;
3196 uint16 tran_call = SVAL(inbuf, smb_setup0);
3197 uint16 info_level;
3198 int dosmode=0;
3199 SMB_OFF_T size=0;
3200 struct utimbuf tvs;
3201 SMB_STRUCT_STAT sbuf;
3202 pstring fname;
3203 int fd = -1;
3204 BOOL bad_path = False;
3205 files_struct *fsp = NULL;
3206 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3207 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3208 mode_t unixmode = 0;
3209 NTSTATUS status = NT_STATUS_OK;
3211 if (!params)
3212 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3214 ZERO_STRUCT(sbuf);
3216 if (tran_call == TRANSACT2_SETFILEINFO) {
3217 if (total_params < 4)
3218 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3220 fsp = file_fsp(params,0);
3221 info_level = SVAL(params,2);
3223 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3225 * This is actually a SETFILEINFO on a directory
3226 * handle (returned from an NT SMB). NT5.0 seems
3227 * to do this call. JRA.
3229 pstrcpy(fname, fsp->fsp_name);
3230 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3231 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3232 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3234 } else if (fsp && fsp->print_file) {
3236 * Doing a DELETE_ON_CLOSE should cancel a print job.
3238 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3239 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3241 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3243 SSVAL(params,0,0);
3244 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3245 return(-1);
3246 } else
3247 return (UNIXERROR(ERRDOS,ERRbadpath));
3248 } else {
3250 * Original code - this is an open file.
3252 CHECK_FSP(fsp,conn);
3254 pstrcpy(fname, fsp->fsp_name);
3255 fd = fsp->fd;
3257 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3258 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3259 return(UNIXERROR(ERRDOS,ERRbadfid));
3262 } else {
3263 /* set path info */
3264 if (total_params < 6)
3265 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3267 info_level = SVAL(params,0);
3268 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3269 if (!NT_STATUS_IS_OK(status)) {
3270 return ERROR_NT(status);
3272 unix_convert(fname,conn,0,&bad_path,&sbuf);
3273 if (bad_path) {
3274 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3278 * For CIFS UNIX extensions the target name may not exist.
3281 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3282 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3283 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3286 if(!check_name(fname, conn)) {
3287 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3292 if (!CAN_WRITE(conn))
3293 return ERROR_DOS(ERRSRV,ERRaccess);
3295 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3296 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3298 if (VALID_STAT(sbuf))
3299 unixmode = sbuf.st_mode;
3301 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3302 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3304 /* Realloc the parameter and data sizes */
3305 params = SMB_REALLOC(*pparams,2);
3306 if(params == NULL)
3307 return ERROR_DOS(ERRDOS,ERRnomem);
3308 *pparams = params;
3310 SSVAL(params,0,0);
3312 if (fsp && fsp->pending_modtime) {
3313 /* the pending modtime overrides the current modtime */
3314 sbuf.st_mtime = fsp->pending_modtime;
3317 size = get_file_size(sbuf);
3318 tvs.modtime = sbuf.st_mtime;
3319 tvs.actime = sbuf.st_atime;
3320 dosmode = dos_mode(conn,fname,&sbuf);
3321 unixmode = sbuf.st_mode;
3323 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3324 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3326 switch (info_level) {
3327 case SMB_INFO_STANDARD:
3329 if (total_data < 12)
3330 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3332 /* access time */
3333 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3334 /* write time */
3335 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3336 break;
3339 case SMB_INFO_SET_EA:
3340 status = set_ea(conn, fsp, fname, pdata, total_data);
3341 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3342 return ERROR_NT(status);
3343 break;
3345 /* XXXX um, i don't think this is right.
3346 it's also not in the cifs6.txt spec.
3348 case SMB_INFO_QUERY_EAS_FROM_LIST:
3349 if (total_data < 28)
3350 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3352 tvs.actime = make_unix_date2(pdata+8);
3353 tvs.modtime = make_unix_date2(pdata+12);
3354 size = IVAL(pdata,16);
3355 dosmode = IVAL(pdata,24);
3356 break;
3358 /* XXXX nor this. not in cifs6.txt, either. */
3359 case SMB_INFO_QUERY_ALL_EAS:
3360 if (total_data < 28)
3361 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3363 tvs.actime = make_unix_date2(pdata+8);
3364 tvs.modtime = make_unix_date2(pdata+12);
3365 size = IVAL(pdata,16);
3366 dosmode = IVAL(pdata,24);
3367 break;
3369 case SMB_SET_FILE_BASIC_INFO:
3370 case SMB_FILE_BASIC_INFORMATION:
3372 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3373 time_t write_time;
3374 time_t changed_time;
3376 if (total_data < 36)
3377 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3379 /* Ignore create time at offset pdata. */
3381 /* access time */
3382 tvs.actime = interpret_long_date(pdata+8);
3384 write_time = interpret_long_date(pdata+16);
3385 changed_time = interpret_long_date(pdata+24);
3387 tvs.modtime = MIN(write_time, changed_time);
3389 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3390 tvs.modtime = write_time;
3392 /* Prefer a defined time to an undefined one. */
3393 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3394 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3395 ? changed_time : write_time);
3397 /* attributes */
3398 dosmode = IVAL(pdata,32);
3399 break;
3402 case SMB_FILE_ALLOCATION_INFORMATION:
3403 case SMB_SET_FILE_ALLOCATION_INFO:
3405 int ret = -1;
3406 SMB_BIG_UINT allocation_size;
3408 if (total_data < 8)
3409 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3411 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3412 #ifdef LARGE_SMB_OFF_T
3413 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3414 #else /* LARGE_SMB_OFF_T */
3415 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3416 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3417 #endif /* LARGE_SMB_OFF_T */
3418 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3419 fname, (double)allocation_size ));
3421 if (allocation_size)
3422 allocation_size = smb_roundup(allocation_size);
3424 if(allocation_size != get_file_size(sbuf)) {
3425 SMB_STRUCT_STAT new_sbuf;
3427 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3428 fname, (double)allocation_size ));
3430 if (fd == -1) {
3431 files_struct *new_fsp = NULL;
3432 int access_mode = 0;
3433 int action = 0;
3435 if(global_oplock_break) {
3436 /* Queue this file modify as we are the process of an oplock break. */
3438 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3439 DEBUGADD(2,( "in oplock break state.\n"));
3441 push_oplock_pending_smb_message(inbuf, length);
3442 return -1;
3445 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3446 SET_OPEN_MODE(DOS_OPEN_RDWR),
3447 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3448 FILE_ATTRIBUTE_NORMAL,
3449 INTERNAL_OPEN_ONLY, &access_mode, &action);
3451 if (new_fsp == NULL)
3452 return(UNIXERROR(ERRDOS,ERRbadpath));
3453 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3454 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3455 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3456 new_fsp->fnum, strerror(errno)));
3457 ret = -1;
3459 close_file(new_fsp,True);
3460 } else {
3461 ret = vfs_allocate_file_space(fsp, allocation_size);
3462 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3463 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3464 fsp->fnum, strerror(errno)));
3465 ret = -1;
3468 if (ret == -1)
3469 return ERROR_NT(NT_STATUS_DISK_FULL);
3471 /* Allocate can truncate size... */
3472 size = get_file_size(new_sbuf);
3475 break;
3478 case SMB_FILE_END_OF_FILE_INFORMATION:
3479 case SMB_SET_FILE_END_OF_FILE_INFO:
3481 if (total_data < 8)
3482 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3484 size = IVAL(pdata,0);
3485 #ifdef LARGE_SMB_OFF_T
3486 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3487 #else /* LARGE_SMB_OFF_T */
3488 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3489 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3490 #endif /* LARGE_SMB_OFF_T */
3491 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3492 break;
3495 case SMB_FILE_DISPOSITION_INFORMATION:
3496 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3498 BOOL delete_on_close;
3500 if (total_data < 1)
3501 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3503 delete_on_close = (CVAL(pdata,0) ? True : False);
3505 /* Just ignore this set on a path. */
3506 if (tran_call != TRANSACT2_SETFILEINFO)
3507 break;
3509 if (fsp == NULL)
3510 return(UNIXERROR(ERRDOS,ERRbadfid));
3512 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3514 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3515 return ERROR_NT(status);
3517 /* The set is across all open files on this dev/inode pair. */
3518 status =set_delete_on_close_over_all(fsp, delete_on_close);
3519 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3520 return ERROR_NT(status);
3522 break;
3525 case SMB_FILE_POSITION_INFORMATION:
3527 SMB_BIG_UINT position_information;
3529 if (total_data < 8)
3530 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3532 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3533 #ifdef LARGE_SMB_OFF_T
3534 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3535 #else /* LARGE_SMB_OFF_T */
3536 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3537 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3538 #endif /* LARGE_SMB_OFF_T */
3539 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3540 fname, (double)position_information ));
3541 if (fsp)
3542 fsp->position_information = position_information;
3543 break;
3547 * CIFS UNIX extensions.
3550 case SMB_SET_FILE_UNIX_BASIC:
3552 uint32 raw_unixmode;
3554 if (total_data < 100)
3555 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3557 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3558 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3559 size=IVAL(pdata,0); /* first 8 Bytes are size */
3560 #ifdef LARGE_SMB_OFF_T
3561 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3562 #else /* LARGE_SMB_OFF_T */
3563 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3564 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3565 #endif /* LARGE_SMB_OFF_T */
3567 pdata+=24; /* ctime & st_blocks are not changed */
3568 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3569 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3570 pdata+=16;
3571 set_owner = (uid_t)IVAL(pdata,0);
3572 pdata += 8;
3573 set_grp = (gid_t)IVAL(pdata,0);
3574 pdata += 8;
3575 raw_unixmode = IVAL(pdata,28);
3576 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3577 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3579 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3580 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3581 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3583 if (!VALID_STAT(sbuf)) {
3586 * The only valid use of this is to create character and block
3587 * devices, and named pipes. This is deprecated (IMHO) and
3588 * a new info level should be used for mknod. JRA.
3591 uint32 file_type = IVAL(pdata,0);
3592 #if defined(HAVE_MAKEDEV)
3593 uint32 dev_major = IVAL(pdata,4);
3594 uint32 dev_minor = IVAL(pdata,12);
3595 #endif
3597 uid_t myuid = geteuid();
3598 gid_t mygid = getegid();
3599 SMB_DEV_T dev = (SMB_DEV_T)0;
3601 if (tran_call == TRANSACT2_SETFILEINFO)
3602 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3604 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3605 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3607 #if defined(HAVE_MAKEDEV)
3608 dev = makedev(dev_major, dev_minor);
3609 #endif
3611 /* We can only create as the owner/group we are. */
3613 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3614 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3615 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3616 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3618 switch (file_type) {
3619 #if defined(S_IFIFO)
3620 case UNIX_TYPE_FIFO:
3621 unixmode |= S_IFIFO;
3622 break;
3623 #endif
3624 #if defined(S_IFSOCK)
3625 case UNIX_TYPE_SOCKET:
3626 unixmode |= S_IFSOCK;
3627 break;
3628 #endif
3629 #if defined(S_IFCHR)
3630 case UNIX_TYPE_CHARDEV:
3631 unixmode |= S_IFCHR;
3632 break;
3633 #endif
3634 #if defined(S_IFBLK)
3635 case UNIX_TYPE_BLKDEV:
3636 unixmode |= S_IFBLK;
3637 break;
3638 #endif
3639 default:
3640 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3643 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3644 0%o for file %s\n", (double)dev, unixmode, fname ));
3646 /* Ok - do the mknod. */
3647 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3648 return(UNIXERROR(ERRDOS,ERRnoaccess));
3650 inherit_access_acl(conn, fname, unixmode);
3652 SSVAL(params,0,0);
3653 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3654 return(-1);
3658 * Deal with the UNIX specific mode set.
3661 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3662 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3663 (unsigned int)unixmode, fname ));
3664 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3665 return(UNIXERROR(ERRDOS,ERRnoaccess));
3669 * Deal with the UNIX specific uid set.
3672 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3673 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3674 (unsigned int)set_owner, fname ));
3675 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3676 return(UNIXERROR(ERRDOS,ERRnoaccess));
3680 * Deal with the UNIX specific gid set.
3683 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3684 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3685 (unsigned int)set_owner, fname ));
3686 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3687 return(UNIXERROR(ERRDOS,ERRnoaccess));
3689 break;
3692 case SMB_SET_FILE_UNIX_LINK:
3694 pstring link_target;
3695 char *newname = fname;
3697 /* Set a symbolic link. */
3698 /* Don't allow this if follow links is false. */
3700 if (!lp_symlinks(SNUM(conn)))
3701 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3703 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3705 /* !widelinks forces the target path to be within the share. */
3706 /* This means we can interpret the target as a pathname. */
3707 if (!lp_widelinks(SNUM(conn))) {
3708 pstring rel_name;
3709 char *last_dirp = NULL;
3711 unix_format(link_target);
3712 if (*link_target == '/') {
3713 /* No absolute paths allowed. */
3714 return(UNIXERROR(ERRDOS,ERRnoaccess));
3716 pstrcpy(rel_name, newname);
3717 last_dirp = strrchr_m(rel_name, '/');
3718 if (last_dirp) {
3719 last_dirp[1] = '\0';
3720 } else {
3721 pstrcpy(rel_name, "./");
3723 pstrcat(rel_name, link_target);
3725 if (!check_name(rel_name, conn)) {
3726 return(UNIXERROR(ERRDOS,ERRnoaccess));
3730 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3731 fname, link_target ));
3733 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3734 return(UNIXERROR(ERRDOS,ERRnoaccess));
3735 SSVAL(params,0,0);
3736 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3737 return(-1);
3740 case SMB_SET_FILE_UNIX_HLINK:
3742 pstring oldname;
3743 char *newname = fname;
3745 /* Set a hard link. */
3746 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3747 if (!NT_STATUS_IS_OK(status)) {
3748 return ERROR_NT(status);
3751 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3752 fname, oldname));
3754 status = hardlink_internals(conn, oldname, newname);
3755 if (!NT_STATUS_IS_OK(status)) {
3756 return ERROR_NT(status);
3759 SSVAL(params,0,0);
3760 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3761 return(-1);
3764 case SMB_FILE_RENAME_INFORMATION:
3766 BOOL overwrite;
3767 uint32 root_fid;
3768 uint32 len;
3769 pstring newname;
3770 pstring base_name;
3771 char *p;
3773 if (total_data < 12)
3774 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3776 overwrite = (CVAL(pdata,0) ? True : False);
3777 root_fid = IVAL(pdata,4);
3778 len = IVAL(pdata,8);
3779 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3780 if (!NT_STATUS_IS_OK(status)) {
3781 return ERROR_NT(status);
3784 /* Check the new name has no '/' characters. */
3785 if (strchr_m(newname, '/'))
3786 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3788 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3790 /* Create the base directory. */
3791 pstrcpy(base_name, fname);
3792 p = strrchr_m(base_name, '/');
3793 if (p)
3794 *p = '\0';
3795 /* Append the new name. */
3796 pstrcat(base_name, "/");
3797 pstrcat(base_name, newname);
3799 if (fsp) {
3800 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3801 fsp->fnum, fsp->fsp_name, base_name ));
3802 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3803 } else {
3804 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3805 fname, newname ));
3806 status = rename_internals(conn, fname, base_name, 0, overwrite);
3808 if (!NT_STATUS_IS_OK(status)) {
3809 return ERROR_NT(status);
3811 process_pending_change_notify_queue((time_t)0);
3812 SSVAL(params,0,0);
3813 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3814 return(-1);
3817 case SMB_SET_POSIX_ACL:
3819 uint16 posix_acl_version;
3820 uint16 num_file_acls;
3821 uint16 num_def_acls;
3822 BOOL valid_file_acls = True;
3823 BOOL valid_def_acls = True;
3825 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3826 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3828 posix_acl_version = SVAL(pdata,0);
3829 num_file_acls = SVAL(pdata,2);
3830 num_def_acls = SVAL(pdata,4);
3832 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3833 valid_file_acls = False;
3834 num_file_acls = 0;
3837 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3838 valid_def_acls = False;
3839 num_def_acls = 0;
3842 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3843 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3846 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3847 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3848 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3851 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3852 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3853 return(UNIXERROR(ERRDOS,ERRnoaccess));
3856 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3857 pdata + SMB_POSIX_ACL_HEADER_SIZE +
3858 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3859 return(UNIXERROR(ERRDOS,ERRnoaccess));
3862 SSVAL(params,0,0);
3863 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3864 return(-1);
3867 default:
3868 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3871 /* get some defaults (no modifications) if any info is zero or -1. */
3872 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3873 tvs.actime = sbuf.st_atime;
3875 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3876 tvs.modtime = sbuf.st_mtime;
3878 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3879 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3880 DEBUG(6,("size: %.0f ", (double)size));
3882 if (dosmode) {
3883 if (S_ISDIR(sbuf.st_mode))
3884 dosmode |= aDIR;
3885 else
3886 dosmode &= ~aDIR;
3889 DEBUG(6,("dosmode: %x\n" , dosmode));
3891 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3892 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3893 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3894 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3897 * Only do this test if we are not explicitly
3898 * changing the size of a file.
3900 if (!size)
3901 size = get_file_size(sbuf);
3905 * Try and set the times, size and mode of this file -
3906 * if they are different from the current values
3908 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3909 if(fsp != NULL) {
3911 * This was a setfileinfo on an open file.
3912 * NT does this a lot. We also need to
3913 * set the time here, as it can be read by
3914 * FindFirst/FindNext and with the patch for bug #2045
3915 * in smbd/fileio.c it ensures that this timestamp is
3916 * kept sticky even after a write. We save the request
3917 * away and will set it on file close and after a write. JRA.
3920 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3921 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3922 fsp->pending_modtime = tvs.modtime;
3925 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3927 if(file_utime(conn, fname, &tvs)!=0) {
3928 return(UNIXERROR(ERRDOS,ERRnoaccess));
3933 /* check the mode isn't different, before changing it */
3934 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3936 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3938 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
3939 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3940 return(UNIXERROR(ERRDOS,ERRnoaccess));
3944 if (size != get_file_size(sbuf)) {
3946 int ret;
3948 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3949 fname, (double)size ));
3951 if (fd == -1) {
3952 files_struct *new_fsp = NULL;
3953 int access_mode = 0;
3954 int action = 0;
3956 if(global_oplock_break) {
3957 /* Queue this file modify as we are the process of an oplock break. */
3959 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3960 DEBUGADD(2,( "in oplock break state.\n"));
3962 push_oplock_pending_smb_message(inbuf, length);
3963 return -1;
3966 new_fsp = open_file_shared(conn, fname, &sbuf,
3967 SET_OPEN_MODE(DOS_OPEN_RDWR),
3968 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3969 FILE_ATTRIBUTE_NORMAL,
3970 INTERNAL_OPEN_ONLY, &access_mode, &action);
3972 if (new_fsp == NULL)
3973 return(UNIXERROR(ERRDOS,ERRbadpath));
3974 ret = vfs_set_filelen(new_fsp, size);
3975 close_file(new_fsp,True);
3976 } else {
3977 ret = vfs_set_filelen(fsp, size);
3980 if (ret == -1)
3981 return (UNIXERROR(ERRHRD,ERRdiskfull));
3984 SSVAL(params,0,0);
3985 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3987 return(-1);
3990 /****************************************************************************
3991 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3992 ****************************************************************************/
3994 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3995 char **pparams, int total_params, char **ppdata, int total_data,
3996 unsigned int max_data_bytes)
3998 char *params = *pparams;
3999 pstring directory;
4000 int ret = -1;
4001 SMB_STRUCT_STAT sbuf;
4002 BOOL bad_path = False;
4003 NTSTATUS status = NT_STATUS_OK;
4005 if (!CAN_WRITE(conn))
4006 return ERROR_DOS(ERRSRV,ERRaccess);
4008 if (total_params < 4)
4009 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4011 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4012 if (!NT_STATUS_IS_OK(status)) {
4013 return ERROR_NT(status);
4016 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4018 unix_convert(directory,conn,0,&bad_path,&sbuf);
4019 if (bad_path) {
4020 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4022 if (check_name(directory,conn))
4023 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4025 if(ret < 0) {
4026 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4027 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4030 /* Realloc the parameter and data sizes */
4031 params = SMB_REALLOC(*pparams,2);
4032 if(params == NULL)
4033 return ERROR_DOS(ERRDOS,ERRnomem);
4034 *pparams = params;
4036 SSVAL(params,0,0);
4038 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4040 return(-1);
4043 /****************************************************************************
4044 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4045 We don't actually do this - we just send a null response.
4046 ****************************************************************************/
4048 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4049 char **pparams, int total_params, char **ppdata, int total_data,
4050 unsigned int max_data_bytes)
4052 static uint16 fnf_handle = 257;
4053 char *params = *pparams;
4054 uint16 info_level;
4056 if (total_params < 6)
4057 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4059 info_level = SVAL(params,4);
4060 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4062 switch (info_level) {
4063 case 1:
4064 case 2:
4065 break;
4066 default:
4067 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4070 /* Realloc the parameter and data sizes */
4071 params = SMB_REALLOC(*pparams,6);
4072 if(params == NULL)
4073 return ERROR_DOS(ERRDOS,ERRnomem);
4074 *pparams = params;
4076 SSVAL(params,0,fnf_handle);
4077 SSVAL(params,2,0); /* No changes */
4078 SSVAL(params,4,0); /* No EA errors */
4080 fnf_handle++;
4082 if(fnf_handle == 0)
4083 fnf_handle = 257;
4085 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4087 return(-1);
4090 /****************************************************************************
4091 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4092 changes). Currently this does nothing.
4093 ****************************************************************************/
4095 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4096 char **pparams, int total_params, char **ppdata, int total_data,
4097 unsigned int max_data_bytes)
4099 char *params = *pparams;
4101 DEBUG(3,("call_trans2findnotifynext\n"));
4103 /* Realloc the parameter and data sizes */
4104 params = SMB_REALLOC(*pparams,4);
4105 if(params == NULL)
4106 return ERROR_DOS(ERRDOS,ERRnomem);
4107 *pparams = params;
4109 SSVAL(params,0,0); /* No changes */
4110 SSVAL(params,2,0); /* No EA errors */
4112 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4114 return(-1);
4117 /****************************************************************************
4118 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4119 ****************************************************************************/
4121 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4122 char **pparams, int total_params, char **ppdata, int total_data,
4123 unsigned int max_data_bytes)
4125 char *params = *pparams;
4126 pstring pathname;
4127 int reply_size = 0;
4128 int max_referral_level;
4130 DEBUG(10,("call_trans2getdfsreferral\n"));
4132 if (total_params < 2)
4133 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4135 max_referral_level = SVAL(params,0);
4137 if(!lp_host_msdfs())
4138 return ERROR_DOS(ERRDOS,ERRbadfunc);
4140 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4141 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4142 return UNIXERROR(ERRDOS,ERRbadfile);
4144 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4145 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4147 return(-1);
4150 #define LMCAT_SPL 0x53
4151 #define LMFUNC_GETJOBID 0x60
4153 /****************************************************************************
4154 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4155 ****************************************************************************/
4157 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4158 char **pparams, int total_params, char **ppdata, int total_data,
4159 unsigned int max_data_bytes)
4161 char *pdata = *ppdata;
4162 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4164 /* check for an invalid fid before proceeding */
4166 if (!fsp)
4167 return(ERROR_DOS(ERRDOS,ERRbadfid));
4169 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4170 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4171 pdata = SMB_REALLOC(*ppdata, 32);
4172 if(pdata == NULL)
4173 return ERROR_DOS(ERRDOS,ERRnomem);
4174 *ppdata = pdata;
4176 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4177 CAN ACCEPT THIS IN UNICODE. JRA. */
4179 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4180 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4181 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4182 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4183 return(-1);
4184 } else {
4185 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4186 return ERROR_DOS(ERRSRV,ERRerror);
4190 /****************************************************************************
4191 Reply to a SMBfindclose (stop trans2 directory search).
4192 ****************************************************************************/
4194 int reply_findclose(connection_struct *conn,
4195 char *inbuf,char *outbuf,int length,int bufsize)
4197 int outsize = 0;
4198 int dptr_num=SVALS(inbuf,smb_vwv0);
4199 START_PROFILE(SMBfindclose);
4201 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4203 dptr_close(&dptr_num);
4205 outsize = set_message(outbuf,0,0,True);
4207 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4209 END_PROFILE(SMBfindclose);
4210 return(outsize);
4213 /****************************************************************************
4214 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4215 ****************************************************************************/
4217 int reply_findnclose(connection_struct *conn,
4218 char *inbuf,char *outbuf,int length,int bufsize)
4220 int outsize = 0;
4221 int dptr_num= -1;
4222 START_PROFILE(SMBfindnclose);
4224 dptr_num = SVAL(inbuf,smb_vwv0);
4226 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4228 /* We never give out valid handles for a
4229 findnotifyfirst - so any dptr_num is ok here.
4230 Just ignore it. */
4232 outsize = set_message(outbuf,0,0,True);
4234 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4236 END_PROFILE(SMBfindnclose);
4237 return(outsize);
4240 /****************************************************************************
4241 Reply to a SMBtranss2 - just ignore it!
4242 ****************************************************************************/
4244 int reply_transs2(connection_struct *conn,
4245 char *inbuf,char *outbuf,int length,int bufsize)
4247 START_PROFILE(SMBtranss2);
4248 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4249 END_PROFILE(SMBtranss2);
4250 return(-1);
4253 /****************************************************************************
4254 Reply to a SMBtrans2.
4255 ****************************************************************************/
4257 int reply_trans2(connection_struct *conn,
4258 char *inbuf,char *outbuf,int length,int bufsize)
4260 int outsize = 0;
4261 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4262 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4263 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4264 #if 0
4265 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4266 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4267 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4268 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4269 int32 timeout = IVALS(inbuf,smb_timeout);
4270 #endif
4271 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4272 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4273 char *params = NULL, *data = NULL;
4274 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4275 START_PROFILE(SMBtrans2);
4277 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4278 /* Queue this open message as we are the process of an
4279 * oplock break. */
4281 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4282 DEBUGADD(2,( "in oplock break state.\n"));
4284 push_oplock_pending_smb_message(inbuf, length);
4285 END_PROFILE(SMBtrans2);
4286 return -1;
4289 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4290 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4291 END_PROFILE(SMBtrans2);
4292 return ERROR_DOS(ERRSRV,ERRaccess);
4295 outsize = set_message(outbuf,0,0,True);
4297 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4298 is so as a sanity check */
4299 if (suwcnt != 1) {
4301 * Need to have rc=0 for ioctl to get job id for OS/2.
4302 * Network printing will fail if function is not successful.
4303 * Similar function in reply.c will be used if protocol
4304 * is LANMAN1.0 instead of LM1.2X002.
4305 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4306 * outbuf doesn't have to be set(only job id is used).
4308 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4309 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4310 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4311 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4312 } else {
4313 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4314 DEBUG(2,("Transaction is %d\n",tran_call));
4315 END_PROFILE(SMBtrans2);
4316 ERROR_DOS(ERRDOS,ERRinvalidparam);
4320 /* Allocate the space for the maximum needed parameters and data */
4321 if (total_params > 0)
4322 params = (char *)SMB_MALLOC(total_params);
4323 if (total_data > 0)
4324 data = (char *)SMB_MALLOC(total_data);
4326 if ((total_params && !params) || (total_data && !data)) {
4327 DEBUG(2,("Out of memory in reply_trans2\n"));
4328 SAFE_FREE(params);
4329 SAFE_FREE(data);
4330 END_PROFILE(SMBtrans2);
4331 return ERROR_DOS(ERRDOS,ERRnomem);
4334 /* Copy the param and data bytes sent with this request into
4335 the params buffer */
4336 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4337 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4339 if (num_params > total_params || num_data > total_data)
4340 exit_server("invalid params in reply_trans2");
4342 if(params) {
4343 unsigned int psoff = SVAL(inbuf, smb_psoff);
4344 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4345 goto bad_param;
4346 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4347 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4348 goto bad_param;
4349 memcpy( params, smb_base(inbuf) + psoff, num_params);
4351 if(data) {
4352 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4353 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4354 goto bad_param;
4355 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4356 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4357 goto bad_param;
4358 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4361 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4363 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4364 /* We need to send an interim response then receive the rest
4365 of the parameter/data bytes */
4366 outsize = set_message(outbuf,0,0,True);
4367 srv_signing_trans_stop();
4368 if (!send_smb(smbd_server_fd(),outbuf))
4369 exit_server("reply_trans2: send_smb failed.");
4371 while (num_data_sofar < total_data ||
4372 num_params_sofar < total_params) {
4373 BOOL ret;
4374 unsigned int param_disp;
4375 unsigned int param_off;
4376 unsigned int data_disp;
4377 unsigned int data_off;
4379 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4382 * The sequence number for the trans reply is always
4383 * based on the last secondary received.
4386 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4388 if ((ret &&
4389 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4390 outsize = set_message(outbuf,0,0,True);
4391 if(ret)
4392 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4393 else
4394 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4395 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4396 goto bad_param;
4399 /* Revise total_params and total_data in case
4400 they have changed downwards */
4401 if (SVAL(inbuf, smb_tpscnt) < total_params)
4402 total_params = SVAL(inbuf, smb_tpscnt);
4403 if (SVAL(inbuf, smb_tdscnt) < total_data)
4404 total_data = SVAL(inbuf, smb_tdscnt);
4406 num_params = SVAL(inbuf,smb_spscnt);
4407 param_off = SVAL(inbuf, smb_spsoff);
4408 param_disp = SVAL(inbuf, smb_spsdisp);
4409 num_params_sofar += num_params;
4411 num_data = SVAL(inbuf, smb_sdscnt);
4412 data_off = SVAL(inbuf, smb_sdsoff);
4413 data_disp = SVAL(inbuf, smb_sdsdisp);
4414 num_data_sofar += num_data;
4416 if (num_params_sofar > total_params || num_data_sofar > total_data)
4417 goto bad_param;
4419 if (num_params) {
4420 if (param_disp + num_params > total_params)
4421 goto bad_param;
4422 if ((param_disp + num_params < param_disp) ||
4423 (param_disp + num_params < num_params))
4424 goto bad_param;
4425 if (param_disp > total_params)
4426 goto bad_param;
4427 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4428 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4429 goto bad_param;
4430 if (params + param_disp < params)
4431 goto bad_param;
4433 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4435 if (num_data) {
4436 if (data_disp + num_data > total_data)
4437 goto bad_param;
4438 if ((data_disp + num_data < data_disp) ||
4439 (data_disp + num_data < num_data))
4440 goto bad_param;
4441 if (data_disp > total_data)
4442 goto bad_param;
4443 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4444 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4445 goto bad_param;
4446 if (data + data_disp < data)
4447 goto bad_param;
4449 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4454 if (Protocol >= PROTOCOL_NT1) {
4455 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4458 /* Now we must call the relevant TRANS2 function */
4459 switch(tran_call) {
4460 case TRANSACT2_OPEN:
4461 START_PROFILE_NESTED(Trans2_open);
4462 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4463 &params, total_params, &data, total_data, max_data_bytes);
4464 END_PROFILE_NESTED(Trans2_open);
4465 break;
4467 case TRANSACT2_FINDFIRST:
4468 START_PROFILE_NESTED(Trans2_findfirst);
4469 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4470 &params, total_params, &data, total_data, max_data_bytes);
4471 END_PROFILE_NESTED(Trans2_findfirst);
4472 break;
4474 case TRANSACT2_FINDNEXT:
4475 START_PROFILE_NESTED(Trans2_findnext);
4476 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4477 &params, total_params, &data, total_data, max_data_bytes);
4478 END_PROFILE_NESTED(Trans2_findnext);
4479 break;
4481 case TRANSACT2_QFSINFO:
4482 START_PROFILE_NESTED(Trans2_qfsinfo);
4483 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4484 &params, total_params, &data, total_data, max_data_bytes);
4485 END_PROFILE_NESTED(Trans2_qfsinfo);
4486 break;
4488 #ifdef HAVE_SYS_QUOTAS
4489 case TRANSACT2_SETFSINFO:
4490 START_PROFILE_NESTED(Trans2_setfsinfo);
4491 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4492 &params, total_params, &data, total_data, max_data_bytes);
4493 END_PROFILE_NESTED(Trans2_setfsinfo);
4494 break;
4495 #endif
4496 case TRANSACT2_QPATHINFO:
4497 case TRANSACT2_QFILEINFO:
4498 START_PROFILE_NESTED(Trans2_qpathinfo);
4499 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4500 &params, total_params, &data, total_data, max_data_bytes);
4501 END_PROFILE_NESTED(Trans2_qpathinfo);
4502 break;
4503 case TRANSACT2_SETPATHINFO:
4504 case TRANSACT2_SETFILEINFO:
4505 START_PROFILE_NESTED(Trans2_setpathinfo);
4506 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4507 &params, total_params, &data, total_data, max_data_bytes);
4508 END_PROFILE_NESTED(Trans2_setpathinfo);
4509 break;
4511 case TRANSACT2_FINDNOTIFYFIRST:
4512 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4513 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4514 &params, total_params, &data, total_data, max_data_bytes);
4515 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4516 break;
4518 case TRANSACT2_FINDNOTIFYNEXT:
4519 START_PROFILE_NESTED(Trans2_findnotifynext);
4520 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4521 &params, total_params, &data, total_data, max_data_bytes);
4522 END_PROFILE_NESTED(Trans2_findnotifynext);
4523 break;
4524 case TRANSACT2_MKDIR:
4525 START_PROFILE_NESTED(Trans2_mkdir);
4526 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4527 &params, total_params, &data, total_data, max_data_bytes);
4528 END_PROFILE_NESTED(Trans2_mkdir);
4529 break;
4531 case TRANSACT2_GET_DFS_REFERRAL:
4532 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4533 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4534 &params, total_params, &data, total_data, max_data_bytes);
4535 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4536 break;
4537 case TRANSACT2_IOCTL:
4538 START_PROFILE_NESTED(Trans2_ioctl);
4539 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4540 &params, total_params, &data, total_data, max_data_bytes);
4541 END_PROFILE_NESTED(Trans2_ioctl);
4542 break;
4543 default:
4544 /* Error in request */
4545 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4546 SAFE_FREE(params);
4547 SAFE_FREE(data);
4548 END_PROFILE(SMBtrans2);
4549 srv_signing_trans_stop();
4550 return ERROR_DOS(ERRSRV,ERRerror);
4553 /* As we do not know how many data packets will need to be
4554 returned here the various call_trans2xxxx calls
4555 must send their own. Thus a call_trans2xxx routine only
4556 returns a value other than -1 when it wants to send
4557 an error packet.
4560 srv_signing_trans_stop();
4562 SAFE_FREE(params);
4563 SAFE_FREE(data);
4564 END_PROFILE(SMBtrans2);
4565 return outsize; /* If a correct response was needed the
4566 call_trans2xxx calls have already sent
4567 it. If outsize != -1 then it is returning */
4569 bad_param:
4571 srv_signing_trans_stop();
4572 SAFE_FREE(params);
4573 SAFE_FREE(data);
4574 END_PROFILE(SMBtrans2);
4575 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);