r3220: merging current 3.0 code to release branch
[Samba.git] / source / smbd / trans2.c
blob9b1f2aa21051369208959f2a0ef88b498725e47b
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 int 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(mem_ctx, val, 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(mem_ctx, ea_namelist, 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(mem_ctx, sizeof(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)
589 char *params = *pparams;
590 int16 open_mode;
591 int16 open_attr;
592 BOOL oplock_request;
593 #if 0
594 BOOL return_additional_info;
595 int16 open_sattr;
596 time_t open_time;
597 #endif
598 int16 open_ofun;
599 int32 open_size;
600 char *pname;
601 pstring fname;
602 SMB_OFF_T size=0;
603 int fmode=0,mtime=0,rmode;
604 SMB_INO_T inode = 0;
605 SMB_STRUCT_STAT sbuf;
606 int smb_action = 0;
607 BOOL bad_path = False;
608 files_struct *fsp;
609 NTSTATUS status;
612 * Ensure we have enough parameters to perform the operation.
615 if (total_params < 29)
616 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
618 open_mode = SVAL(params, 2);
619 open_attr = SVAL(params,6);
620 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
621 #if 0
622 return_additional_info = BITSETW(params,0);
623 open_sattr = SVAL(params, 4);
624 open_time = make_unix_date3(params+8);
625 #endif
626 open_ofun = SVAL(params,12);
627 open_size = IVAL(params,14);
628 pname = &params[28];
630 if (IS_IPC(conn))
631 return(ERROR_DOS(ERRSRV,ERRaccess));
633 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
634 if (!NT_STATUS_IS_OK(status)) {
635 return ERROR_NT(status);
638 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
639 fname,open_mode, open_attr, open_ofun, open_size));
641 /* XXXX we need to handle passed times, sattr and flags */
643 unix_convert(fname,conn,0,&bad_path,&sbuf);
644 if (bad_path) {
645 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
648 if (!check_name(fname,conn)) {
649 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
652 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
653 oplock_request, &rmode,&smb_action);
655 if (!fsp) {
656 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
657 /* We have re-scheduled this call. */
658 clear_cached_errors();
659 return -1;
661 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
664 size = get_file_size(sbuf);
665 fmode = dos_mode(conn,fname,&sbuf);
666 mtime = sbuf.st_mtime;
667 inode = sbuf.st_ino;
668 if (fmode & aDIR) {
669 close_file(fsp,False);
670 return(ERROR_DOS(ERRDOS,ERRnoaccess));
673 /* Realloc the size of parameters and data we will return */
674 params = Realloc(*pparams, 28);
675 if( params == NULL )
676 return(ERROR_DOS(ERRDOS,ERRnomem));
677 *pparams = params;
679 memset((char *)params,'\0',28);
680 SSVAL(params,0,fsp->fnum);
681 SSVAL(params,2,fmode);
682 put_dos_date2(params,4, mtime);
683 SIVAL(params,8, (uint32)size);
684 SSVAL(params,12,rmode);
686 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
687 smb_action |= EXTENDED_OPLOCK_GRANTED;
689 SSVAL(params,18,smb_action);
692 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
694 SIVAL(params,20,inode);
696 /* Send the required number of replies */
697 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
699 return -1;
702 /*********************************************************
703 Routine to check if a given string matches exactly.
704 as a special case a mask of "." does NOT match. That
705 is required for correct wildcard semantics
706 Case can be significant or not.
707 **********************************************************/
709 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
711 if (mask[0] == '.' && mask[1] == 0)
712 return False;
713 if (case_sig)
714 return strcmp(str,mask)==0;
715 if (StrCaseCmp(str,mask) != 0) {
716 return False;
718 if (ms_has_wild(str)) {
719 return False;
721 return True;
724 /****************************************************************************
725 Return the filetype for UNIX extensions.
726 ****************************************************************************/
728 static uint32 unix_filetype(mode_t mode)
730 if(S_ISREG(mode))
731 return UNIX_TYPE_FILE;
732 else if(S_ISDIR(mode))
733 return UNIX_TYPE_DIR;
734 #ifdef S_ISLNK
735 else if(S_ISLNK(mode))
736 return UNIX_TYPE_SYMLINK;
737 #endif
738 #ifdef S_ISCHR
739 else if(S_ISCHR(mode))
740 return UNIX_TYPE_CHARDEV;
741 #endif
742 #ifdef S_ISBLK
743 else if(S_ISBLK(mode))
744 return UNIX_TYPE_BLKDEV;
745 #endif
746 #ifdef S_ISFIFO
747 else if(S_ISFIFO(mode))
748 return UNIX_TYPE_FIFO;
749 #endif
750 #ifdef S_ISSOCK
751 else if(S_ISSOCK(mode))
752 return UNIX_TYPE_SOCKET;
753 #endif
755 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
756 return UNIX_TYPE_UNKNOWN;
759 /****************************************************************************
760 Map wire perms onto standard UNIX permissions. Obey share restrictions.
761 ****************************************************************************/
763 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
765 mode_t ret = 0;
767 if (perms == SMB_MODE_NO_CHANGE)
768 return pst->st_mode;
770 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
771 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
772 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
773 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
774 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
775 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
776 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
777 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
778 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
779 #ifdef S_ISVTX
780 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
781 #endif
782 #ifdef S_ISGID
783 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
784 #endif
785 #ifdef S_ISUID
786 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
787 #endif
789 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
790 ret &= lp_dir_mask(SNUM(conn));
791 /* Add in force bits */
792 ret |= lp_force_dir_mode(SNUM(conn));
793 } else {
794 /* Apply mode mask */
795 ret &= lp_create_mask(SNUM(conn));
796 /* Add in force bits */
797 ret |= lp_force_create_mode(SNUM(conn));
800 return ret;
803 /****************************************************************************
804 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
805 ****************************************************************************/
807 time_t interpret_long_unix_date(char *p)
809 DEBUG(10,("interpret_long_unix_date\n"));
810 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
811 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
812 return -1;
813 } else {
814 return interpret_long_date(p);
818 /****************************************************************************
819 Get a level dependent lanman2 dir entry.
820 ****************************************************************************/
822 static BOOL get_lanman2_dir_entry(connection_struct *conn,
823 void *inbuf, void *outbuf,
824 char *path_mask,int dirtype,int info_level,
825 int requires_resume_key,
826 BOOL dont_descend,char **ppdata,
827 char *base_data, int space_remaining,
828 BOOL *out_of_space, BOOL *got_exact_match,
829 int *last_name_off)
831 const char *dname;
832 BOOL found = False;
833 SMB_STRUCT_STAT sbuf;
834 pstring mask;
835 pstring pathreal;
836 pstring fname;
837 char *p, *q, *pdata = *ppdata;
838 uint32 reskey=0;
839 int prev_dirpos=0;
840 int mode=0;
841 SMB_OFF_T file_size = 0;
842 SMB_BIG_UINT allocation_size = 0;
843 uint32 len;
844 time_t mdate=0, adate=0, cdate=0;
845 char *nameptr;
846 BOOL was_8_3;
847 int nt_extmode; /* Used for NT connections instead of mode */
848 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
850 *fname = 0;
851 *out_of_space = False;
852 *got_exact_match = False;
854 if (!conn->dirptr)
855 return(False);
857 p = strrchr_m(path_mask,'/');
858 if(p != NULL) {
859 if(p[1] == '\0')
860 pstrcpy(mask,"*.*");
861 else
862 pstrcpy(mask, p+1);
863 } else
864 pstrcpy(mask, path_mask);
866 while (!found) {
867 BOOL got_match;
869 /* Needed if we run out of space */
870 prev_dirpos = TellDir(conn->dirptr);
871 dname = ReadDirName(conn->dirptr);
874 * Due to bugs in NT client redirectors we are not using
875 * resume keys any more - set them to zero.
876 * Check out the related comments in findfirst/findnext.
877 * JRA.
880 reskey = 0;
882 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
883 (long)conn->dirptr,TellDir(conn->dirptr)));
885 if (!dname)
886 return(False);
888 pstrcpy(fname,dname);
890 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
891 got_match = mask_match(fname, mask, conn->case_sensitive);
893 if(!got_match && !mangle_is_8_3(fname, False)) {
896 * It turns out that NT matches wildcards against
897 * both long *and* short names. This may explain some
898 * of the wildcard wierdness from old DOS clients
899 * that some people have been seeing.... JRA.
902 pstring newname;
903 pstrcpy( newname, fname);
904 mangle_map( newname, True, False, SNUM(conn));
905 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
906 got_match = mask_match(newname, mask, conn->case_sensitive);
909 if(got_match) {
910 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
911 if (dont_descend && !isdots)
912 continue;
914 pstrcpy(pathreal,conn->dirpath);
915 if(needslash)
916 pstrcat(pathreal,"/");
917 pstrcat(pathreal,dname);
919 if (INFO_LEVEL_IS_UNIX(info_level)) {
920 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
921 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
922 pathreal,strerror(errno)));
923 continue;
925 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
927 /* Needed to show the msdfs symlinks as
928 * directories */
930 if(lp_host_msdfs() &&
931 lp_msdfs_root(SNUM(conn)) &&
932 is_msdfs_link(conn, pathreal, NULL, NULL,
933 &sbuf)) {
935 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
936 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
938 } else {
940 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
941 pathreal,strerror(errno)));
942 continue;
946 mode = dos_mode(conn,pathreal,&sbuf);
948 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
949 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
950 continue;
953 file_size = get_file_size(sbuf);
954 allocation_size = get_allocation_size(NULL,&sbuf);
955 mdate = sbuf.st_mtime;
956 adate = sbuf.st_atime;
957 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
959 if (lp_dos_filetime_resolution(SNUM(conn))) {
960 cdate &= ~1;
961 mdate &= ~1;
962 adate &= ~1;
965 if(mode & aDIR)
966 file_size = 0;
968 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
970 found = True;
974 mangle_map(fname,False,True,SNUM(conn));
976 p = pdata;
977 nameptr = p;
979 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
981 switch (info_level) {
982 case SMB_INFO_STANDARD:
983 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
984 if(requires_resume_key) {
985 SIVAL(p,0,reskey);
986 p += 4;
988 put_dos_date2(p,l1_fdateCreation,cdate);
989 put_dos_date2(p,l1_fdateLastAccess,adate);
990 put_dos_date2(p,l1_fdateLastWrite,mdate);
991 SIVAL(p,l1_cbFile,(uint32)file_size);
992 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
993 SSVAL(p,l1_attrFile,mode);
994 p += l1_achName;
995 nameptr = p;
996 p += align_string(outbuf, p, 0);
997 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
998 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
999 if (len > 2) {
1000 SCVAL(nameptr, -1, len - 2);
1001 } else {
1002 SCVAL(nameptr, -1, 0);
1004 } else {
1005 if (len > 1) {
1006 SCVAL(nameptr, -1, len - 1);
1007 } else {
1008 SCVAL(nameptr, -1, 0);
1011 p += len;
1012 break;
1014 case SMB_INFO_QUERY_EA_SIZE:
1015 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1016 if(requires_resume_key) {
1017 SIVAL(p,0,reskey);
1018 p += 4;
1020 put_dos_date2(p,l2_fdateCreation,cdate);
1021 put_dos_date2(p,l2_fdateLastAccess,adate);
1022 put_dos_date2(p,l2_fdateLastWrite,mdate);
1023 SIVAL(p,l2_cbFile,(uint32)file_size);
1024 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1025 SSVAL(p,l2_attrFile,mode);
1027 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1028 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1030 p += l2_achName;
1031 nameptr = p - 1;
1032 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1033 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1034 if (len > 2) {
1035 len -= 2;
1036 } else {
1037 len = 0;
1039 } else {
1040 if (len > 1) {
1041 len -= 1;
1042 } else {
1043 len = 0;
1046 SCVAL(nameptr,0,len);
1047 p += len;
1048 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1049 break;
1051 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1052 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1053 was_8_3 = mangle_is_8_3(fname, True);
1054 p += 4;
1055 SIVAL(p,0,reskey); p += 4;
1056 put_long_date(p,cdate); p += 8;
1057 put_long_date(p,adate); p += 8;
1058 put_long_date(p,mdate); p += 8;
1059 put_long_date(p,mdate); p += 8;
1060 SOFF_T(p,0,file_size); p += 8;
1061 SOFF_T(p,0,allocation_size); p += 8;
1062 SIVAL(p,0,nt_extmode); p += 4;
1063 q = p; p += 4; /* q is placeholder for name length. */
1065 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1066 SIVAL(p,0,ea_size); /* Extended attributes */
1067 p += 4;
1069 /* Clear the short name buffer. This is
1070 * IMPORTANT as not doing so will trigger
1071 * a Win2k client bug. JRA.
1073 memset(p,'\0',26);
1074 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1075 pstring mangled_name;
1076 pstrcpy(mangled_name, fname);
1077 mangle_map(mangled_name,True,True,SNUM(conn));
1078 mangled_name[12] = 0;
1079 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1080 SSVAL(p, 0, len);
1081 } else {
1082 SSVAL(p,0,0);
1083 *(p+2) = 0;
1085 p += 2 + 24;
1086 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1087 SIVAL(q,0,len);
1088 p += len;
1089 len = PTR_DIFF(p, pdata);
1090 len = (len + 3) & ~3;
1091 SIVAL(pdata,0,len);
1092 p = pdata + len;
1093 break;
1095 case SMB_FIND_FILE_DIRECTORY_INFO:
1096 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1097 p += 4;
1098 SIVAL(p,0,reskey); p += 4;
1099 put_long_date(p,cdate); p += 8;
1100 put_long_date(p,adate); p += 8;
1101 put_long_date(p,mdate); p += 8;
1102 put_long_date(p,mdate); p += 8;
1103 SOFF_T(p,0,file_size); p += 8;
1104 SOFF_T(p,0,allocation_size); p += 8;
1105 SIVAL(p,0,nt_extmode); p += 4;
1106 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1107 SIVAL(p,0,len);
1108 p += 4 + len;
1109 len = PTR_DIFF(p, pdata);
1110 len = (len + 3) & ~3;
1111 SIVAL(pdata,0,len);
1112 p = pdata + len;
1113 break;
1115 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1116 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1117 p += 4;
1118 SIVAL(p,0,reskey); p += 4;
1119 put_long_date(p,cdate); p += 8;
1120 put_long_date(p,adate); p += 8;
1121 put_long_date(p,mdate); p += 8;
1122 put_long_date(p,mdate); p += 8;
1123 SOFF_T(p,0,file_size); p += 8;
1124 SOFF_T(p,0,allocation_size); p += 8;
1125 SIVAL(p,0,nt_extmode); p += 4;
1126 q = p; p += 4; /* q is placeholder for name length. */
1128 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1129 SIVAL(p,0,ea_size); /* Extended attributes */
1130 p +=4;
1132 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1133 SIVAL(q, 0, len);
1134 p += len;
1136 len = PTR_DIFF(p, pdata);
1137 len = (len + 3) & ~3;
1138 SIVAL(pdata,0,len);
1139 p = pdata + len;
1140 break;
1142 case SMB_FIND_FILE_NAMES_INFO:
1143 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1144 p += 4;
1145 SIVAL(p,0,reskey); p += 4;
1146 p += 4;
1147 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1148 acl on a dir (tridge) */
1149 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1150 SIVAL(p, -4, len);
1151 p += len;
1152 len = PTR_DIFF(p, pdata);
1153 len = (len + 3) & ~3;
1154 SIVAL(pdata,0,len);
1155 p = pdata + len;
1156 break;
1158 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1159 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1160 p += 4;
1161 SIVAL(p,0,reskey); p += 4;
1162 put_long_date(p,cdate); p += 8;
1163 put_long_date(p,adate); p += 8;
1164 put_long_date(p,mdate); p += 8;
1165 put_long_date(p,mdate); p += 8;
1166 SOFF_T(p,0,file_size); p += 8;
1167 SOFF_T(p,0,allocation_size); p += 8;
1168 SIVAL(p,0,nt_extmode); p += 4;
1169 q = p; p += 4; /* q is placeholder for name length. */
1171 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1172 SIVAL(p,0,ea_size); /* Extended attributes */
1173 p +=4;
1175 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1176 SIVAL(p,0,sbuf.st_dev); p += 4;
1177 SIVAL(p,0,sbuf.st_ino); p += 4;
1178 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1179 SIVAL(q, 0, len);
1180 p += len;
1181 len = PTR_DIFF(p, pdata);
1182 len = (len + 3) & ~3;
1183 SIVAL(pdata,0,len);
1184 p = pdata + len;
1185 break;
1187 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1188 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1189 was_8_3 = mangle_is_8_3(fname, True);
1190 p += 4;
1191 SIVAL(p,0,reskey); p += 4;
1192 put_long_date(p,cdate); p += 8;
1193 put_long_date(p,adate); p += 8;
1194 put_long_date(p,mdate); p += 8;
1195 put_long_date(p,mdate); p += 8;
1196 SOFF_T(p,0,file_size); p += 8;
1197 SOFF_T(p,0,allocation_size); p += 8;
1198 SIVAL(p,0,nt_extmode); p += 4;
1199 q = p; p += 4; /* q is placeholder for name length */
1201 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1202 SIVAL(p,0,ea_size); /* Extended attributes */
1203 p +=4;
1205 /* Clear the short name buffer. This is
1206 * IMPORTANT as not doing so will trigger
1207 * a Win2k client bug. JRA.
1209 memset(p,'\0',26);
1210 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1211 pstring mangled_name;
1212 pstrcpy(mangled_name, fname);
1213 mangle_map(mangled_name,True,True,SNUM(conn));
1214 mangled_name[12] = 0;
1215 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1216 SSVAL(p, 0, len);
1217 } else {
1218 SSVAL(p,0,0);
1219 *(p+2) = 0;
1221 p += 26;
1222 SSVAL(p,0,0); p += 2; /* Reserved ? */
1223 SIVAL(p,0,sbuf.st_dev); p += 4;
1224 SIVAL(p,0,sbuf.st_ino); p += 4;
1225 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1226 SIVAL(q,0,len);
1227 p += len;
1228 len = PTR_DIFF(p, pdata);
1229 len = (len + 3) & ~3;
1230 SIVAL(pdata,0,len);
1231 p = pdata + len;
1232 break;
1234 /* CIFS UNIX Extension. */
1236 case SMB_FIND_FILE_UNIX:
1237 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1238 p+= 4;
1239 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1241 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1242 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1243 p+= 8;
1245 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1246 p+= 8;
1248 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1249 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1250 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1251 p+= 24;
1253 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1254 SIVAL(p,4,0);
1255 p+= 8;
1257 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1258 SIVAL(p,4,0);
1259 p+= 8;
1261 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1262 p+= 4;
1264 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1265 SIVAL(p,4,0);
1266 p+= 8;
1268 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1269 SIVAL(p,4,0);
1270 p+= 8;
1272 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1273 p+= 8;
1275 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1276 SIVAL(p,4,0);
1277 p+= 8;
1279 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1280 SIVAL(p,4,0);
1281 p+= 8;
1283 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1284 p += len;
1286 len = PTR_DIFF(p, pdata);
1287 len = (len + 3) & ~3;
1288 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1289 p = pdata + len;
1290 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1292 break;
1294 default:
1295 return(False);
1299 if (PTR_DIFF(p,pdata) > space_remaining) {
1300 /* Move the dirptr back to prev_dirpos */
1301 SeekDir(conn->dirptr, prev_dirpos);
1302 *out_of_space = True;
1303 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1304 return False; /* Not finished - just out of space */
1307 /* Setup the last_filename pointer, as an offset from base_data */
1308 *last_name_off = PTR_DIFF(nameptr,base_data);
1309 /* Advance the data pointer to the next slot */
1310 *ppdata = p;
1312 return(found);
1315 /****************************************************************************
1316 Reply to a TRANS2_FINDFIRST.
1317 ****************************************************************************/
1319 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1320 char **pparams, int total_params, char **ppdata, int total_data)
1322 /* We must be careful here that we don't return more than the
1323 allowed number of data bytes. If this means returning fewer than
1324 maxentries then so be it. We assume that the redirector has
1325 enough room for the fixed number of parameter bytes it has
1326 requested. */
1327 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1328 char *params = *pparams;
1329 char *pdata = *ppdata;
1330 int dirtype = SVAL(params,0);
1331 int maxentries = SVAL(params,2);
1332 BOOL close_after_first = BITSETW(params+4,0);
1333 BOOL close_if_end = BITSETW(params+4,1);
1334 BOOL requires_resume_key = BITSETW(params+4,2);
1335 int info_level = SVAL(params,6);
1336 pstring directory;
1337 pstring mask;
1338 char *p, *wcard;
1339 int last_name_off=0;
1340 int dptr_num = -1;
1341 int numentries = 0;
1342 int i;
1343 BOOL finished = False;
1344 BOOL dont_descend = False;
1345 BOOL out_of_space = False;
1346 int space_remaining;
1347 BOOL bad_path = False;
1348 SMB_STRUCT_STAT sbuf;
1349 NTSTATUS ntstatus = NT_STATUS_OK;
1351 if (total_params < 12)
1352 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1354 *directory = *mask = 0;
1356 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1357 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1358 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1359 info_level, max_data_bytes));
1361 if (!maxentries) {
1362 /* W2K3 seems to treat zero as 1. */
1363 maxentries = 1;
1366 switch (info_level) {
1367 case SMB_INFO_STANDARD:
1368 case SMB_INFO_QUERY_EA_SIZE:
1369 case SMB_FIND_FILE_DIRECTORY_INFO:
1370 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1371 case SMB_FIND_FILE_NAMES_INFO:
1372 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1373 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1374 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1375 break;
1376 case SMB_FIND_FILE_UNIX:
1377 if (!lp_unix_extensions())
1378 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1379 break;
1380 default:
1381 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1384 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1385 if (!NT_STATUS_IS_OK(ntstatus)) {
1386 return ERROR_NT(ntstatus);
1389 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1391 unix_convert(directory,conn,0,&bad_path,&sbuf);
1392 if (bad_path) {
1393 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1395 if(!check_name(directory,conn)) {
1396 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1399 p = strrchr_m(directory,'/');
1400 if(p == NULL) {
1401 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1402 if((directory[0] == '.') && (directory[1] == '\0'))
1403 pstrcpy(mask,"*");
1404 else
1405 pstrcpy(mask,directory);
1406 pstrcpy(directory,"./");
1407 } else {
1408 pstrcpy(mask,p+1);
1409 *p = 0;
1412 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1414 pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1415 if( pdata == NULL )
1416 return(ERROR_DOS(ERRDOS,ERRnomem));
1418 *ppdata = pdata;
1419 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1421 /* Realloc the params space */
1422 params = Realloc(*pparams, 10);
1423 if (params == NULL)
1424 return ERROR_DOS(ERRDOS,ERRnomem);
1425 *pparams = params;
1427 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1428 if (dptr_num < 0)
1429 return(UNIXERROR(ERRDOS,ERRbadfile));
1431 /* Save the wildcard match and attribs we are using on this directory -
1432 needed as lanman2 assumes these are being saved between calls */
1434 if(!(wcard = strdup(mask))) {
1435 dptr_close(&dptr_num);
1436 return ERROR_DOS(ERRDOS,ERRnomem);
1439 dptr_set_wcard(dptr_num, wcard);
1440 dptr_set_attr(dptr_num, dirtype);
1442 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1444 /* We don't need to check for VOL here as this is returned by
1445 a different TRANS2 call. */
1447 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1448 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1449 dont_descend = True;
1451 p = pdata;
1452 space_remaining = max_data_bytes;
1453 out_of_space = False;
1455 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1456 BOOL got_exact_match = False;
1458 /* this is a heuristic to avoid seeking the dirptr except when
1459 absolutely necessary. It allows for a filename of about 40 chars */
1460 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1461 out_of_space = True;
1462 finished = False;
1463 } else {
1464 finished = !get_lanman2_dir_entry(conn,
1465 inbuf, outbuf,
1466 mask,dirtype,info_level,
1467 requires_resume_key,dont_descend,
1468 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1469 &last_name_off);
1472 if (finished && out_of_space)
1473 finished = False;
1475 if (!finished && !out_of_space)
1476 numentries++;
1479 * As an optimisation if we know we aren't looking
1480 * for a wildcard name (ie. the name matches the wildcard exactly)
1481 * then we can finish on any (first) match.
1482 * This speeds up large directory searches. JRA.
1485 if(got_exact_match)
1486 finished = True;
1488 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1491 /* Check if we can close the dirptr */
1492 if(close_after_first || (finished && close_if_end)) {
1493 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1494 dptr_close(&dptr_num);
1498 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1499 * from observation of NT.
1502 if(numentries == 0) {
1503 dptr_close(&dptr_num);
1504 return ERROR_DOS(ERRDOS,ERRbadfile);
1507 /* At this point pdata points to numentries directory entries. */
1509 /* Set up the return parameter block */
1510 SSVAL(params,0,dptr_num);
1511 SSVAL(params,2,numentries);
1512 SSVAL(params,4,finished);
1513 SSVAL(params,6,0); /* Never an EA error */
1514 SSVAL(params,8,last_name_off);
1516 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1518 if ((! *directory) && dptr_path(dptr_num))
1519 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1521 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1522 smb_fn_name(CVAL(inbuf,smb_com)),
1523 mask, directory, dirtype, numentries ) );
1526 * Force a name mangle here to ensure that the
1527 * mask as an 8.3 name is top of the mangled cache.
1528 * The reasons for this are subtle. Don't remove
1529 * this code unless you know what you are doing
1530 * (see PR#13758). JRA.
1533 if(!mangle_is_8_3_wildcards( mask, False))
1534 mangle_map(mask, True, True, SNUM(conn));
1536 return(-1);
1539 /****************************************************************************
1540 Reply to a TRANS2_FINDNEXT.
1541 ****************************************************************************/
1543 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1544 char **pparams, int total_params, char **ppdata, int total_data)
1546 /* We must be careful here that we don't return more than the
1547 allowed number of data bytes. If this means returning fewer than
1548 maxentries then so be it. We assume that the redirector has
1549 enough room for the fixed number of parameter bytes it has
1550 requested. */
1551 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1552 char *params = *pparams;
1553 char *pdata = *ppdata;
1554 int dptr_num = SVAL(params,0);
1555 int maxentries = SVAL(params,2);
1556 uint16 info_level = SVAL(params,4);
1557 uint32 resume_key = IVAL(params,6);
1558 BOOL close_after_request = BITSETW(params+10,0);
1559 BOOL close_if_end = BITSETW(params+10,1);
1560 BOOL requires_resume_key = BITSETW(params+10,2);
1561 BOOL continue_bit = BITSETW(params+10,3);
1562 pstring resume_name;
1563 pstring mask;
1564 pstring directory;
1565 char *p;
1566 uint16 dirtype;
1567 int numentries = 0;
1568 int i, last_name_off=0;
1569 BOOL finished = False;
1570 BOOL dont_descend = False;
1571 BOOL out_of_space = False;
1572 int space_remaining;
1573 NTSTATUS ntstatus = NT_STATUS_OK;
1575 if (total_params < 12)
1576 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1578 *mask = *directory = *resume_name = 0;
1580 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1581 if (!NT_STATUS_IS_OK(ntstatus)) {
1582 return ERROR_NT(ntstatus);
1585 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1586 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1587 resume_key = %d resume name = %s continue=%d level = %d\n",
1588 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1589 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1591 if (!maxentries) {
1592 /* W2K3 seems to treat zero as 1. */
1593 maxentries = 1;
1596 switch (info_level) {
1597 case SMB_INFO_STANDARD:
1598 case SMB_INFO_QUERY_EA_SIZE:
1599 case SMB_FIND_FILE_DIRECTORY_INFO:
1600 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1601 case SMB_FIND_FILE_NAMES_INFO:
1602 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1603 break;
1604 case SMB_FIND_FILE_UNIX:
1605 if (!lp_unix_extensions())
1606 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1607 break;
1608 default:
1609 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1612 pdata = Realloc( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1613 if(pdata == NULL)
1614 return ERROR_DOS(ERRDOS,ERRnomem);
1616 *ppdata = pdata;
1617 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1619 /* Realloc the params space */
1620 params = Realloc(*pparams, 6*SIZEOFWORD);
1621 if( params == NULL )
1622 return ERROR_DOS(ERRDOS,ERRnomem);
1624 *pparams = params;
1626 /* Check that the dptr is valid */
1627 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1628 return ERROR_DOS(ERRDOS,ERRnofiles);
1630 string_set(&conn->dirpath,dptr_path(dptr_num));
1632 /* Get the wildcard mask from the dptr */
1633 if((p = dptr_wcard(dptr_num))== NULL) {
1634 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1635 return ERROR_DOS(ERRDOS,ERRnofiles);
1638 pstrcpy(mask, p);
1639 pstrcpy(directory,conn->dirpath);
1641 /* Get the attr mask from the dptr */
1642 dirtype = dptr_attr(dptr_num);
1644 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1645 dptr_num, mask, dirtype,
1646 (long)conn->dirptr,
1647 TellDir(conn->dirptr)));
1649 /* We don't need to check for VOL here as this is returned by
1650 a different TRANS2 call. */
1652 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1653 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1654 dont_descend = True;
1656 p = pdata;
1657 space_remaining = max_data_bytes;
1658 out_of_space = False;
1661 * Seek to the correct position. We no longer use the resume key but
1662 * depend on the last file name instead.
1665 if(requires_resume_key && *resume_name && !continue_bit) {
1668 * Fix for NT redirector problem triggered by resume key indexes
1669 * changing between directory scans. We now return a resume key of 0
1670 * and instead look for the filename to continue from (also given
1671 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1672 * findfirst/findnext (as is usual) then the directory pointer
1673 * should already be at the correct place. Check this by scanning
1674 * backwards looking for an exact (ie. case sensitive) filename match.
1675 * If we get to the beginning of the directory and haven't found it then scan
1676 * forwards again looking for a match. JRA.
1679 int current_pos, start_pos;
1680 const char *dname = NULL;
1681 pstring dname_pstring;
1682 void *dirptr = conn->dirptr;
1683 start_pos = TellDir(dirptr);
1684 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1685 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1687 SeekDir(dirptr, current_pos);
1688 dname = ReadDirName(dirptr);
1689 if (dname) {
1691 * Remember, mangle_map is called by
1692 * get_lanman2_dir_entry(), so the resume name
1693 * could be mangled. Ensure we do the same
1694 * here.
1697 /* make sure we get a copy that mangle_map can modify */
1699 pstrcpy(dname_pstring, dname);
1700 mangle_map( dname_pstring, False, True, SNUM(conn));
1702 if(strcsequal( resume_name, dname_pstring)) {
1703 SeekDir(dirptr, current_pos+1);
1704 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1705 break;
1711 * Scan forward from start if not found going backwards.
1714 if(current_pos < 0) {
1715 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1716 SeekDir(dirptr, start_pos);
1717 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1720 * Remember, mangle_map is called by
1721 * get_lanman2_dir_entry(), so the resume name
1722 * could be mangled. Ensure we do the same
1723 * here.
1726 if(dname) {
1727 /* make sure we get a copy that mangle_map can modify */
1729 pstrcpy(dname_pstring, dname);
1730 mangle_map(dname_pstring, False, True, SNUM(conn));
1732 if(strcsequal( resume_name, dname_pstring)) {
1733 SeekDir(dirptr, current_pos+1);
1734 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1735 break;
1738 } /* end for */
1739 } /* end if current_pos */
1740 } /* end if requires_resume_key && !continue_bit */
1742 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1743 BOOL got_exact_match = False;
1745 /* this is a heuristic to avoid seeking the dirptr except when
1746 absolutely necessary. It allows for a filename of about 40 chars */
1747 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1748 out_of_space = True;
1749 finished = False;
1750 } else {
1751 finished = !get_lanman2_dir_entry(conn,
1752 inbuf, outbuf,
1753 mask,dirtype,info_level,
1754 requires_resume_key,dont_descend,
1755 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1756 &last_name_off);
1759 if (finished && out_of_space)
1760 finished = False;
1762 if (!finished && !out_of_space)
1763 numentries++;
1766 * As an optimisation if we know we aren't looking
1767 * for a wildcard name (ie. the name matches the wildcard exactly)
1768 * then we can finish on any (first) match.
1769 * This speeds up large directory searches. JRA.
1772 if(got_exact_match)
1773 finished = True;
1775 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1778 /* Check if we can close the dirptr */
1779 if(close_after_request || (finished && close_if_end)) {
1780 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1781 dptr_close(&dptr_num); /* This frees up the saved mask */
1784 /* Set up the return parameter block */
1785 SSVAL(params,0,numentries);
1786 SSVAL(params,2,finished);
1787 SSVAL(params,4,0); /* Never an EA error */
1788 SSVAL(params,6,last_name_off);
1790 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1792 if ((! *directory) && dptr_path(dptr_num))
1793 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1795 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1796 smb_fn_name(CVAL(inbuf,smb_com)),
1797 mask, directory, dirtype, numentries ) );
1799 return(-1);
1802 /****************************************************************************
1803 Reply to a TRANS2_QFSINFO (query filesystem info).
1804 ****************************************************************************/
1806 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1807 int length, int bufsize,
1808 char **pparams, int total_params, char **ppdata, int total_data)
1810 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1811 char *pdata = *ppdata;
1812 char *params = *pparams;
1813 uint16 info_level = SVAL(params,0);
1814 int data_len, len;
1815 SMB_STRUCT_STAT st;
1816 char *vname = volume_label(SNUM(conn));
1817 int snum = SNUM(conn);
1818 char *fstype = lp_fstype(SNUM(conn));
1819 int quota_flag = 0;
1821 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1823 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1824 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1825 return ERROR_DOS(ERRSRV,ERRinvdevice);
1828 pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1829 if ( pdata == NULL )
1830 return ERROR_DOS(ERRDOS,ERRnomem);
1832 *ppdata = pdata;
1833 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1835 switch (info_level) {
1836 case SMB_INFO_ALLOCATION:
1838 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1839 data_len = 18;
1840 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1841 block_size = lp_block_size(snum);
1842 if (bsize < block_size) {
1843 SMB_BIG_UINT factor = block_size/bsize;
1844 bsize = block_size;
1845 dsize /= factor;
1846 dfree /= factor;
1848 if (bsize > block_size) {
1849 SMB_BIG_UINT factor = bsize/block_size;
1850 bsize = block_size;
1851 dsize *= factor;
1852 dfree *= factor;
1854 bytes_per_sector = 512;
1855 sectors_per_unit = bsize/bytes_per_sector;
1857 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1858 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1859 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1861 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1862 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1863 SIVAL(pdata,l1_cUnit,dsize);
1864 SIVAL(pdata,l1_cUnitAvail,dfree);
1865 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1866 break;
1869 case SMB_INFO_VOLUME:
1870 /* Return volume name */
1872 * Add volume serial number - hash of a combination of
1873 * the called hostname and the service name.
1875 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1876 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1877 SCVAL(pdata,l2_vol_cch,len);
1878 data_len = l2_vol_szVolLabel + len;
1879 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1880 (unsigned)st.st_ctime, len, vname));
1881 break;
1883 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1884 case SMB_FS_ATTRIBUTE_INFORMATION:
1887 #if defined(HAVE_SYS_QUOTAS)
1888 quota_flag = FILE_VOLUME_QUOTAS;
1889 #endif
1891 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1892 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1893 quota_flag); /* FS ATTRIBUTES */
1895 SIVAL(pdata,4,255); /* Max filename component length */
1896 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1897 and will think we can't do long filenames */
1898 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1899 SIVAL(pdata,8,len);
1900 data_len = 12 + len;
1901 break;
1903 case SMB_QUERY_FS_LABEL_INFO:
1904 case SMB_FS_LABEL_INFORMATION:
1905 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1906 data_len = 4 + len;
1907 SIVAL(pdata,0,len);
1908 break;
1910 case SMB_QUERY_FS_VOLUME_INFO:
1911 case SMB_FS_VOLUME_INFORMATION:
1914 * Add volume serial number - hash of a combination of
1915 * the called hostname and the service name.
1917 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1918 (str_checksum(local_machine)<<16));
1920 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1921 SIVAL(pdata,12,len);
1922 data_len = 18+len;
1923 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1924 (int)strlen(vname),vname, lp_servicename(snum)));
1925 break;
1927 case SMB_QUERY_FS_SIZE_INFO:
1928 case SMB_FS_SIZE_INFORMATION:
1930 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1931 data_len = 24;
1932 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1933 block_size = lp_block_size(snum);
1934 if (bsize < block_size) {
1935 SMB_BIG_UINT factor = block_size/bsize;
1936 bsize = block_size;
1937 dsize /= factor;
1938 dfree /= factor;
1940 if (bsize > block_size) {
1941 SMB_BIG_UINT factor = bsize/block_size;
1942 bsize = block_size;
1943 dsize *= factor;
1944 dfree *= factor;
1946 bytes_per_sector = 512;
1947 sectors_per_unit = bsize/bytes_per_sector;
1948 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1949 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1950 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1951 SBIG_UINT(pdata,0,dsize);
1952 SBIG_UINT(pdata,8,dfree);
1953 SIVAL(pdata,16,sectors_per_unit);
1954 SIVAL(pdata,20,bytes_per_sector);
1955 break;
1958 case SMB_FS_FULL_SIZE_INFORMATION:
1960 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1961 data_len = 32;
1962 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1963 block_size = lp_block_size(snum);
1964 if (bsize < block_size) {
1965 SMB_BIG_UINT factor = block_size/bsize;
1966 bsize = block_size;
1967 dsize /= factor;
1968 dfree /= factor;
1970 if (bsize > block_size) {
1971 SMB_BIG_UINT factor = bsize/block_size;
1972 bsize = block_size;
1973 dsize *= factor;
1974 dfree *= factor;
1976 bytes_per_sector = 512;
1977 sectors_per_unit = bsize/bytes_per_sector;
1978 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1979 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1980 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1981 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1982 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1983 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1984 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1985 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1986 break;
1989 case SMB_QUERY_FS_DEVICE_INFO:
1990 case SMB_FS_DEVICE_INFORMATION:
1991 data_len = 8;
1992 SIVAL(pdata,0,0); /* dev type */
1993 SIVAL(pdata,4,0); /* characteristics */
1994 break;
1996 #ifdef HAVE_SYS_QUOTAS
1997 case SMB_FS_QUOTA_INFORMATION:
1999 * what we have to send --metze:
2001 * Unknown1: 24 NULL bytes
2002 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2003 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2004 * Quota Flags: 2 byte :
2005 * Unknown3: 6 NULL bytes
2007 * 48 bytes total
2009 * details for Quota Flags:
2011 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2012 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2013 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2014 * 0x0001 Enable Quotas: enable quota for this fs
2018 /* we need to fake up a fsp here,
2019 * because its not send in this call
2021 files_struct fsp;
2022 SMB_NTQUOTA_STRUCT quotas;
2024 ZERO_STRUCT(fsp);
2025 ZERO_STRUCT(quotas);
2027 fsp.conn = conn;
2028 fsp.fnum = -1;
2029 fsp.fd = -1;
2031 /* access check */
2032 if (current_user.uid != 0) {
2033 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2034 lp_servicename(SNUM(conn)),conn->user));
2035 return ERROR_DOS(ERRDOS,ERRnoaccess);
2038 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2039 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2040 return ERROR_DOS(ERRSRV,ERRerror);
2043 data_len = 48;
2045 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2047 /* Unknown1 24 NULL bytes*/
2048 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2049 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2050 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2052 /* Default Soft Quota 8 bytes */
2053 SBIG_UINT(pdata,24,quotas.softlim);
2055 /* Default Hard Quota 8 bytes */
2056 SBIG_UINT(pdata,32,quotas.hardlim);
2058 /* Quota flag 2 bytes */
2059 SSVAL(pdata,40,quotas.qflags);
2061 /* Unknown3 6 NULL bytes */
2062 SSVAL(pdata,42,0);
2063 SIVAL(pdata,44,0);
2065 break;
2067 #endif /* HAVE_SYS_QUOTAS */
2068 case SMB_FS_OBJECTID_INFORMATION:
2069 data_len = 64;
2070 break;
2073 * Query the version and capabilities of the CIFS UNIX extensions
2074 * in use.
2077 case SMB_QUERY_CIFS_UNIX_INFO:
2078 if (!lp_unix_extensions())
2079 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2080 data_len = 12;
2081 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2082 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2083 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2084 break;
2086 case SMB_MAC_QUERY_FS_INFO:
2088 * Thursby MAC extension... ONLY on NTFS filesystems
2089 * once we do streams then we don't need this
2091 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2092 data_len = 88;
2093 SIVAL(pdata,84,0x100); /* Don't support mac... */
2094 break;
2096 /* drop through */
2097 default:
2098 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2102 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2104 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2106 return -1;
2109 #ifdef HAVE_SYS_QUOTAS
2110 /****************************************************************************
2111 Reply to a TRANS2_SETFSINFO (set filesystem info).
2112 ****************************************************************************/
2114 static int call_trans2setfsinfo(connection_struct *conn,
2115 char *inbuf, char *outbuf, int length, int bufsize,
2116 char **pparams, int total_params, char **ppdata, int total_data)
2118 char *pdata = *ppdata;
2119 char *params = *pparams;
2120 files_struct *fsp = NULL;
2121 uint16 info_level;
2122 int outsize;
2123 SMB_NTQUOTA_STRUCT quotas;
2125 ZERO_STRUCT(quotas);
2127 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2129 /* access check */
2130 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2131 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2132 lp_servicename(SNUM(conn)),conn->user));
2133 return ERROR_DOS(ERRSRV,ERRaccess);
2136 /* */
2137 if (total_params < 4) {
2138 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2139 total_params));
2140 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2143 fsp = file_fsp(params,0);
2145 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2146 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2147 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2150 info_level = SVAL(params,2);
2152 switch(info_level) {
2153 case SMB_FS_QUOTA_INFORMATION:
2154 /* note: normaly there're 48 bytes,
2155 * but we didn't use the last 6 bytes for now
2156 * --metze
2158 if (total_data < 42) {
2159 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2160 total_data));
2161 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2164 /* unknown_1 24 NULL bytes in pdata*/
2166 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2167 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2168 #ifdef LARGE_SMB_OFF_T
2169 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2170 #else /* LARGE_SMB_OFF_T */
2171 if ((IVAL(pdata,28) != 0)&&
2172 ((quotas.softlim != 0xFFFFFFFF)||
2173 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2174 /* more than 32 bits? */
2175 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2177 #endif /* LARGE_SMB_OFF_T */
2179 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2180 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2181 #ifdef LARGE_SMB_OFF_T
2182 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2183 #else /* LARGE_SMB_OFF_T */
2184 if ((IVAL(pdata,36) != 0)&&
2185 ((quotas.hardlim != 0xFFFFFFFF)||
2186 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2187 /* more than 32 bits? */
2188 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2190 #endif /* LARGE_SMB_OFF_T */
2192 /* quota_flags 2 bytes **/
2193 quotas.qflags = SVAL(pdata,40);
2195 /* unknown_2 6 NULL bytes follow*/
2197 /* now set the quotas */
2198 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2199 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2200 return ERROR_DOS(ERRSRV,ERRerror);
2203 break;
2204 default:
2205 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2206 info_level));
2207 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2208 break;
2212 * sending this reply works fine,
2213 * but I'm not sure it's the same
2214 * like windows do...
2215 * --metze
2217 outsize = set_message(outbuf,10,0,True);
2219 return outsize;
2221 #endif /* HAVE_SYS_QUOTAS */
2223 /****************************************************************************
2224 * Utility function to set bad path error.
2225 ****************************************************************************/
2227 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2229 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2230 err, (int)bad_path ));
2232 if(err == ENOENT) {
2233 if (bad_path) {
2234 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2235 } else {
2236 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2239 return UNIXERROR(def_class,def_code);
2242 /****************************************************************************
2243 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2244 file name or file id).
2245 ****************************************************************************/
2247 static int call_trans2qfilepathinfo(connection_struct *conn,
2248 char *inbuf, char *outbuf, int length,
2249 int bufsize,
2250 char **pparams, int total_params, char **ppdata, int total_data)
2252 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2253 char *params = *pparams;
2254 char *pdata = *ppdata;
2255 uint16 tran_call = SVAL(inbuf, smb_setup0);
2256 uint16 info_level;
2257 int mode=0;
2258 SMB_OFF_T file_size=0;
2259 SMB_BIG_UINT allocation_size=0;
2260 unsigned int data_size;
2261 unsigned int param_size = 2;
2262 SMB_STRUCT_STAT sbuf;
2263 pstring fname, dos_fname;
2264 char *fullpathname;
2265 char *base_name;
2266 char *p;
2267 SMB_OFF_T pos = 0;
2268 BOOL bad_path = False;
2269 BOOL delete_pending = False;
2270 int len;
2271 time_t c_time;
2272 files_struct *fsp = NULL;
2273 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2275 if (!params)
2276 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2278 ZERO_STRUCT(sbuf);
2280 if (tran_call == TRANSACT2_QFILEINFO) {
2281 if (total_params < 4)
2282 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2284 fsp = file_fsp(params,0);
2285 info_level = SVAL(params,2);
2287 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2289 if(fsp && (fsp->fake_file_handle)) {
2291 * This is actually for the QUOTA_FAKE_FILE --metze
2294 pstrcpy(fname, fsp->fsp_name);
2295 /* We know this name is ok, it's already passed the checks. */
2297 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2299 * This is actually a QFILEINFO on a directory
2300 * handle (returned from an NT SMB). NT5.0 seems
2301 * to do this call. JRA.
2303 /* We know this name is ok, it's already passed the checks. */
2304 pstrcpy(fname, fsp->fsp_name);
2306 if (INFO_LEVEL_IS_UNIX(info_level)) {
2307 /* Always do lstat for UNIX calls. */
2308 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2309 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2310 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2312 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2313 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2314 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2317 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2318 } else {
2320 * Original code - this is an open file.
2322 CHECK_FSP(fsp,conn);
2324 pstrcpy(fname, fsp->fsp_name);
2325 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2326 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2327 return(UNIXERROR(ERRDOS,ERRbadfid));
2329 pos = fsp->position_information;
2330 delete_pending = fsp->delete_on_close;
2331 desired_access = fsp->desired_access;
2333 } else {
2334 NTSTATUS status = NT_STATUS_OK;
2336 /* qpathinfo */
2337 if (total_params < 6)
2338 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2340 info_level = SVAL(params,0);
2342 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2344 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2345 if (!NT_STATUS_IS_OK(status)) {
2346 return ERROR_NT(status);
2349 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2351 unix_convert(fname,conn,0,&bad_path,&sbuf);
2352 if (bad_path) {
2353 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2355 if (!check_name(fname,conn)) {
2356 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2357 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2360 if (INFO_LEVEL_IS_UNIX(info_level)) {
2361 /* Always do lstat for UNIX calls. */
2362 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2363 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2364 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2366 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2367 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2368 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2372 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2373 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2375 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2376 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2378 p = strrchr_m(fname,'/');
2379 if (!p)
2380 base_name = fname;
2381 else
2382 base_name = p+1;
2384 mode = dos_mode(conn,fname,&sbuf);
2385 if (!mode)
2386 mode = FILE_ATTRIBUTE_NORMAL;
2388 fullpathname = fname;
2389 file_size = get_file_size(sbuf);
2390 allocation_size = get_allocation_size(fsp,&sbuf);
2391 if (mode & aDIR)
2392 file_size = 0;
2394 params = Realloc(*pparams,2);
2395 if (params == NULL)
2396 return ERROR_DOS(ERRDOS,ERRnomem);
2397 *pparams = params;
2398 memset((char *)params,'\0',2);
2399 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2400 pdata = Realloc(*ppdata, data_size);
2401 if ( pdata == NULL )
2402 return ERROR_DOS(ERRDOS,ERRnomem);
2403 *ppdata = pdata;
2405 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2406 /* uggh, EAs for OS2 */
2407 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2408 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2411 memset((char *)pdata,'\0',data_size);
2413 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2415 if (lp_dos_filetime_resolution(SNUM(conn))) {
2416 c_time &= ~1;
2417 sbuf.st_atime &= ~1;
2418 sbuf.st_ctime &= ~1;
2419 sbuf.st_mtime &= ~1;
2422 /* NT expects the name to be in an exact form of the *full*
2423 filename. See the trans2 torture test */
2424 if (strequal(base_name,".")) {
2425 pstrcpy(dos_fname, "\\");
2426 } else {
2427 pstr_sprintf(dos_fname, "\\%s", fname);
2428 string_replace(dos_fname, '/', '\\');
2431 switch (info_level) {
2432 case SMB_INFO_STANDARD:
2433 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2434 data_size = 22;
2435 put_dos_date2(pdata,l1_fdateCreation,c_time);
2436 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2437 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2438 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2439 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2440 SSVAL(pdata,l1_attrFile,mode);
2441 break;
2443 case SMB_INFO_QUERY_EA_SIZE:
2445 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2446 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2447 data_size = 26;
2448 put_dos_date2(pdata,l1_fdateCreation,c_time);
2449 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2450 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2451 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2452 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2453 SSVAL(pdata,l1_attrFile,mode);
2454 SIVAL(pdata,l1_attrFile+2,ea_size);
2455 break;
2458 case SMB_INFO_IS_NAME_VALID:
2459 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2460 if (tran_call == TRANSACT2_QFILEINFO) {
2461 /* os/2 needs this ? really ?*/
2462 return ERROR_DOS(ERRDOS,ERRbadfunc);
2464 data_size = 0;
2465 param_size = 0;
2466 break;
2468 case SMB_INFO_QUERY_EAS_FROM_LIST:
2469 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2470 data_size = 24;
2471 put_dos_date2(pdata,0,c_time);
2472 put_dos_date2(pdata,4,sbuf.st_atime);
2473 put_dos_date2(pdata,8,sbuf.st_mtime);
2474 SIVAL(pdata,12,(uint32)file_size);
2475 SIVAL(pdata,16,(uint32)allocation_size);
2476 SIVAL(pdata,20,mode);
2477 break;
2479 case SMB_INFO_QUERY_ALL_EAS:
2480 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2481 /* We have data_size bytes to put EA's into. */
2482 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2483 break;
2485 case SMB_FILE_BASIC_INFORMATION:
2486 case SMB_QUERY_FILE_BASIC_INFO:
2488 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2489 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2490 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2491 } else {
2492 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2493 data_size = 40;
2494 SIVAL(pdata,36,0);
2496 put_long_date(pdata,c_time);
2497 put_long_date(pdata+8,sbuf.st_atime);
2498 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2499 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2500 SIVAL(pdata,32,mode);
2502 DEBUG(5,("SMB_QFBI - "));
2504 time_t create_time = c_time;
2505 DEBUG(5,("create: %s ", ctime(&create_time)));
2507 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2508 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2509 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2510 DEBUG(5,("mode: %x\n", mode));
2512 break;
2514 case SMB_FILE_STANDARD_INFORMATION:
2515 case SMB_QUERY_FILE_STANDARD_INFO:
2517 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2518 data_size = 24;
2519 SOFF_T(pdata,0,allocation_size);
2520 SOFF_T(pdata,8,file_size);
2521 if (delete_pending & sbuf.st_nlink)
2522 SIVAL(pdata,16,sbuf.st_nlink - 1);
2523 else
2524 SIVAL(pdata,16,sbuf.st_nlink);
2525 SCVAL(pdata,20,0);
2526 SCVAL(pdata,21,(mode&aDIR)?1:0);
2527 break;
2529 case SMB_FILE_EA_INFORMATION:
2530 case SMB_QUERY_FILE_EA_INFO:
2532 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2533 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2534 data_size = 4;
2535 SIVAL(pdata,0,ea_size);
2536 break;
2539 /* Get the 8.3 name - used if NT SMB was negotiated. */
2540 case SMB_QUERY_FILE_ALT_NAME_INFO:
2541 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2543 pstring short_name;
2545 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2546 pstrcpy(short_name,base_name);
2547 /* Mangle if not already 8.3 */
2548 if(!mangle_is_8_3(short_name, True)) {
2549 mangle_map(short_name,True,True,SNUM(conn));
2551 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2552 data_size = 4 + len;
2553 SIVAL(pdata,0,len);
2554 break;
2557 case SMB_QUERY_FILE_NAME_INFO:
2559 this must be *exactly* right for ACLs on mapped drives to work
2561 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2562 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2563 data_size = 4 + len;
2564 SIVAL(pdata,0,len);
2565 break;
2567 case SMB_FILE_ALLOCATION_INFORMATION:
2568 case SMB_QUERY_FILE_ALLOCATION_INFO:
2569 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2570 data_size = 8;
2571 SOFF_T(pdata,0,allocation_size);
2572 break;
2574 case SMB_FILE_END_OF_FILE_INFORMATION:
2575 case SMB_QUERY_FILE_END_OF_FILEINFO:
2576 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2577 data_size = 8;
2578 SOFF_T(pdata,0,file_size);
2579 break;
2581 case SMB_QUERY_FILE_ALL_INFO:
2582 case SMB_FILE_ALL_INFORMATION:
2584 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2585 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2586 put_long_date(pdata,c_time);
2587 put_long_date(pdata+8,sbuf.st_atime);
2588 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2589 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2590 SIVAL(pdata,32,mode);
2591 pdata += 40;
2592 SOFF_T(pdata,0,allocation_size);
2593 SOFF_T(pdata,8,file_size);
2594 if (delete_pending && sbuf.st_nlink)
2595 SIVAL(pdata,16,sbuf.st_nlink - 1);
2596 else
2597 SIVAL(pdata,16,sbuf.st_nlink);
2598 SCVAL(pdata,20,delete_pending);
2599 SCVAL(pdata,21,(mode&aDIR)?1:0);
2600 pdata += 24;
2601 SIVAL(pdata,0,ea_size);
2602 pdata += 4; /* EA info */
2603 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2604 SIVAL(pdata,0,len);
2605 pdata += 4 + len;
2606 data_size = PTR_DIFF(pdata,(*ppdata));
2607 break;
2609 case SMB_FILE_INTERNAL_INFORMATION:
2610 /* This should be an index number - looks like
2611 dev/ino to me :-)
2613 I think this causes us to fail the IFSKIT
2614 BasicFileInformationTest. -tpot */
2616 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2617 SIVAL(pdata,0,sbuf.st_dev);
2618 SIVAL(pdata,4,sbuf.st_ino);
2619 data_size = 8;
2620 break;
2622 case SMB_FILE_ACCESS_INFORMATION:
2623 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2624 SIVAL(pdata,0,desired_access);
2625 data_size = 4;
2626 break;
2628 case SMB_FILE_NAME_INFORMATION:
2629 /* Pathname with leading '\'. */
2631 size_t byte_len;
2632 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2633 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2634 SIVAL(pdata,0,byte_len);
2635 data_size = 4 + byte_len;
2636 break;
2639 case SMB_FILE_DISPOSITION_INFORMATION:
2640 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2641 data_size = 1;
2642 SCVAL(pdata,0,delete_pending);
2643 break;
2645 case SMB_FILE_POSITION_INFORMATION:
2646 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2647 data_size = 8;
2648 SOFF_T(pdata,0,pos);
2649 break;
2651 case SMB_FILE_MODE_INFORMATION:
2652 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2653 SIVAL(pdata,0,mode);
2654 data_size = 4;
2655 break;
2657 case SMB_FILE_ALIGNMENT_INFORMATION:
2658 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2659 SIVAL(pdata,0,0); /* No alignment needed. */
2660 data_size = 4;
2661 break;
2663 #if 0
2665 * NT4 server just returns "invalid query" to this - if we try to answer
2666 * it then NTws gets a BSOD! (tridge).
2667 * W2K seems to want this. JRA.
2669 case SMB_QUERY_FILE_STREAM_INFO:
2670 #endif
2671 case SMB_FILE_STREAM_INFORMATION:
2672 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2673 if (mode & aDIR) {
2674 data_size = 0;
2675 } else {
2676 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2677 SIVAL(pdata,0,0); /* ??? */
2678 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2679 SOFF_T(pdata,8,file_size);
2680 SIVAL(pdata,16,allocation_size);
2681 SIVAL(pdata,20,0); /* ??? */
2682 data_size = 24 + byte_len;
2684 break;
2686 case SMB_QUERY_COMPRESSION_INFO:
2687 case SMB_FILE_COMPRESSION_INFORMATION:
2688 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2689 SOFF_T(pdata,0,file_size);
2690 SIVAL(pdata,8,0); /* ??? */
2691 SIVAL(pdata,12,0); /* ??? */
2692 data_size = 16;
2693 break;
2695 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2696 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2697 put_long_date(pdata,c_time);
2698 put_long_date(pdata+8,sbuf.st_atime);
2699 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2700 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2701 SIVAL(pdata,32,allocation_size);
2702 SOFF_T(pdata,40,file_size);
2703 SIVAL(pdata,48,mode);
2704 SIVAL(pdata,52,0); /* ??? */
2705 data_size = 56;
2706 break;
2708 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2709 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2710 SIVAL(pdata,0,mode);
2711 SIVAL(pdata,4,0);
2712 data_size = 8;
2713 break;
2716 * CIFS UNIX Extensions.
2719 case SMB_QUERY_FILE_UNIX_BASIC:
2721 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2722 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2724 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2725 pdata += 8;
2727 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2728 pdata += 8;
2730 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2731 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2732 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2733 pdata += 24;
2735 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2736 SIVAL(pdata,4,0);
2737 pdata += 8;
2739 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2740 SIVAL(pdata,4,0);
2741 pdata += 8;
2743 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2744 pdata += 4;
2746 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2747 SIVAL(pdata,4,0);
2748 pdata += 8;
2750 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2751 SIVAL(pdata,4,0);
2752 pdata += 8;
2754 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2755 pdata += 8;
2757 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2758 SIVAL(pdata,4,0);
2759 pdata += 8;
2761 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2762 SIVAL(pdata,4,0);
2763 pdata += 8+1;
2764 data_size = PTR_DIFF(pdata,(*ppdata));
2767 int i;
2768 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2770 for (i=0; i<100; i++)
2771 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2772 DEBUG(4,("\n"));
2775 break;
2777 case SMB_QUERY_FILE_UNIX_LINK:
2779 pstring buffer;
2781 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2782 #ifdef S_ISLNK
2783 if(!S_ISLNK(sbuf.st_mode))
2784 return(UNIXERROR(ERRSRV,ERRbadlink));
2785 #else
2786 return(UNIXERROR(ERRDOS,ERRbadlink));
2787 #endif
2788 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2789 if (len == -1)
2790 return(UNIXERROR(ERRDOS,ERRnoaccess));
2791 buffer[len] = 0;
2792 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2793 pdata += len;
2794 data_size = PTR_DIFF(pdata,(*ppdata));
2796 break;
2799 default:
2800 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2803 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2805 return(-1);
2808 /****************************************************************************
2809 Deal with the internal needs of setting the delete on close flag. Note that
2810 as the tdb locking is recursive, it is safe to call this from within
2811 open_file_shared. JRA.
2812 ****************************************************************************/
2814 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
2816 if (delete_on_close) {
2818 * Only allow delete on close for writable files.
2821 if (dosmode & aRONLY) {
2822 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
2823 fsp->fsp_name ));
2824 return NT_STATUS_CANNOT_DELETE;
2828 * Only allow delete on close for writable shares.
2831 if (!CAN_WRITE(fsp->conn)) {
2832 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2833 fsp->fsp_name ));
2834 return NT_STATUS_ACCESS_DENIED;
2838 * Only allow delete on close for files/directories opened with delete intent.
2841 if (!(fsp->desired_access & DELETE_ACCESS)) {
2842 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2843 fsp->fsp_name ));
2844 return NT_STATUS_ACCESS_DENIED;
2848 if(fsp->is_directory) {
2849 fsp->directory_delete_on_close = delete_on_close;
2850 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2851 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2852 } else {
2853 fsp->delete_on_close = delete_on_close;
2854 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2855 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2858 return NT_STATUS_OK;
2861 /****************************************************************************
2862 Sets the delete on close flag over all share modes on this file.
2863 Modify the share mode entry for all files open
2864 on this device and inode to tell other smbds we have
2865 changed the delete on close flag. This will be noticed
2866 in the close code, the last closer will delete the file
2867 if flag is set.
2868 ****************************************************************************/
2870 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2872 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2873 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2875 if (fsp->is_directory || fsp->is_stat)
2876 return NT_STATUS_OK;
2878 if (lock_share_entry_fsp(fsp) == False)
2879 return NT_STATUS_ACCESS_DENIED;
2881 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2882 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
2883 fsp->fsp_name ));
2884 unlock_share_entry_fsp(fsp);
2885 return NT_STATUS_ACCESS_DENIED;
2888 unlock_share_entry_fsp(fsp);
2889 return NT_STATUS_OK;
2892 /****************************************************************************
2893 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2894 code.
2895 ****************************************************************************/
2897 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2899 BOOL bad_path_oldname = False;
2900 BOOL bad_path_newname = False;
2901 SMB_STRUCT_STAT sbuf1, sbuf2;
2902 pstring last_component_oldname;
2903 pstring last_component_newname;
2904 NTSTATUS status = NT_STATUS_OK;
2906 ZERO_STRUCT(sbuf1);
2907 ZERO_STRUCT(sbuf2);
2909 /* No wildcards. */
2910 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2911 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2914 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2915 if (bad_path_oldname) {
2916 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2919 /* Quick check for "." and ".." */
2920 if (last_component_oldname[0] == '.') {
2921 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2922 return NT_STATUS_OBJECT_NAME_INVALID;
2926 /* source must already exist. */
2927 if (!VALID_STAT(sbuf1)) {
2928 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2931 if (!check_name(oldname,conn)) {
2932 return NT_STATUS_ACCESS_DENIED;
2935 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2936 if (bad_path_newname) {
2937 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2940 /* Quick check for "." and ".." */
2941 if (last_component_newname[0] == '.') {
2942 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2943 return NT_STATUS_OBJECT_NAME_INVALID;
2947 /* Disallow if newname already exists. */
2948 if (VALID_STAT(sbuf2)) {
2949 return NT_STATUS_OBJECT_NAME_COLLISION;
2952 if (!check_name(newname,conn)) {
2953 return NT_STATUS_ACCESS_DENIED;
2956 /* No links from a directory. */
2957 if (S_ISDIR(sbuf1.st_mode)) {
2958 return NT_STATUS_FILE_IS_A_DIRECTORY;
2961 /* Ensure this is within the share. */
2962 if (!reduce_name(conn, oldname) != 0)
2963 return NT_STATUS_ACCESS_DENIED;
2965 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
2967 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
2968 status = map_nt_error_from_unix(errno);
2969 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
2970 nt_errstr(status), newname, oldname));
2973 return status;
2976 /****************************************************************************
2977 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2978 ****************************************************************************/
2980 static int call_trans2setfilepathinfo(connection_struct *conn,
2981 char *inbuf, char *outbuf, int length, int bufsize,
2982 char **pparams, int total_params, char **ppdata, int total_data)
2984 char *params = *pparams;
2985 char *pdata = *ppdata;
2986 uint16 tran_call = SVAL(inbuf, smb_setup0);
2987 uint16 info_level;
2988 int dosmode=0;
2989 SMB_OFF_T size=0;
2990 struct utimbuf tvs;
2991 SMB_STRUCT_STAT sbuf;
2992 pstring fname;
2993 int fd = -1;
2994 BOOL bad_path = False;
2995 files_struct *fsp = NULL;
2996 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2997 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2998 mode_t unixmode = 0;
2999 NTSTATUS status = NT_STATUS_OK;
3001 if (!params)
3002 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3004 ZERO_STRUCT(sbuf);
3006 if (tran_call == TRANSACT2_SETFILEINFO) {
3007 if (total_params < 4)
3008 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3010 fsp = file_fsp(params,0);
3011 info_level = SVAL(params,2);
3013 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3015 * This is actually a SETFILEINFO on a directory
3016 * handle (returned from an NT SMB). NT5.0 seems
3017 * to do this call. JRA.
3019 pstrcpy(fname, fsp->fsp_name);
3020 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3021 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3022 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3024 } else if (fsp && fsp->print_file) {
3026 * Doing a DELETE_ON_CLOSE should cancel a print job.
3028 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3029 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3031 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3033 SSVAL(params,0,0);
3034 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3035 return(-1);
3036 } else
3037 return (UNIXERROR(ERRDOS,ERRbadpath));
3038 } else {
3040 * Original code - this is an open file.
3042 CHECK_FSP(fsp,conn);
3044 pstrcpy(fname, fsp->fsp_name);
3045 fd = fsp->fd;
3047 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3048 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3049 return(UNIXERROR(ERRDOS,ERRbadfid));
3052 } else {
3053 /* set path info */
3054 if (total_params < 6)
3055 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3057 info_level = SVAL(params,0);
3058 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3059 if (!NT_STATUS_IS_OK(status)) {
3060 return ERROR_NT(status);
3062 unix_convert(fname,conn,0,&bad_path,&sbuf);
3063 if (bad_path) {
3064 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3068 * For CIFS UNIX extensions the target name may not exist.
3071 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3072 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3073 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3076 if(!check_name(fname, conn)) {
3077 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3082 if (!CAN_WRITE(conn))
3083 return ERROR_DOS(ERRSRV,ERRaccess);
3085 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3086 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3088 if (VALID_STAT(sbuf))
3089 unixmode = sbuf.st_mode;
3091 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3092 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3094 /* Realloc the parameter and data sizes */
3095 params = Realloc(*pparams,2);
3096 if(params == NULL)
3097 return ERROR_DOS(ERRDOS,ERRnomem);
3098 *pparams = params;
3100 SSVAL(params,0,0);
3102 if (fsp) {
3103 /* the pending modtime overrides the current modtime */
3104 sbuf.st_mtime = fsp->pending_modtime;
3107 size = get_file_size(sbuf);
3108 tvs.modtime = sbuf.st_mtime;
3109 tvs.actime = sbuf.st_atime;
3110 dosmode = dos_mode(conn,fname,&sbuf);
3111 unixmode = sbuf.st_mode;
3113 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3114 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3116 switch (info_level) {
3117 case SMB_INFO_STANDARD:
3119 if (total_data < 12)
3120 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3122 /* access time */
3123 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3124 /* write time */
3125 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3126 break;
3129 case SMB_INFO_SET_EA:
3130 status = set_ea(conn, fsp, fname, pdata, total_data);
3131 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3132 return ERROR_NT(status);
3133 break;
3135 /* XXXX um, i don't think this is right.
3136 it's also not in the cifs6.txt spec.
3138 case SMB_INFO_QUERY_EAS_FROM_LIST:
3139 if (total_data < 28)
3140 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3142 tvs.actime = make_unix_date2(pdata+8);
3143 tvs.modtime = make_unix_date2(pdata+12);
3144 size = IVAL(pdata,16);
3145 dosmode = IVAL(pdata,24);
3146 break;
3148 /* XXXX nor this. not in cifs6.txt, either. */
3149 case SMB_INFO_QUERY_ALL_EAS:
3150 if (total_data < 28)
3151 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3153 tvs.actime = make_unix_date2(pdata+8);
3154 tvs.modtime = make_unix_date2(pdata+12);
3155 size = IVAL(pdata,16);
3156 dosmode = IVAL(pdata,24);
3157 break;
3159 case SMB_SET_FILE_BASIC_INFO:
3160 case SMB_FILE_BASIC_INFORMATION:
3162 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3163 time_t write_time;
3164 time_t changed_time;
3166 if (total_data < 36)
3167 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3169 /* Ignore create time at offset pdata. */
3171 /* access time */
3172 tvs.actime = interpret_long_date(pdata+8);
3174 write_time = interpret_long_date(pdata+16);
3175 changed_time = interpret_long_date(pdata+24);
3177 tvs.modtime = MIN(write_time, changed_time);
3179 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3180 tvs.modtime = write_time;
3182 /* Prefer a defined time to an undefined one. */
3183 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3184 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3185 ? changed_time : write_time);
3187 /* attributes */
3188 dosmode = IVAL(pdata,32);
3189 break;
3192 case SMB_FILE_ALLOCATION_INFORMATION:
3193 case SMB_SET_FILE_ALLOCATION_INFO:
3195 int ret = -1;
3196 SMB_BIG_UINT allocation_size;
3198 if (total_data < 8)
3199 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3201 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3202 #ifdef LARGE_SMB_OFF_T
3203 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3204 #else /* LARGE_SMB_OFF_T */
3205 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3206 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3207 #endif /* LARGE_SMB_OFF_T */
3208 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3209 fname, (double)allocation_size ));
3211 if (allocation_size)
3212 allocation_size = smb_roundup(allocation_size);
3214 if(allocation_size != get_file_size(sbuf)) {
3215 SMB_STRUCT_STAT new_sbuf;
3217 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3218 fname, (double)allocation_size ));
3220 if (fd == -1) {
3221 files_struct *new_fsp = NULL;
3222 int access_mode = 0;
3223 int action = 0;
3225 if(global_oplock_break) {
3226 /* Queue this file modify as we are the process of an oplock break. */
3228 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3229 DEBUGADD(2,( "in oplock break state.\n"));
3231 push_oplock_pending_smb_message(inbuf, length);
3232 return -1;
3235 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3236 SET_OPEN_MODE(DOS_OPEN_RDWR),
3237 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3238 FILE_ATTRIBUTE_NORMAL,
3239 INTERNAL_OPEN_ONLY, &access_mode, &action);
3241 if (new_fsp == NULL)
3242 return(UNIXERROR(ERRDOS,ERRbadpath));
3243 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3244 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3245 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3246 new_fsp->fnum, strerror(errno)));
3247 ret = -1;
3249 close_file(new_fsp,True);
3250 } else {
3251 ret = vfs_allocate_file_space(fsp, allocation_size);
3252 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3253 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3254 fsp->fnum, strerror(errno)));
3255 ret = -1;
3258 if (ret == -1)
3259 return ERROR_NT(NT_STATUS_DISK_FULL);
3261 /* Allocate can truncate size... */
3262 size = get_file_size(new_sbuf);
3265 break;
3268 case SMB_FILE_END_OF_FILE_INFORMATION:
3269 case SMB_SET_FILE_END_OF_FILE_INFO:
3271 if (total_data < 8)
3272 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3274 size = IVAL(pdata,0);
3275 #ifdef LARGE_SMB_OFF_T
3276 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3277 #else /* LARGE_SMB_OFF_T */
3278 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3279 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3280 #endif /* LARGE_SMB_OFF_T */
3281 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3282 break;
3285 case SMB_FILE_DISPOSITION_INFORMATION:
3286 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3288 BOOL delete_on_close;
3290 if (total_data < 1)
3291 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3293 delete_on_close = (CVAL(pdata,0) ? True : False);
3295 /* Just ignore this set on a path. */
3296 if (tran_call != TRANSACT2_SETFILEINFO)
3297 break;
3299 if (fsp == NULL)
3300 return(UNIXERROR(ERRDOS,ERRbadfid));
3302 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3304 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3305 return ERROR_NT(status);
3307 /* The set is across all open files on this dev/inode pair. */
3308 status =set_delete_on_close_over_all(fsp, delete_on_close);
3309 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3310 return ERROR_NT(status);
3312 break;
3315 case SMB_FILE_POSITION_INFORMATION:
3317 SMB_BIG_UINT position_information;
3319 if (total_data < 8)
3320 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3322 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3323 #ifdef LARGE_SMB_OFF_T
3324 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3325 #else /* LARGE_SMB_OFF_T */
3326 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3327 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3328 #endif /* LARGE_SMB_OFF_T */
3329 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3330 fname, (double)position_information ));
3331 if (fsp)
3332 fsp->position_information = position_information;
3333 break;
3337 * CIFS UNIX extensions.
3340 case SMB_SET_FILE_UNIX_BASIC:
3342 uint32 raw_unixmode;
3344 if (total_data < 100)
3345 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3347 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3348 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3349 size=IVAL(pdata,0); /* first 8 Bytes are size */
3350 #ifdef LARGE_SMB_OFF_T
3351 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3352 #else /* LARGE_SMB_OFF_T */
3353 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3354 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3355 #endif /* LARGE_SMB_OFF_T */
3357 pdata+=24; /* ctime & st_blocks are not changed */
3358 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3359 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3360 pdata+=16;
3361 set_owner = (uid_t)IVAL(pdata,0);
3362 pdata += 8;
3363 set_grp = (gid_t)IVAL(pdata,0);
3364 pdata += 8;
3365 raw_unixmode = IVAL(pdata,28);
3366 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3367 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3369 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3370 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3371 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3373 if (!VALID_STAT(sbuf)) {
3376 * The only valid use of this is to create character and block
3377 * devices, and named pipes. This is deprecated (IMHO) and
3378 * a new info level should be used for mknod. JRA.
3381 uint32 file_type = IVAL(pdata,0);
3382 #if defined(HAVE_MAKEDEV)
3383 uint32 dev_major = IVAL(pdata,4);
3384 uint32 dev_minor = IVAL(pdata,12);
3385 #endif
3387 uid_t myuid = geteuid();
3388 gid_t mygid = getegid();
3389 SMB_DEV_T dev = (SMB_DEV_T)0;
3391 if (tran_call == TRANSACT2_SETFILEINFO)
3392 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3394 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3395 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3397 #if defined(HAVE_MAKEDEV)
3398 dev = makedev(dev_major, dev_minor);
3399 #endif
3401 /* We can only create as the owner/group we are. */
3403 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3404 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3405 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3406 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3408 switch (file_type) {
3409 #if defined(S_IFIFO)
3410 case UNIX_TYPE_FIFO:
3411 unixmode |= S_IFIFO;
3412 break;
3413 #endif
3414 #if defined(S_IFSOCK)
3415 case UNIX_TYPE_SOCKET:
3416 unixmode |= S_IFSOCK;
3417 break;
3418 #endif
3419 #if defined(S_IFCHR)
3420 case UNIX_TYPE_CHARDEV:
3421 unixmode |= S_IFCHR;
3422 break;
3423 #endif
3424 #if defined(S_IFBLK)
3425 case UNIX_TYPE_BLKDEV:
3426 unixmode |= S_IFBLK;
3427 break;
3428 #endif
3429 default:
3430 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3433 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3434 0%o for file %s\n", (double)dev, unixmode, fname ));
3436 /* Ok - do the mknod. */
3437 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3438 return(UNIXERROR(ERRDOS,ERRnoaccess));
3440 inherit_access_acl(conn, fname, unixmode);
3442 SSVAL(params,0,0);
3443 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3444 return(-1);
3448 * Deal with the UNIX specific mode set.
3451 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3452 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3453 (unsigned int)unixmode, fname ));
3454 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3455 return(UNIXERROR(ERRDOS,ERRnoaccess));
3459 * Deal with the UNIX specific uid set.
3462 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3463 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3464 (unsigned int)set_owner, fname ));
3465 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3466 return(UNIXERROR(ERRDOS,ERRnoaccess));
3470 * Deal with the UNIX specific gid set.
3473 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3474 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3475 (unsigned int)set_owner, fname ));
3476 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3477 return(UNIXERROR(ERRDOS,ERRnoaccess));
3479 break;
3482 case SMB_SET_FILE_UNIX_LINK:
3484 pstring link_target;
3485 char *newname = fname;
3487 /* Set a symbolic link. */
3488 /* Don't allow this if follow links is false. */
3490 if (!lp_symlinks(SNUM(conn)))
3491 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3493 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3495 /* !widelinks forces the target path to be within the share. */
3496 /* This means we can interpret the target as a pathname. */
3497 if (!lp_widelinks(SNUM(conn))) {
3498 pstring rel_name;
3499 char *last_dirp = NULL;
3501 unix_format(link_target);
3502 if (*link_target == '/') {
3503 /* No absolute paths allowed. */
3504 return(UNIXERROR(ERRDOS,ERRnoaccess));
3506 pstrcpy(rel_name, newname);
3507 last_dirp = strrchr_m(rel_name, '/');
3508 if (last_dirp) {
3509 last_dirp[1] = '\0';
3510 } else {
3511 pstrcpy(rel_name, "./");
3513 pstrcat(rel_name, link_target);
3515 if (!check_name(rel_name, conn)) {
3516 return(UNIXERROR(ERRDOS,ERRnoaccess));
3520 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3521 fname, link_target ));
3523 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3524 return(UNIXERROR(ERRDOS,ERRnoaccess));
3525 SSVAL(params,0,0);
3526 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3527 return(-1);
3530 case SMB_SET_FILE_UNIX_HLINK:
3532 pstring oldname;
3533 char *newname = fname;
3535 /* Set a hard link. */
3536 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3537 if (!NT_STATUS_IS_OK(status)) {
3538 return ERROR_NT(status);
3541 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3542 fname, oldname));
3544 status = hardlink_internals(conn, oldname, newname);
3545 if (!NT_STATUS_IS_OK(status)) {
3546 return ERROR_NT(status);
3549 SSVAL(params,0,0);
3550 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3551 return(-1);
3554 case SMB_FILE_RENAME_INFORMATION:
3556 BOOL overwrite;
3557 uint32 root_fid;
3558 uint32 len;
3559 pstring newname;
3560 pstring base_name;
3561 char *p;
3563 if (total_data < 12)
3564 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3566 overwrite = (CVAL(pdata,0) ? True : False);
3567 root_fid = IVAL(pdata,4);
3568 len = IVAL(pdata,8);
3569 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3570 if (!NT_STATUS_IS_OK(status)) {
3571 return ERROR_NT(status);
3574 /* Check the new name has no '/' characters. */
3575 if (strchr_m(newname, '/'))
3576 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3578 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3580 /* Create the base directory. */
3581 pstrcpy(base_name, fname);
3582 p = strrchr_m(base_name, '/');
3583 if (p)
3584 *p = '\0';
3585 /* Append the new name. */
3586 pstrcat(base_name, "/");
3587 pstrcat(base_name, newname);
3589 if (fsp) {
3590 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3591 fsp->fnum, fsp->fsp_name, base_name ));
3592 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3593 } else {
3594 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3595 fname, newname ));
3596 status = rename_internals(conn, fname, base_name, 0, overwrite);
3598 if (!NT_STATUS_IS_OK(status)) {
3599 return ERROR_NT(status);
3601 process_pending_change_notify_queue((time_t)0);
3602 SSVAL(params,0,0);
3603 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3604 return(-1);
3606 default:
3607 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3610 /* get some defaults (no modifications) if any info is zero or -1. */
3611 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3612 tvs.actime = sbuf.st_atime;
3614 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3615 tvs.modtime = sbuf.st_mtime;
3617 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3618 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3619 DEBUG(6,("size: %.0f ", (double)size));
3621 if (dosmode) {
3622 if (S_ISDIR(sbuf.st_mode))
3623 dosmode |= aDIR;
3624 else
3625 dosmode &= ~aDIR;
3628 DEBUG(6,("dosmode: %x\n" , dosmode));
3630 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3631 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3632 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3633 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3636 * Only do this test if we are not explicitly
3637 * changing the size of a file.
3639 if (!size)
3640 size = get_file_size(sbuf);
3644 * Try and set the times, size and mode of this file -
3645 * if they are different from the current values
3647 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3648 if(fsp != NULL) {
3650 * This was a setfileinfo on an open file.
3651 * NT does this a lot. It's actually pointless
3652 * setting the time here, as it will be overwritten
3653 * on the next write, so we save the request
3654 * away and will set it on file close. JRA.
3657 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3658 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3659 fsp->pending_modtime = tvs.modtime;
3662 } else {
3664 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3666 if(file_utime(conn, fname, &tvs)!=0)
3667 return(UNIXERROR(ERRDOS,ERRnoaccess));
3671 /* check the mode isn't different, before changing it */
3672 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3674 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3676 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3677 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3678 return(UNIXERROR(ERRDOS,ERRnoaccess));
3682 if (size != get_file_size(sbuf)) {
3684 int ret;
3686 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3687 fname, (double)size ));
3689 if (fd == -1) {
3690 files_struct *new_fsp = NULL;
3691 int access_mode = 0;
3692 int action = 0;
3694 if(global_oplock_break) {
3695 /* Queue this file modify as we are the process of an oplock break. */
3697 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3698 DEBUGADD(2,( "in oplock break state.\n"));
3700 push_oplock_pending_smb_message(inbuf, length);
3701 return -1;
3704 new_fsp = open_file_shared(conn, fname, &sbuf,
3705 SET_OPEN_MODE(DOS_OPEN_RDWR),
3706 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3707 FILE_ATTRIBUTE_NORMAL,
3708 INTERNAL_OPEN_ONLY, &access_mode, &action);
3710 if (new_fsp == NULL)
3711 return(UNIXERROR(ERRDOS,ERRbadpath));
3712 ret = vfs_set_filelen(new_fsp, size);
3713 close_file(new_fsp,True);
3714 } else {
3715 ret = vfs_set_filelen(fsp, size);
3718 if (ret == -1)
3719 return (UNIXERROR(ERRHRD,ERRdiskfull));
3722 SSVAL(params,0,0);
3723 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3725 return(-1);
3728 /****************************************************************************
3729 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3730 ****************************************************************************/
3732 static int call_trans2mkdir(connection_struct *conn,
3733 char *inbuf, char *outbuf, int length, int bufsize,
3734 char **pparams, int total_params, char **ppdata, int total_data)
3736 char *params = *pparams;
3737 pstring directory;
3738 int ret = -1;
3739 SMB_STRUCT_STAT sbuf;
3740 BOOL bad_path = False;
3741 NTSTATUS status = NT_STATUS_OK;
3743 if (!CAN_WRITE(conn))
3744 return ERROR_DOS(ERRSRV,ERRaccess);
3746 if (total_params < 4)
3747 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3749 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
3750 if (!NT_STATUS_IS_OK(status)) {
3751 return ERROR_NT(status);
3754 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3756 unix_convert(directory,conn,0,&bad_path,&sbuf);
3757 if (bad_path) {
3758 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3760 if (check_name(directory,conn))
3761 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3763 if(ret < 0) {
3764 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3765 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3768 /* Realloc the parameter and data sizes */
3769 params = Realloc(*pparams,2);
3770 if(params == NULL)
3771 return ERROR_DOS(ERRDOS,ERRnomem);
3772 *pparams = params;
3774 SSVAL(params,0,0);
3776 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3778 return(-1);
3781 /****************************************************************************
3782 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3783 We don't actually do this - we just send a null response.
3784 ****************************************************************************/
3786 static int call_trans2findnotifyfirst(connection_struct *conn,
3787 char *inbuf, char *outbuf, int length, int bufsize,
3788 char **pparams, int total_params, char **ppdata, int total_data)
3790 static uint16 fnf_handle = 257;
3791 char *params = *pparams;
3792 uint16 info_level;
3794 if (total_params < 6)
3795 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3797 info_level = SVAL(params,4);
3798 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3800 switch (info_level) {
3801 case 1:
3802 case 2:
3803 break;
3804 default:
3805 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3808 /* Realloc the parameter and data sizes */
3809 params = Realloc(*pparams,6);
3810 if(params == NULL)
3811 return ERROR_DOS(ERRDOS,ERRnomem);
3812 *pparams = params;
3814 SSVAL(params,0,fnf_handle);
3815 SSVAL(params,2,0); /* No changes */
3816 SSVAL(params,4,0); /* No EA errors */
3818 fnf_handle++;
3820 if(fnf_handle == 0)
3821 fnf_handle = 257;
3823 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3825 return(-1);
3828 /****************************************************************************
3829 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3830 changes). Currently this does nothing.
3831 ****************************************************************************/
3833 static int call_trans2findnotifynext(connection_struct *conn,
3834 char *inbuf, char *outbuf, int length, int bufsize,
3835 char **pparams, int total_params, char **ppdata, int total_data)
3837 char *params = *pparams;
3839 DEBUG(3,("call_trans2findnotifynext\n"));
3841 /* Realloc the parameter and data sizes */
3842 params = Realloc(*pparams,4);
3843 if(params == NULL)
3844 return ERROR_DOS(ERRDOS,ERRnomem);
3845 *pparams = params;
3847 SSVAL(params,0,0); /* No changes */
3848 SSVAL(params,2,0); /* No EA errors */
3850 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3852 return(-1);
3855 /****************************************************************************
3856 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3857 ****************************************************************************/
3859 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3860 char* outbuf, int length, int bufsize,
3861 char **pparams, int total_params, char **ppdata, int total_data)
3863 char *params = *pparams;
3864 pstring pathname;
3865 int reply_size = 0;
3866 int max_referral_level;
3868 DEBUG(10,("call_trans2getdfsreferral\n"));
3870 if (total_params < 2)
3871 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3873 max_referral_level = SVAL(params,0);
3875 if(!lp_host_msdfs())
3876 return ERROR_DOS(ERRDOS,ERRbadfunc);
3878 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3879 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3880 return UNIXERROR(ERRDOS,ERRbadfile);
3882 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3883 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3885 return(-1);
3888 #define LMCAT_SPL 0x53
3889 #define LMFUNC_GETJOBID 0x60
3891 /****************************************************************************
3892 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3893 ****************************************************************************/
3895 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3896 char* outbuf, int length, int bufsize,
3897 char **pparams, int total_params, char **ppdata, int total_data)
3899 char *pdata = *ppdata;
3900 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3902 /* check for an invalid fid before proceeding */
3904 if (!fsp)
3905 return(ERROR_DOS(ERRDOS,ERRbadfid));
3907 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3908 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3909 pdata = Realloc(*ppdata, 32);
3910 if(pdata == NULL)
3911 return ERROR_DOS(ERRDOS,ERRnomem);
3912 *ppdata = pdata;
3914 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3915 CAN ACCEPT THIS IN UNICODE. JRA. */
3917 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3918 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3919 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3920 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3921 return(-1);
3922 } else {
3923 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3924 return ERROR_DOS(ERRSRV,ERRerror);
3928 /****************************************************************************
3929 Reply to a SMBfindclose (stop trans2 directory search).
3930 ****************************************************************************/
3932 int reply_findclose(connection_struct *conn,
3933 char *inbuf,char *outbuf,int length,int bufsize)
3935 int outsize = 0;
3936 int dptr_num=SVALS(inbuf,smb_vwv0);
3937 START_PROFILE(SMBfindclose);
3939 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3941 dptr_close(&dptr_num);
3943 outsize = set_message(outbuf,0,0,True);
3945 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3947 END_PROFILE(SMBfindclose);
3948 return(outsize);
3951 /****************************************************************************
3952 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3953 ****************************************************************************/
3955 int reply_findnclose(connection_struct *conn,
3956 char *inbuf,char *outbuf,int length,int bufsize)
3958 int outsize = 0;
3959 int dptr_num= -1;
3960 START_PROFILE(SMBfindnclose);
3962 dptr_num = SVAL(inbuf,smb_vwv0);
3964 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3966 /* We never give out valid handles for a
3967 findnotifyfirst - so any dptr_num is ok here.
3968 Just ignore it. */
3970 outsize = set_message(outbuf,0,0,True);
3972 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3974 END_PROFILE(SMBfindnclose);
3975 return(outsize);
3978 /****************************************************************************
3979 Reply to a SMBtranss2 - just ignore it!
3980 ****************************************************************************/
3982 int reply_transs2(connection_struct *conn,
3983 char *inbuf,char *outbuf,int length,int bufsize)
3985 START_PROFILE(SMBtranss2);
3986 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3987 END_PROFILE(SMBtranss2);
3988 return(-1);
3991 /****************************************************************************
3992 Reply to a SMBtrans2.
3993 ****************************************************************************/
3995 int reply_trans2(connection_struct *conn,
3996 char *inbuf,char *outbuf,int length,int bufsize)
3998 int outsize = 0;
3999 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4000 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4001 #if 0
4002 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4003 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
4004 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4005 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4006 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4007 int32 timeout = IVALS(inbuf,smb_timeout);
4008 #endif
4009 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4010 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4011 char *params = NULL, *data = NULL;
4012 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4013 START_PROFILE(SMBtrans2);
4015 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4016 /* Queue this open message as we are the process of an
4017 * oplock break. */
4019 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4020 DEBUGADD(2,( "in oplock break state.\n"));
4022 push_oplock_pending_smb_message(inbuf, length);
4023 END_PROFILE(SMBtrans2);
4024 return -1;
4027 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4028 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4029 END_PROFILE(SMBtrans2);
4030 return ERROR_DOS(ERRSRV,ERRaccess);
4033 outsize = set_message(outbuf,0,0,True);
4035 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4036 is so as a sanity check */
4037 if (suwcnt != 1) {
4039 * Need to have rc=0 for ioctl to get job id for OS/2.
4040 * Network printing will fail if function is not successful.
4041 * Similar function in reply.c will be used if protocol
4042 * is LANMAN1.0 instead of LM1.2X002.
4043 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4044 * outbuf doesn't have to be set(only job id is used).
4046 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4047 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4048 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4049 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4050 } else {
4051 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4052 DEBUG(2,("Transaction is %d\n",tran_call));
4053 END_PROFILE(SMBtrans2);
4054 ERROR_DOS(ERRDOS,ERRinvalidparam);
4058 /* Allocate the space for the maximum needed parameters and data */
4059 if (total_params > 0)
4060 params = (char *)malloc(total_params);
4061 if (total_data > 0)
4062 data = (char *)malloc(total_data);
4064 if ((total_params && !params) || (total_data && !data)) {
4065 DEBUG(2,("Out of memory in reply_trans2\n"));
4066 SAFE_FREE(params);
4067 SAFE_FREE(data);
4068 END_PROFILE(SMBtrans2);
4069 return ERROR_DOS(ERRDOS,ERRnomem);
4072 /* Copy the param and data bytes sent with this request into
4073 the params buffer */
4074 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4075 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4077 if (num_params > total_params || num_data > total_data)
4078 exit_server("invalid params in reply_trans2");
4080 if(params) {
4081 unsigned int psoff = SVAL(inbuf, smb_psoff);
4082 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4083 goto bad_param;
4084 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4085 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4086 goto bad_param;
4087 memcpy( params, smb_base(inbuf) + psoff, num_params);
4089 if(data) {
4090 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4091 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4092 goto bad_param;
4093 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4094 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4095 goto bad_param;
4096 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4099 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4101 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4102 /* We need to send an interim response then receive the rest
4103 of the parameter/data bytes */
4104 outsize = set_message(outbuf,0,0,True);
4105 srv_signing_trans_stop();
4106 if (!send_smb(smbd_server_fd(),outbuf))
4107 exit_server("reply_trans2: send_smb failed.");
4109 while (num_data_sofar < total_data ||
4110 num_params_sofar < total_params) {
4111 BOOL ret;
4112 unsigned int param_disp;
4113 unsigned int param_off;
4114 unsigned int data_disp;
4115 unsigned int data_off;
4117 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4120 * The sequence number for the trans reply is always
4121 * based on the last secondary received.
4124 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4126 if ((ret &&
4127 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4128 outsize = set_message(outbuf,0,0,True);
4129 if(ret)
4130 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4131 else
4132 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4133 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4134 goto bad_param;
4137 /* Revise total_params and total_data in case
4138 they have changed downwards */
4139 if (SVAL(inbuf, smb_tpscnt) < total_params)
4140 total_params = SVAL(inbuf, smb_tpscnt);
4141 if (SVAL(inbuf, smb_tdscnt) < total_data)
4142 total_data = SVAL(inbuf, smb_tdscnt);
4144 num_params = SVAL(inbuf,smb_spscnt);
4145 param_off = SVAL(inbuf, smb_spsoff);
4146 param_disp = SVAL(inbuf, smb_spsdisp);
4147 num_params_sofar += num_params;
4149 num_data = SVAL(inbuf, smb_sdscnt);
4150 data_off = SVAL(inbuf, smb_sdsoff);
4151 data_disp = SVAL(inbuf, smb_sdsdisp);
4152 num_data_sofar += num_data;
4154 if (num_params_sofar > total_params || num_data_sofar > total_data)
4155 goto bad_param;
4157 if (num_params) {
4158 if (param_disp + num_params >= total_params)
4159 goto bad_param;
4160 if ((param_disp + num_params < param_disp) ||
4161 (param_disp + num_params < num_params))
4162 goto bad_param;
4163 if (param_disp > total_params)
4164 goto bad_param;
4165 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4166 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4167 goto bad_param;
4168 if (params + param_disp < params)
4169 goto bad_param;
4171 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4173 if (num_data) {
4174 if (data_disp + num_data >= total_data)
4175 goto bad_param;
4176 if ((data_disp + num_data < data_disp) ||
4177 (data_disp + num_data < num_data))
4178 goto bad_param;
4179 if (data_disp > total_data)
4180 goto bad_param;
4181 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4182 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4183 goto bad_param;
4184 if (data + data_disp < data)
4185 goto bad_param;
4187 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4192 if (Protocol >= PROTOCOL_NT1) {
4193 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4196 /* Now we must call the relevant TRANS2 function */
4197 switch(tran_call) {
4198 case TRANSACT2_OPEN:
4199 START_PROFILE_NESTED(Trans2_open);
4200 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4201 &params, total_params, &data, total_data);
4202 END_PROFILE_NESTED(Trans2_open);
4203 break;
4205 case TRANSACT2_FINDFIRST:
4206 START_PROFILE_NESTED(Trans2_findfirst);
4207 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4208 &params, total_params, &data, total_data);
4209 END_PROFILE_NESTED(Trans2_findfirst);
4210 break;
4212 case TRANSACT2_FINDNEXT:
4213 START_PROFILE_NESTED(Trans2_findnext);
4214 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4215 &params, total_params, &data, total_data);
4216 END_PROFILE_NESTED(Trans2_findnext);
4217 break;
4219 case TRANSACT2_QFSINFO:
4220 START_PROFILE_NESTED(Trans2_qfsinfo);
4221 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4222 &params, total_params, &data, total_data);
4223 END_PROFILE_NESTED(Trans2_qfsinfo);
4224 break;
4226 #ifdef HAVE_SYS_QUOTAS
4227 case TRANSACT2_SETFSINFO:
4228 START_PROFILE_NESTED(Trans2_setfsinfo);
4229 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4230 &params, total_params, &data, total_data);
4231 END_PROFILE_NESTED(Trans2_setfsinfo);
4232 break;
4233 #endif
4234 case TRANSACT2_QPATHINFO:
4235 case TRANSACT2_QFILEINFO:
4236 START_PROFILE_NESTED(Trans2_qpathinfo);
4237 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4238 &params, total_params, &data, total_data);
4239 END_PROFILE_NESTED(Trans2_qpathinfo);
4240 break;
4241 case TRANSACT2_SETPATHINFO:
4242 case TRANSACT2_SETFILEINFO:
4243 START_PROFILE_NESTED(Trans2_setpathinfo);
4244 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4245 &params, total_params, &data, total_data);
4246 END_PROFILE_NESTED(Trans2_setpathinfo);
4247 break;
4249 case TRANSACT2_FINDNOTIFYFIRST:
4250 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4251 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4252 &params, total_params, &data, total_data);
4253 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4254 break;
4256 case TRANSACT2_FINDNOTIFYNEXT:
4257 START_PROFILE_NESTED(Trans2_findnotifynext);
4258 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4259 &params, total_params, &data, total_data);
4260 END_PROFILE_NESTED(Trans2_findnotifynext);
4261 break;
4262 case TRANSACT2_MKDIR:
4263 START_PROFILE_NESTED(Trans2_mkdir);
4264 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4265 &params, total_params, &data, total_data);
4266 END_PROFILE_NESTED(Trans2_mkdir);
4267 break;
4269 case TRANSACT2_GET_DFS_REFERRAL:
4270 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4271 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4272 &params, total_params, &data, total_data);
4273 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4274 break;
4275 case TRANSACT2_IOCTL:
4276 START_PROFILE_NESTED(Trans2_ioctl);
4277 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4278 &params, total_params, &data, total_data);
4279 END_PROFILE_NESTED(Trans2_ioctl);
4280 break;
4281 default:
4282 /* Error in request */
4283 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4284 SAFE_FREE(params);
4285 SAFE_FREE(data);
4286 END_PROFILE(SMBtrans2);
4287 srv_signing_trans_stop();
4288 return ERROR_DOS(ERRSRV,ERRerror);
4291 /* As we do not know how many data packets will need to be
4292 returned here the various call_trans2xxxx calls
4293 must send their own. Thus a call_trans2xxx routine only
4294 returns a value other than -1 when it wants to send
4295 an error packet.
4298 srv_signing_trans_stop();
4300 SAFE_FREE(params);
4301 SAFE_FREE(data);
4302 END_PROFILE(SMBtrans2);
4303 return outsize; /* If a correct response was needed the
4304 call_trans2xxx calls have already sent
4305 it. If outsize != -1 then it is returning */
4307 bad_param:
4309 srv_signing_trans_stop();
4310 SAFE_FREE(params);
4311 SAFE_FREE(data);
4312 END_PROFILE(SMBtrans2);
4313 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);