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.
27 extern BOOL case_sensitive;
28 extern int smb_read_error;
29 extern fstring local_machine;
30 extern int global_oplock_break;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
36 /* given a stat buffer return the allocated size on disk, taking into
37 account sparse files */
38 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
41 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
42 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
44 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
46 if (!ret && fsp && fsp->initial_allocation_size)
47 ret = fsp->initial_allocation_size;
48 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
52 /****************************************************************************
53 Utility functions for dealing with extended attributes.
54 ****************************************************************************/
56 static const char *prohibited_ea_names[] = {
57 SAMBA_POSIX_INHERITANCE_EA_NAME,
58 SAMBA_XATTR_DOS_ATTRIB,
62 /****************************************************************************
63 Refuse to allow clients to overwrite our private xattrs.
64 ****************************************************************************/
66 static BOOL samba_private_attr_name(const char *unix_ea_name)
70 for (i = 0; prohibited_ea_names[i]; i++) {
71 if (strequal( prohibited_ea_names[i], unix_ea_name))
78 struct ea_list *next, *prev;
82 /****************************************************************************
83 Get one EA value. Fill in a struct ea_struct.
84 ****************************************************************************/
86 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
87 const char *fname, char *ea_name, struct ea_struct *pea)
89 /* Get the value of this xattr. Max size is 64k. */
90 size_t attr_size = 256;
96 val = talloc_realloc(mem_ctx, val, attr_size);
101 if (fsp && fsp->fd != -1) {
102 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
104 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
107 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
116 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
117 dump_data(10, val, sizeret);
120 if (strnequal(ea_name, "user.", 5)) {
121 pea->name = &ea_name[5];
125 pea->value.data = val;
126 pea->value.length = (size_t)sizeret;
130 /****************************************************************************
131 Return a linked list of the total EA's. Plus a guess as to the total size
132 (NB. The is not the total size on the wire - we need to convert to DOS
134 ****************************************************************************/
136 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)
138 /* Get a list of all xattrs. Max namesize is 64k. */
139 size_t ea_namelist_size = 1024;
144 struct ea_list *ea_list_head = NULL;
150 if (!lp_ea_support(SNUM(conn))) {
154 for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6;
155 ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) {
156 if (fsp && fsp->fd != -1) {
157 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
159 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
162 if (sizeret == -1 && errno == ERANGE) {
163 ea_namelist_size *= 2;
172 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
175 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
176 struct ea_list *listp, *tmp;
178 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
181 listp = talloc(mem_ctx, sizeof(struct ea_list));
185 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
190 *pea_total_len += 4 + strlen(p) + 1 + listp->ea.value.length;
192 DLIST_ADD_END(ea_list_head, listp, tmp);
196 /* Add on 4 for total length. */
203 /****************************************************************************
204 Fill a qfilepathinfo buffer with EA's.
205 ****************************************************************************/
207 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
208 connection_struct *conn, files_struct *fsp, const char *fname)
210 unsigned int ret_data_size = 4;
213 TALLOC_CTX *mem_ctx = talloc_init("fill_ea_buffer");
214 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
216 SMB_ASSERT(total_data_size >= 4);
224 talloc_destroy(mem_ctx);
228 if (total_ea_len > total_data_size) {
229 talloc_destroy(mem_ctx);
233 total_data_size -= 4;
234 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
237 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
238 dos_namelen = strlen(dos_ea_name);
239 if (dos_namelen > 255 || dos_namelen == 0) {
242 if (ea_list->ea.value.length > 65535) {
245 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
249 /* We know we have room. */
250 SCVAL(p,0,ea_list->ea.flags);
251 SCVAL(p,1,dos_namelen);
252 SSVAL(p,2,ea_list->ea.value.length);
253 fstrcpy(p+4, dos_ea_name);
254 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
256 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
257 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
260 ret_data_size = PTR_DIFF(p, pdata);
261 talloc_destroy(mem_ctx);
262 SIVAL(pdata,0,ret_data_size);
263 return ret_data_size;
266 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
268 size_t total_ea_len = 0;
269 TALLOC_CTX *mem_ctx = talloc_init("estimate_ea_size");
271 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
272 talloc_destroy(mem_ctx);
276 /****************************************************************************
277 Ensure the EA name is case insensitive by matching any existing EA name.
278 ****************************************************************************/
280 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
283 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
284 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
286 for (; ea_list; ea_list = ea_list->next) {
287 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
288 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
289 &unix_ea_name[5], ea_list->ea.name));
290 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
294 talloc_destroy(mem_ctx);
297 /****************************************************************************
298 Set or delete an extended attribute.
299 ****************************************************************************/
301 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
302 char *pdata, int total_data)
304 unsigned int namelen;
307 fstring unix_ea_name;
309 if (!lp_ea_support(SNUM(conn))) {
310 return NT_STATUS_EAS_NOT_SUPPORTED;
313 if (total_data < 8) {
314 return NT_STATUS_INVALID_PARAMETER;
317 if (IVAL(pdata,0) > total_data) {
318 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
319 return NT_STATUS_INVALID_PARAMETER;
323 namelen = CVAL(pdata,1);
324 ealen = SVAL(pdata,2);
326 if (total_data < 8 + namelen + 1 + ealen) {
327 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
328 (unsigned int)total_data, namelen, ealen));
329 return NT_STATUS_INVALID_PARAMETER;
332 if (pdata[namelen] != '\0') {
333 DEBUG(10,("set_ea: ea name not null terminated\n"));
334 return NT_STATUS_INVALID_PARAMETER;
337 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
338 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
339 pdata += (namelen + 1);
341 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
343 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
345 DEBUG(10,("set_ea: data :\n"));
346 dump_data(10, pdata, ealen);
349 if (samba_private_attr_name(unix_ea_name)) {
350 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
351 return NT_STATUS_ACCESS_DENIED;
355 /* Remove the attribute. */
356 if (fsp && (fsp->fd != -1)) {
357 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
358 unix_ea_name, fsp->fsp_name));
359 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
361 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
362 unix_ea_name, fname));
363 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 /* Removing a non existent attribute always succeeds. */
367 if (ret == -1 && errno == ENOATTR) {
368 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
373 if (fsp && (fsp->fd != -1)) {
374 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
375 unix_ea_name, fsp->fsp_name));
376 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
378 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
379 unix_ea_name, fname));
380 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
385 if (errno == ENOTSUP) {
386 return NT_STATUS_EAS_NOT_SUPPORTED;
388 return map_nt_error_from_unix(errno);
394 /****************************************************************************
395 Send the required number of replies back.
396 We assume all fields other than the data fields are
397 set correctly for the type of call.
398 HACK ! Always assumes smb_setup field is zero.
399 ****************************************************************************/
401 static int send_trans2_replies(char *outbuf,
408 /* As we are using a protocol > LANMAN1 then the max_send
409 variable must have been set in the sessetupX call.
410 This takes precedence over the max_xmit field in the
411 global struct. These different max_xmit variables should
412 be merged as this is now too confusing */
415 int data_to_send = datasize;
416 int params_to_send = paramsize;
420 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
421 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
422 int data_alignment_offset = 0;
424 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
426 set_message(outbuf,10,0,True);
428 /* If there genuinely are no parameters or data to send just send the empty packet */
430 if(params_to_send == 0 && data_to_send == 0) {
431 if (!send_smb(smbd_server_fd(),outbuf))
432 exit_server("send_trans2_replies: send_smb failed.");
436 /* When sending params and data ensure that both are nicely aligned */
437 /* Only do this alignment when there is also data to send - else
438 can cause NT redirector problems. */
440 if (((params_to_send % 4) != 0) && (data_to_send != 0))
441 data_alignment_offset = 4 - (params_to_send % 4);
443 /* Space is bufsize minus Netbios over TCP header minus SMB header */
444 /* The alignment_offset is to align the param bytes on an even byte
445 boundary. NT 4.0 Beta needs this to work correctly. */
447 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
449 /* useable_space can never be more than max_send minus the alignment offset. */
451 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
453 while (params_to_send || data_to_send) {
454 /* Calculate whether we will totally or partially fill this packet */
456 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
458 /* We can never send more than useable_space */
460 * Note that 'useable_space' does not include the alignment offsets,
461 * but we must include the alignment offsets in the calculation of
462 * the length of the data we send over the wire, as the alignment offsets
463 * are sent here. Fix from Marc_Jacobsen@hp.com.
466 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
468 set_message(outbuf, 10, total_sent_thistime, True);
470 /* Set total params and data to be sent */
471 SSVAL(outbuf,smb_tprcnt,paramsize);
472 SSVAL(outbuf,smb_tdrcnt,datasize);
474 /* Calculate how many parameters and data we can fit into
475 * this packet. Parameters get precedence
478 params_sent_thistime = MIN(params_to_send,useable_space);
479 data_sent_thistime = useable_space - params_sent_thistime;
480 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
482 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
484 /* smb_proff is the offset from the start of the SMB header to the
485 parameter bytes, however the first 4 bytes of outbuf are
486 the Netbios over TCP header. Thus use smb_base() to subtract
487 them from the calculation */
489 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
491 if(params_sent_thistime == 0)
492 SSVAL(outbuf,smb_prdisp,0);
494 /* Absolute displacement of param bytes sent in this packet */
495 SSVAL(outbuf,smb_prdisp,pp - params);
497 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
498 if(data_sent_thistime == 0) {
499 SSVAL(outbuf,smb_droff,0);
500 SSVAL(outbuf,smb_drdisp, 0);
502 /* The offset of the data bytes is the offset of the
503 parameter bytes plus the number of parameters being sent this time */
504 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
505 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
506 SSVAL(outbuf,smb_drdisp, pd - pdata);
509 /* Copy the param bytes into the packet */
511 if(params_sent_thistime)
512 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
514 /* Copy in the data bytes */
515 if(data_sent_thistime)
516 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
517 data_alignment_offset,pd,data_sent_thistime);
519 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
520 params_sent_thistime, data_sent_thistime, useable_space));
521 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
522 params_to_send, data_to_send, paramsize, datasize));
524 /* Send the packet */
525 if (!send_smb(smbd_server_fd(),outbuf))
526 exit_server("send_trans2_replies: send_smb failed.");
528 pp += params_sent_thistime;
529 pd += data_sent_thistime;
531 params_to_send -= params_sent_thistime;
532 data_to_send -= data_sent_thistime;
535 if(params_to_send < 0 || data_to_send < 0) {
536 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
537 params_to_send, data_to_send));
545 /****************************************************************************
546 Reply to a TRANSACT2_OPEN.
547 ****************************************************************************/
549 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
550 char **pparams, int total_params, char **ppdata, int total_data)
552 char *params = *pparams;
557 BOOL return_additional_info;
566 int fmode=0,mtime=0,rmode;
568 SMB_STRUCT_STAT sbuf;
570 BOOL bad_path = False;
575 * Ensure we have enough parameters to perform the operation.
578 if (total_params < 29)
579 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
581 open_mode = SVAL(params, 2);
582 open_attr = SVAL(params,6);
583 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
585 return_additional_info = BITSETW(params,0);
586 open_sattr = SVAL(params, 4);
587 open_time = make_unix_date3(params+8);
589 open_ofun = SVAL(params,12);
590 open_size = IVAL(params,14);
594 return(ERROR_DOS(ERRSRV,ERRaccess));
596 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
597 if (!NT_STATUS_IS_OK(status)) {
598 return ERROR_NT(status);
601 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
602 fname,open_mode, open_attr, open_ofun, open_size));
604 /* XXXX we need to handle passed times, sattr and flags */
606 unix_convert(fname,conn,0,&bad_path,&sbuf);
608 if (!check_name(fname,conn)) {
609 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
612 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
613 oplock_request, &rmode,&smb_action);
616 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
619 size = get_file_size(sbuf);
620 fmode = dos_mode(conn,fname,&sbuf);
621 mtime = sbuf.st_mtime;
624 close_file(fsp,False);
625 return(ERROR_DOS(ERRDOS,ERRnoaccess));
628 /* Realloc the size of parameters and data we will return */
629 params = Realloc(*pparams, 28);
631 return(ERROR_DOS(ERRDOS,ERRnomem));
634 memset((char *)params,'\0',28);
635 SSVAL(params,0,fsp->fnum);
636 SSVAL(params,2,fmode);
637 put_dos_date2(params,4, mtime);
638 SIVAL(params,8, (uint32)size);
639 SSVAL(params,12,rmode);
641 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
642 smb_action |= EXTENDED_OPLOCK_GRANTED;
644 SSVAL(params,18,smb_action);
647 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
649 SIVAL(params,20,inode);
651 /* Send the required number of replies */
652 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
657 /*********************************************************
658 Routine to check if a given string matches exactly.
659 as a special case a mask of "." does NOT match. That
660 is required for correct wildcard semantics
661 Case can be significant or not.
662 **********************************************************/
664 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
666 if (mask[0] == '.' && mask[1] == 0)
669 return strcmp(str,mask)==0;
670 if (StrCaseCmp(str,mask) != 0) {
673 if (ms_has_wild(str)) {
679 /****************************************************************************
680 Return the filetype for UNIX extensions.
681 ****************************************************************************/
683 static uint32 unix_filetype(mode_t mode)
686 return UNIX_TYPE_FILE;
687 else if(S_ISDIR(mode))
688 return UNIX_TYPE_DIR;
690 else if(S_ISLNK(mode))
691 return UNIX_TYPE_SYMLINK;
694 else if(S_ISCHR(mode))
695 return UNIX_TYPE_CHARDEV;
698 else if(S_ISBLK(mode))
699 return UNIX_TYPE_BLKDEV;
702 else if(S_ISFIFO(mode))
703 return UNIX_TYPE_FIFO;
706 else if(S_ISSOCK(mode))
707 return UNIX_TYPE_SOCKET;
710 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
711 return UNIX_TYPE_UNKNOWN;
714 /****************************************************************************
715 Return the major devicenumber for UNIX extensions.
716 ****************************************************************************/
718 static uint32 unix_dev_major(SMB_DEV_T dev)
720 #if defined(HAVE_DEVICE_MAJOR_FN)
721 return (uint32)major(dev);
723 return (uint32)(dev >> 8);
727 /****************************************************************************
728 Return the minor devicenumber for UNIX extensions.
729 ****************************************************************************/
731 static uint32 unix_dev_minor(SMB_DEV_T dev)
733 #if defined(HAVE_DEVICE_MINOR_FN)
734 return (uint32)minor(dev);
736 return (uint32)(dev & 0xff);
740 /****************************************************************************
741 Map wire perms onto standard UNIX permissions. Obey share restrictions.
742 ****************************************************************************/
744 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
748 if (perms == SMB_MODE_NO_CHANGE)
751 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
752 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
753 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
754 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
755 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
756 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
757 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
758 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
759 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
761 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
764 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
767 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
770 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
771 ret &= lp_dir_mask(SNUM(conn));
772 /* Add in force bits */
773 ret |= lp_force_dir_mode(SNUM(conn));
775 /* Apply mode mask */
776 ret &= lp_create_mask(SNUM(conn));
777 /* Add in force bits */
778 ret |= lp_force_create_mode(SNUM(conn));
784 /****************************************************************************
785 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
786 ****************************************************************************/
788 time_t interpret_long_unix_date(char *p)
790 DEBUG(1,("interpret_long_unix_date\n"));
791 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
792 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
795 return interpret_long_date(p);
799 /****************************************************************************
800 Get a level dependent lanman2 dir entry.
801 ****************************************************************************/
803 static BOOL get_lanman2_dir_entry(connection_struct *conn,
804 void *inbuf, void *outbuf,
805 char *path_mask,int dirtype,int info_level,
806 int requires_resume_key,
807 BOOL dont_descend,char **ppdata,
808 char *base_data, int space_remaining,
809 BOOL *out_of_space, BOOL *got_exact_match,
814 SMB_STRUCT_STAT sbuf;
818 char *p, *q, *pdata = *ppdata;
822 SMB_OFF_T file_size = 0;
823 SMB_BIG_UINT allocation_size = 0;
825 time_t mdate=0, adate=0, cdate=0;
828 int nt_extmode; /* Used for NT connections instead of mode */
829 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
832 *out_of_space = False;
833 *got_exact_match = False;
838 p = strrchr_m(path_mask,'/');
845 pstrcpy(mask, path_mask);
850 /* Needed if we run out of space */
851 prev_dirpos = TellDir(conn->dirptr);
852 dname = ReadDirName(conn->dirptr);
855 * Due to bugs in NT client redirectors we are not using
856 * resume keys any more - set them to zero.
857 * Check out the related comments in findfirst/findnext.
863 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
864 (long)conn->dirptr,TellDir(conn->dirptr)));
869 pstrcpy(fname,dname);
871 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
872 got_match = mask_match(fname, mask, case_sensitive);
874 if(!got_match && !mangle_is_8_3(fname, False)) {
877 * It turns out that NT matches wildcards against
878 * both long *and* short names. This may explain some
879 * of the wildcard wierdness from old DOS clients
880 * that some people have been seeing.... JRA.
884 pstrcpy( newname, fname);
885 mangle_map( newname, True, False, SNUM(conn));
886 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
887 got_match = mask_match(newname, mask, case_sensitive);
891 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
892 if (dont_descend && !isdots)
895 pstrcpy(pathreal,conn->dirpath);
897 pstrcat(pathreal,"/");
898 pstrcat(pathreal,dname);
900 if (INFO_LEVEL_IS_UNIX(info_level)) {
901 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
902 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
903 pathreal,strerror(errno)));
906 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
908 /* Needed to show the msdfs symlinks as
911 if(lp_host_msdfs() &&
912 lp_msdfs_root(SNUM(conn)) &&
913 is_msdfs_link(conn, pathreal, NULL, NULL,
916 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
917 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
921 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
922 pathreal,strerror(errno)));
927 mode = dos_mode(conn,pathreal,&sbuf);
929 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
930 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
934 file_size = get_file_size(sbuf);
935 allocation_size = get_allocation_size(NULL,&sbuf);
936 mdate = sbuf.st_mtime;
937 adate = sbuf.st_atime;
938 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
940 if (lp_dos_filetime_resolution(SNUM(conn))) {
949 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
955 mangle_map(fname,False,True,SNUM(conn));
960 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
962 switch (info_level) {
963 case SMB_INFO_STANDARD:
964 if(requires_resume_key) {
968 put_dos_date2(p,l1_fdateCreation,cdate);
969 put_dos_date2(p,l1_fdateLastAccess,adate);
970 put_dos_date2(p,l1_fdateLastWrite,mdate);
971 SIVAL(p,l1_cbFile,(uint32)file_size);
972 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
973 SSVAL(p,l1_attrFile,mode);
976 p += align_string(outbuf, p, 0);
977 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
978 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
979 SCVAL(nameptr, -1, len-2);
981 SCVAL(nameptr, -1, len-1);
985 case SMB_INFO_QUERY_EA_SIZE:
986 if(requires_resume_key) {
990 put_dos_date2(p,l2_fdateCreation,cdate);
991 put_dos_date2(p,l2_fdateLastAccess,adate);
992 put_dos_date2(p,l2_fdateLastWrite,mdate);
993 SIVAL(p,l2_cbFile,(uint32)file_size);
994 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
995 SSVAL(p,l2_attrFile,mode);
996 SIVAL(p,l2_cbList,0); /* No extended attributes */
999 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1000 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
1001 SCVAL(nameptr, -1, len-2);
1003 SCVAL(nameptr, -1, len-1);
1007 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1008 was_8_3 = mangle_is_8_3(fname, True);
1010 SIVAL(p,0,reskey); p += 4;
1011 put_long_date(p,cdate); p += 8;
1012 put_long_date(p,adate); p += 8;
1013 put_long_date(p,mdate); p += 8;
1014 put_long_date(p,mdate); p += 8;
1015 SOFF_T(p,0,file_size);
1016 SOFF_T(p,8,allocation_size);
1018 SIVAL(p,0,nt_extmode); p += 4;
1020 SIVAL(p,0,0); p += 4;
1021 /* Clear the short name buffer. This is
1022 * IMPORTANT as not doing so will trigger
1023 * a Win2k client bug. JRA.
1026 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1027 pstring mangled_name;
1028 pstrcpy(mangled_name, fname);
1029 mangle_map(mangled_name,True,True,SNUM(conn));
1030 mangled_name[12] = 0;
1031 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1038 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1041 len = PTR_DIFF(p, pdata);
1042 len = (len + 3) & ~3;
1047 case SMB_FIND_FILE_DIRECTORY_INFO:
1049 SIVAL(p,0,reskey); p += 4;
1050 put_long_date(p,cdate); p += 8;
1051 put_long_date(p,adate); p += 8;
1052 put_long_date(p,mdate); p += 8;
1053 put_long_date(p,mdate); p += 8;
1054 SOFF_T(p,0,file_size);
1055 SOFF_T(p,8,allocation_size);
1057 SIVAL(p,0,nt_extmode); p += 4;
1059 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1062 len = PTR_DIFF(p, pdata);
1063 len = (len + 3) & ~3;
1068 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1070 SIVAL(p,0,reskey); p += 4;
1071 put_long_date(p,cdate); p += 8;
1072 put_long_date(p,adate); p += 8;
1073 put_long_date(p,mdate); p += 8;
1074 put_long_date(p,mdate); p += 8;
1075 SOFF_T(p,0,file_size);
1076 SOFF_T(p,8,allocation_size);
1078 SIVAL(p,0,nt_extmode);
1081 SIVAL(p,4,0); /* ea size */
1082 len = srvstr_push(outbuf, p+8, fname, -1, STR_TERMINATE_ASCII);
1086 len = PTR_DIFF(p, pdata);
1087 len = (len + 3) & ~3;
1092 case SMB_FIND_FILE_NAMES_INFO:
1094 SIVAL(p,0,reskey); p += 4;
1096 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1097 acl on a dir (tridge) */
1098 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1101 len = PTR_DIFF(p, pdata);
1102 len = (len + 3) & ~3;
1107 case SMB_FIND_FILE_LEVEL_261:
1109 SIVAL(p,0,reskey); p += 4;
1110 put_long_date(p,cdate); p += 8;
1111 put_long_date(p,adate); p += 8;
1112 put_long_date(p,mdate); p += 8;
1113 put_long_date(p,mdate); p += 8;
1114 SOFF_T(p,0,file_size);
1115 SOFF_T(p,8,allocation_size);
1117 SIVAL(p,0,nt_extmode);
1119 len = srvstr_push(outbuf, p + 20, fname, -1, STR_TERMINATE_ASCII);
1121 memset(p+4,'\0',16); /* EA size. Unknown 0 1 2 */
1122 p += 20 + len; /* Strlen, EA size. Unknown 0 1 2, string itself */
1123 len = PTR_DIFF(p, pdata);
1124 len = (len + 3) & ~3;
1129 case SMB_FIND_FILE_LEVEL_262:
1130 was_8_3 = mangle_is_8_3(fname, True);
1132 SIVAL(p,0,reskey); p += 4;
1133 put_long_date(p,cdate); p += 8;
1134 put_long_date(p,adate); p += 8;
1135 put_long_date(p,mdate); p += 8;
1136 put_long_date(p,mdate); p += 8;
1137 SOFF_T(p,0,file_size);
1138 SOFF_T(p,8,allocation_size);
1140 SIVAL(p,0,nt_extmode); p += 4;
1142 SIVAL(p,0,0); p += 4;
1143 /* Clear the short name buffer. This is
1144 * IMPORTANT as not doing so will trigger
1145 * a Win2k client bug. JRA.
1148 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1149 pstring mangled_name;
1150 pstrcpy(mangled_name, fname);
1151 mangle_map(mangled_name,True,True,SNUM(conn));
1152 mangled_name[12] = 0;
1153 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1160 memset(p, '\0', 10); /* 2 4 byte unknowns plus a zero reserved. */
1162 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1165 len = PTR_DIFF(p, pdata);
1166 len = (len + 3) & ~3;
1171 /* CIFS UNIX Extension. */
1173 case SMB_FIND_FILE_UNIX:
1175 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1177 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1178 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1181 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1184 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
1185 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1186 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1189 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1193 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1197 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1200 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1204 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1208 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1211 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1215 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1219 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1222 len = PTR_DIFF(p, pdata);
1223 len = (len + 3) & ~3;
1224 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1226 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1235 if (PTR_DIFF(p,pdata) > space_remaining) {
1236 /* Move the dirptr back to prev_dirpos */
1237 SeekDir(conn->dirptr, prev_dirpos);
1238 *out_of_space = True;
1239 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1240 return False; /* Not finished - just out of space */
1243 /* Setup the last_filename pointer, as an offset from base_data */
1244 *last_name_off = PTR_DIFF(nameptr,base_data);
1245 /* Advance the data pointer to the next slot */
1251 /****************************************************************************
1252 Reply to a TRANS2_FINDFIRST.
1253 ****************************************************************************/
1255 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1256 char **pparams, int total_params, char **ppdata, int total_data)
1258 /* We must be careful here that we don't return more than the
1259 allowed number of data bytes. If this means returning fewer than
1260 maxentries then so be it. We assume that the redirector has
1261 enough room for the fixed number of parameter bytes it has
1263 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1264 char *params = *pparams;
1265 char *pdata = *ppdata;
1266 int dirtype = SVAL(params,0);
1267 int maxentries = SVAL(params,2);
1268 BOOL close_after_first = BITSETW(params+4,0);
1269 BOOL close_if_end = BITSETW(params+4,1);
1270 BOOL requires_resume_key = BITSETW(params+4,2);
1271 int info_level = SVAL(params,6);
1275 int last_name_off=0;
1279 BOOL finished = False;
1280 BOOL dont_descend = False;
1281 BOOL out_of_space = False;
1282 int space_remaining;
1283 BOOL bad_path = False;
1284 SMB_STRUCT_STAT sbuf;
1285 NTSTATUS ntstatus = NT_STATUS_OK;
1287 if (total_params < 12)
1288 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1290 *directory = *mask = 0;
1292 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1293 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
1294 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1295 info_level, max_data_bytes));
1297 switch (info_level) {
1298 case SMB_INFO_STANDARD:
1299 case SMB_INFO_QUERY_EA_SIZE:
1300 case SMB_FIND_FILE_DIRECTORY_INFO:
1301 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1302 case SMB_FIND_FILE_NAMES_INFO:
1303 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1304 case SMB_FIND_FILE_LEVEL_261:
1305 case SMB_FIND_FILE_LEVEL_262:
1307 case SMB_FIND_FILE_UNIX:
1308 if (!lp_unix_extensions())
1309 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1312 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1315 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
1316 if (!NT_STATUS_IS_OK(ntstatus)) {
1317 return ERROR_NT(ntstatus);
1320 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1322 unix_convert(directory,conn,0,&bad_path,&sbuf);
1323 if(!check_name(directory,conn)) {
1324 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1327 p = strrchr_m(directory,'/');
1329 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1330 if((directory[0] == '.') && (directory[1] == '\0'))
1333 pstrcpy(mask,directory);
1334 pstrcpy(directory,"./");
1340 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1342 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1344 return(ERROR_DOS(ERRDOS,ERRnomem));
1347 memset((char *)pdata,'\0',max_data_bytes + 1024);
1349 /* Realloc the params space */
1350 params = Realloc(*pparams, 10);
1352 return ERROR_DOS(ERRDOS,ERRnomem);
1355 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1357 return(UNIXERROR(ERRDOS,ERRbadfile));
1359 /* Save the wildcard match and attribs we are using on this directory -
1360 needed as lanman2 assumes these are being saved between calls */
1362 if(!(wcard = strdup(mask))) {
1363 dptr_close(&dptr_num);
1364 return ERROR_DOS(ERRDOS,ERRnomem);
1367 dptr_set_wcard(dptr_num, wcard);
1368 dptr_set_attr(dptr_num, dirtype);
1370 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1372 /* We don't need to check for VOL here as this is returned by
1373 a different TRANS2 call. */
1375 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1376 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1377 dont_descend = True;
1380 space_remaining = max_data_bytes;
1381 out_of_space = False;
1383 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1384 BOOL got_exact_match = False;
1386 /* this is a heuristic to avoid seeking the dirptr except when
1387 absolutely necessary. It allows for a filename of about 40 chars */
1388 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1389 out_of_space = True;
1392 finished = !get_lanman2_dir_entry(conn,
1394 mask,dirtype,info_level,
1395 requires_resume_key,dont_descend,
1396 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1400 if (finished && out_of_space)
1403 if (!finished && !out_of_space)
1407 * As an optimisation if we know we aren't looking
1408 * for a wildcard name (ie. the name matches the wildcard exactly)
1409 * then we can finish on any (first) match.
1410 * This speeds up large directory searches. JRA.
1416 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1419 /* Check if we can close the dirptr */
1420 if(close_after_first || (finished && close_if_end)) {
1421 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1422 dptr_close(&dptr_num);
1426 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1427 * from observation of NT.
1430 if(numentries == 0) {
1431 dptr_close(&dptr_num);
1432 return ERROR_DOS(ERRDOS,ERRbadfile);
1435 /* At this point pdata points to numentries directory entries. */
1437 /* Set up the return parameter block */
1438 SSVAL(params,0,dptr_num);
1439 SSVAL(params,2,numentries);
1440 SSVAL(params,4,finished);
1441 SSVAL(params,6,0); /* Never an EA error */
1442 SSVAL(params,8,last_name_off);
1444 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1446 if ((! *directory) && dptr_path(dptr_num))
1447 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1449 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1450 smb_fn_name(CVAL(inbuf,smb_com)),
1451 mask, directory, dirtype, numentries ) );
1454 * Force a name mangle here to ensure that the
1455 * mask as an 8.3 name is top of the mangled cache.
1456 * The reasons for this are subtle. Don't remove
1457 * this code unless you know what you are doing
1458 * (see PR#13758). JRA.
1461 if(!mangle_is_8_3_wildcards( mask, False))
1462 mangle_map(mask, True, True, SNUM(conn));
1467 /****************************************************************************
1468 Reply to a TRANS2_FINDNEXT.
1469 ****************************************************************************/
1471 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1472 char **pparams, int total_params, char **ppdata, int total_data)
1474 /* We must be careful here that we don't return more than the
1475 allowed number of data bytes. If this means returning fewer than
1476 maxentries then so be it. We assume that the redirector has
1477 enough room for the fixed number of parameter bytes it has
1479 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1480 char *params = *pparams;
1481 char *pdata = *ppdata;
1482 int dptr_num = SVAL(params,0);
1483 int maxentries = SVAL(params,2);
1484 uint16 info_level = SVAL(params,4);
1485 uint32 resume_key = IVAL(params,6);
1486 BOOL close_after_request = BITSETW(params+10,0);
1487 BOOL close_if_end = BITSETW(params+10,1);
1488 BOOL requires_resume_key = BITSETW(params+10,2);
1489 BOOL continue_bit = BITSETW(params+10,3);
1490 pstring resume_name;
1496 int i, last_name_off=0;
1497 BOOL finished = False;
1498 BOOL dont_descend = False;
1499 BOOL out_of_space = False;
1500 int space_remaining;
1501 NTSTATUS ntstatus = NT_STATUS_OK;
1503 if (total_params < 12)
1504 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1506 *mask = *directory = *resume_name = 0;
1508 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
1509 if (!NT_STATUS_IS_OK(ntstatus)) {
1510 return ERROR_NT(ntstatus);
1513 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1514 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1515 resume_key = %d resume name = %s continue=%d level = %d\n",
1516 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1517 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1519 switch (info_level) {
1520 case SMB_INFO_STANDARD:
1521 case SMB_INFO_QUERY_EA_SIZE:
1522 case SMB_FIND_FILE_DIRECTORY_INFO:
1523 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1524 case SMB_FIND_FILE_NAMES_INFO:
1525 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1527 case SMB_FIND_FILE_UNIX:
1528 if (!lp_unix_extensions())
1529 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1532 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1535 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1537 return ERROR_DOS(ERRDOS,ERRnomem);
1540 memset((char *)pdata,'\0',max_data_bytes + 1024);
1542 /* Realloc the params space */
1543 params = Realloc(*pparams, 6*SIZEOFWORD);
1544 if( params == NULL )
1545 return ERROR_DOS(ERRDOS,ERRnomem);
1549 /* Check that the dptr is valid */
1550 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1551 return ERROR_DOS(ERRDOS,ERRnofiles);
1553 string_set(&conn->dirpath,dptr_path(dptr_num));
1555 /* Get the wildcard mask from the dptr */
1556 if((p = dptr_wcard(dptr_num))== NULL) {
1557 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1558 return ERROR_DOS(ERRDOS,ERRnofiles);
1562 pstrcpy(directory,conn->dirpath);
1564 /* Get the attr mask from the dptr */
1565 dirtype = dptr_attr(dptr_num);
1567 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1568 dptr_num, mask, dirtype,
1570 TellDir(conn->dirptr)));
1572 /* We don't need to check for VOL here as this is returned by
1573 a different TRANS2 call. */
1575 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1576 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1577 dont_descend = True;
1580 space_remaining = max_data_bytes;
1581 out_of_space = False;
1584 * Seek to the correct position. We no longer use the resume key but
1585 * depend on the last file name instead.
1588 if(requires_resume_key && *resume_name && !continue_bit) {
1591 * Fix for NT redirector problem triggered by resume key indexes
1592 * changing between directory scans. We now return a resume key of 0
1593 * and instead look for the filename to continue from (also given
1594 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1595 * findfirst/findnext (as is usual) then the directory pointer
1596 * should already be at the correct place. Check this by scanning
1597 * backwards looking for an exact (ie. case sensitive) filename match.
1598 * If we get to the beginning of the directory and haven't found it then scan
1599 * forwards again looking for a match. JRA.
1602 int current_pos, start_pos;
1603 const char *dname = NULL;
1604 pstring dname_pstring;
1605 void *dirptr = conn->dirptr;
1606 start_pos = TellDir(dirptr);
1607 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1608 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1610 SeekDir(dirptr, current_pos);
1611 dname = ReadDirName(dirptr);
1614 * Remember, mangle_map is called by
1615 * get_lanman2_dir_entry(), so the resume name
1616 * could be mangled. Ensure we do the same
1620 /* make sure we get a copy that mangle_map can modify */
1622 pstrcpy(dname_pstring, dname);
1623 mangle_map( dname_pstring, False, True, SNUM(conn));
1625 if(strcsequal( resume_name, dname_pstring)) {
1626 SeekDir(dirptr, current_pos+1);
1627 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1634 * Scan forward from start if not found going backwards.
1637 if(current_pos < 0) {
1638 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1639 SeekDir(dirptr, start_pos);
1640 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1643 * Remember, mangle_map is called by
1644 * get_lanman2_dir_entry(), so the resume name
1645 * could be mangled. Ensure we do the same
1650 /* make sure we get a copy that mangle_map can modify */
1652 pstrcpy(dname_pstring, dname);
1653 mangle_map(dname_pstring, False, True, SNUM(conn));
1655 if(strcsequal( resume_name, dname_pstring)) {
1656 SeekDir(dirptr, current_pos+1);
1657 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1662 } /* end if current_pos */
1663 } /* end if requires_resume_key && !continue_bit */
1665 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1666 BOOL got_exact_match = False;
1668 /* this is a heuristic to avoid seeking the dirptr except when
1669 absolutely necessary. It allows for a filename of about 40 chars */
1670 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1671 out_of_space = True;
1674 finished = !get_lanman2_dir_entry(conn,
1676 mask,dirtype,info_level,
1677 requires_resume_key,dont_descend,
1678 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1682 if (finished && out_of_space)
1685 if (!finished && !out_of_space)
1689 * As an optimisation if we know we aren't looking
1690 * for a wildcard name (ie. the name matches the wildcard exactly)
1691 * then we can finish on any (first) match.
1692 * This speeds up large directory searches. JRA.
1698 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1701 /* Check if we can close the dirptr */
1702 if(close_after_request || (finished && close_if_end)) {
1703 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1704 dptr_close(&dptr_num); /* This frees up the saved mask */
1707 /* Set up the return parameter block */
1708 SSVAL(params,0,numentries);
1709 SSVAL(params,2,finished);
1710 SSVAL(params,4,0); /* Never an EA error */
1711 SSVAL(params,6,last_name_off);
1713 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1715 if ((! *directory) && dptr_path(dptr_num))
1716 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1718 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1719 smb_fn_name(CVAL(inbuf,smb_com)),
1720 mask, directory, dirtype, numentries ) );
1725 /****************************************************************************
1726 Reply to a TRANS2_QFSINFO (query filesystem info).
1727 ****************************************************************************/
1729 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1730 int length, int bufsize,
1731 char **pparams, int total_params, char **ppdata, int total_data)
1733 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1734 char *pdata = *ppdata;
1735 char *params = *pparams;
1736 uint16 info_level = SVAL(params,0);
1739 char *vname = volume_label(SNUM(conn));
1740 int snum = SNUM(conn);
1741 char *fstype = lp_fstype(SNUM(conn));
1744 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1746 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1747 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1748 return ERROR_DOS(ERRSRV,ERRinvdevice);
1751 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1752 if ( pdata == NULL )
1753 return ERROR_DOS(ERRDOS,ERRnomem);
1756 memset((char *)pdata,'\0',max_data_bytes + 1024);
1758 switch (info_level) {
1759 case SMB_INFO_ALLOCATION:
1761 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1763 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1764 block_size = lp_block_size(snum);
1765 if (bsize < block_size) {
1766 SMB_BIG_UINT factor = block_size/bsize;
1771 if (bsize > block_size) {
1772 SMB_BIG_UINT factor = bsize/block_size;
1777 bytes_per_sector = 512;
1778 sectors_per_unit = bsize/bytes_per_sector;
1780 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1781 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1782 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1784 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1785 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1786 SIVAL(pdata,l1_cUnit,dsize);
1787 SIVAL(pdata,l1_cUnitAvail,dfree);
1788 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1792 case SMB_INFO_VOLUME:
1793 /* Return volume name */
1795 * Add volume serial number - hash of a combination of
1796 * the called hostname and the service name.
1798 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1799 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1800 SCVAL(pdata,l2_vol_cch,len);
1801 data_len = l2_vol_szVolLabel + len;
1802 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1803 (unsigned)st.st_ctime, len, vname));
1806 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1807 case SMB_FS_ATTRIBUTE_INFORMATION:
1810 #if defined(HAVE_SYS_QUOTAS)
1811 quota_flag = FILE_VOLUME_QUOTAS;
1814 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1815 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1816 quota_flag); /* FS ATTRIBUTES */
1818 SIVAL(pdata,4,255); /* Max filename component length */
1819 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1820 and will think we can't do long filenames */
1821 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1823 data_len = 12 + len;
1826 case SMB_QUERY_FS_LABEL_INFO:
1827 case SMB_FS_LABEL_INFORMATION:
1828 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1833 case SMB_QUERY_FS_VOLUME_INFO:
1834 case SMB_FS_VOLUME_INFORMATION:
1837 * Add volume serial number - hash of a combination of
1838 * the called hostname and the service name.
1840 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1841 (str_checksum(local_machine)<<16));
1843 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1844 SIVAL(pdata,12,len);
1846 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1847 (int)strlen(vname),vname, lp_servicename(snum)));
1850 case SMB_QUERY_FS_SIZE_INFO:
1851 case SMB_FS_SIZE_INFORMATION:
1853 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1855 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1856 block_size = lp_block_size(snum);
1857 if (bsize < block_size) {
1858 SMB_BIG_UINT factor = block_size/bsize;
1863 if (bsize > block_size) {
1864 SMB_BIG_UINT factor = bsize/block_size;
1869 bytes_per_sector = 512;
1870 sectors_per_unit = bsize/bytes_per_sector;
1871 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1872 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1873 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1874 SBIG_UINT(pdata,0,dsize);
1875 SBIG_UINT(pdata,8,dfree);
1876 SIVAL(pdata,16,sectors_per_unit);
1877 SIVAL(pdata,20,bytes_per_sector);
1881 case SMB_FS_FULL_SIZE_INFORMATION:
1883 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1885 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1886 block_size = lp_block_size(snum);
1887 if (bsize < block_size) {
1888 SMB_BIG_UINT factor = block_size/bsize;
1893 if (bsize > block_size) {
1894 SMB_BIG_UINT factor = bsize/block_size;
1899 bytes_per_sector = 512;
1900 sectors_per_unit = bsize/bytes_per_sector;
1901 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1902 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1903 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1904 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1905 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1906 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1907 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1908 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1912 case SMB_QUERY_FS_DEVICE_INFO:
1913 case SMB_FS_DEVICE_INFORMATION:
1915 SIVAL(pdata,0,0); /* dev type */
1916 SIVAL(pdata,4,0); /* characteristics */
1919 #ifdef HAVE_SYS_QUOTAS
1920 case SMB_FS_QUOTA_INFORMATION:
1922 * what we have to send --metze:
1924 * Unknown1: 24 NULL bytes
1925 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1926 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1927 * Quota Flags: 2 byte :
1928 * Unknown3: 6 NULL bytes
1932 * details for Quota Flags:
1934 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1935 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1936 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1937 * 0x0001 Enable Quotas: enable quota for this fs
1941 /* we need to fake up a fsp here,
1942 * because its not send in this call
1945 SMB_NTQUOTA_STRUCT quotas;
1948 ZERO_STRUCT(quotas);
1955 if (conn->admin_user != True) {
1956 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1957 lp_servicename(SNUM(conn)),conn->user));
1958 return ERROR_DOS(ERRDOS,ERRnoaccess);
1961 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
1962 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1963 return ERROR_DOS(ERRSRV,ERRerror);
1968 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1970 /* Unknown1 24 NULL bytes*/
1971 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1972 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1973 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1975 /* Default Soft Quota 8 bytes */
1976 SBIG_UINT(pdata,24,quotas.softlim);
1978 /* Default Hard Quota 8 bytes */
1979 SBIG_UINT(pdata,32,quotas.hardlim);
1981 /* Quota flag 2 bytes */
1982 SSVAL(pdata,40,quotas.qflags);
1984 /* Unknown3 6 NULL bytes */
1990 #endif /* HAVE_SYS_QUOTAS */
1991 case SMB_FS_OBJECTID_INFORMATION:
1996 * Query the version and capabilities of the CIFS UNIX extensions
2000 case SMB_QUERY_CIFS_UNIX_INFO:
2001 if (!lp_unix_extensions())
2002 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2004 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2005 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2006 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2009 case SMB_MAC_QUERY_FS_INFO:
2011 * Thursby MAC extension... ONLY on NTFS filesystems
2012 * once we do streams then we don't need this
2014 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2016 SIVAL(pdata,84,0x100); /* Don't support mac... */
2021 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2025 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2027 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2032 #ifdef HAVE_SYS_QUOTAS
2033 /****************************************************************************
2034 Reply to a TRANS2_SETFSINFO (set filesystem info).
2035 ****************************************************************************/
2037 static int call_trans2setfsinfo(connection_struct *conn,
2038 char *inbuf, char *outbuf, int length, int bufsize,
2039 char **pparams, int total_params, char **ppdata, int total_data)
2041 char *pdata = *ppdata;
2042 char *params = *pparams;
2043 files_struct *fsp = NULL;
2046 SMB_NTQUOTA_STRUCT quotas;
2048 ZERO_STRUCT(quotas);
2050 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2053 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
2054 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2055 lp_servicename(SNUM(conn)),conn->user));
2056 return ERROR_DOS(ERRSRV,ERRaccess);
2060 if (total_params < 4) {
2061 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2063 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2066 fsp = file_fsp(params,0);
2068 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2069 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2070 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2073 info_level = SVAL(params,2);
2075 switch(info_level) {
2076 case SMB_FS_QUOTA_INFORMATION:
2077 /* note: normaly there're 48 bytes,
2078 * but we didn't use the last 6 bytes for now
2081 if (total_data < 42) {
2082 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2084 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2087 /* unknown_1 24 NULL bytes in pdata*/
2089 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2090 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2091 #ifdef LARGE_SMB_OFF_T
2092 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2093 #else /* LARGE_SMB_OFF_T */
2094 if ((IVAL(pdata,28) != 0)&&
2095 ((quotas.softlim != 0xFFFFFFFF)||
2096 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2097 /* more than 32 bits? */
2098 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2100 #endif /* LARGE_SMB_OFF_T */
2102 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2103 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2104 #ifdef LARGE_SMB_OFF_T
2105 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2106 #else /* LARGE_SMB_OFF_T */
2107 if ((IVAL(pdata,36) != 0)&&
2108 ((quotas.hardlim != 0xFFFFFFFF)||
2109 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2110 /* more than 32 bits? */
2111 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2113 #endif /* LARGE_SMB_OFF_T */
2115 /* quota_flags 2 bytes **/
2116 quotas.qflags = SVAL(pdata,40);
2118 /* unknown_2 6 NULL bytes follow*/
2120 /* now set the quotas */
2121 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2122 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2123 return ERROR_DOS(ERRSRV,ERRerror);
2128 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2130 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2135 * sending this reply works fine,
2136 * but I'm not sure it's the same
2137 * like windows do...
2140 outsize = set_message(outbuf,10,0,True);
2144 #endif /* HAVE_SYS_QUOTAS */
2146 /****************************************************************************
2147 * Utility function to set bad path error.
2148 ****************************************************************************/
2150 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2152 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2153 err, (int)bad_path ));
2157 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2159 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2162 return UNIXERROR(def_class,def_code);
2165 /****************************************************************************
2166 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2167 file name or file id).
2168 ****************************************************************************/
2170 static int call_trans2qfilepathinfo(connection_struct *conn,
2171 char *inbuf, char *outbuf, int length,
2173 char **pparams, int total_params, char **ppdata, int total_data)
2175 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2176 char *params = *pparams;
2177 char *pdata = *ppdata;
2178 uint16 tran_call = SVAL(inbuf, smb_setup0);
2181 SMB_OFF_T file_size=0;
2182 SMB_BIG_UINT allocation_size=0;
2183 unsigned int data_size;
2184 unsigned int param_size = 2;
2185 SMB_STRUCT_STAT sbuf;
2186 pstring fname, dos_fname;
2191 BOOL bad_path = False;
2192 BOOL delete_pending = False;
2195 files_struct *fsp = NULL;
2196 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2199 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2201 if (tran_call == TRANSACT2_QFILEINFO) {
2202 if (total_params < 4)
2203 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2205 fsp = file_fsp(params,0);
2206 info_level = SVAL(params,2);
2208 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2210 if(fsp && (fsp->fake_file_handle)) {
2212 * This is actually for the QUOTA_FAKE_FILE --metze
2215 pstrcpy(fname, fsp->fsp_name);
2216 unix_convert(fname,conn,0,&bad_path,&sbuf);
2217 if (!check_name(fname,conn)) {
2218 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
2219 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2222 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2224 * This is actually a QFILEINFO on a directory
2225 * handle (returned from an NT SMB). NT5.0 seems
2226 * to do this call. JRA.
2228 pstrcpy(fname, fsp->fsp_name);
2229 unix_convert(fname,conn,0,&bad_path,&sbuf);
2230 if (!check_name(fname,conn)) {
2231 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2232 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2235 if (INFO_LEVEL_IS_UNIX(info_level)) {
2236 /* Always do lstat for UNIX calls. */
2237 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2238 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2239 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2241 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
2242 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2243 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2246 delete_pending = fsp->directory_delete_on_close;
2249 * Original code - this is an open file.
2251 CHECK_FSP(fsp,conn);
2253 pstrcpy(fname, fsp->fsp_name);
2254 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2255 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2256 return(UNIXERROR(ERRDOS,ERRbadfid));
2258 pos = fsp->position_information;
2259 delete_pending = fsp->delete_on_close;
2260 desired_access = fsp->desired_access;
2263 NTSTATUS status = NT_STATUS_OK;
2266 if (total_params < 6)
2267 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2269 info_level = SVAL(params,0);
2271 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2273 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2274 if (!NT_STATUS_IS_OK(status)) {
2275 return ERROR_NT(status);
2278 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2280 unix_convert(fname,conn,0,&bad_path,&sbuf);
2281 if (!check_name(fname,conn)) {
2282 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2283 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2286 if (INFO_LEVEL_IS_UNIX(info_level)) {
2287 /* Always do lstat for UNIX calls. */
2288 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2289 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2290 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2292 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2293 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2294 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2298 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2299 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2301 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2302 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2304 p = strrchr_m(fname,'/');
2310 mode = dos_mode(conn,fname,&sbuf);
2312 mode = FILE_ATTRIBUTE_NORMAL;
2314 fullpathname = fname;
2315 file_size = get_file_size(sbuf);
2316 allocation_size = get_allocation_size(fsp,&sbuf);
2320 params = Realloc(*pparams,2);
2322 return ERROR_DOS(ERRDOS,ERRnomem);
2324 memset((char *)params,'\0',2);
2325 data_size = max_data_bytes + 1024;
2326 pdata = Realloc(*ppdata, data_size);
2327 if ( pdata == NULL )
2328 return ERROR_DOS(ERRDOS,ERRnomem);
2331 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2332 /* uggh, EAs for OS2 */
2333 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2334 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2337 memset((char *)pdata,'\0',data_size);
2339 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2341 if (lp_dos_filetime_resolution(SNUM(conn))) {
2343 sbuf.st_atime &= ~1;
2344 sbuf.st_mtime &= ~1;
2345 sbuf.st_mtime &= ~1;
2348 /* NT expects the name to be in an exact form of the *full*
2349 filename. See the trans2 torture test */
2350 if (strequal(base_name,".")) {
2351 pstrcpy(dos_fname, "\\");
2353 pstr_sprintf(dos_fname, "\\%s", fname);
2354 string_replace(dos_fname, '/', '\\');
2357 switch (info_level) {
2358 case SMB_INFO_STANDARD:
2359 case SMB_INFO_QUERY_EA_SIZE:
2360 data_size = (info_level==1?22:26);
2361 put_dos_date2(pdata,l1_fdateCreation,c_time);
2362 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2363 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2364 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2365 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2366 SSVAL(pdata,l1_attrFile,mode);
2367 SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */
2370 case SMB_INFO_IS_NAME_VALID:
2371 if (tran_call == TRANSACT2_QFILEINFO) {
2372 /* os/2 needs this ? really ?*/
2373 return ERROR_DOS(ERRDOS,ERRbadfunc);
2379 case SMB_INFO_QUERY_EAS_FROM_LIST:
2381 put_dos_date2(pdata,0,c_time);
2382 put_dos_date2(pdata,4,sbuf.st_atime);
2383 put_dos_date2(pdata,8,sbuf.st_mtime);
2384 SIVAL(pdata,12,(uint32)file_size);
2385 SIVAL(pdata,16,(uint32)allocation_size);
2386 SIVAL(pdata,20,mode);
2389 case SMB_INFO_QUERY_ALL_EAS:
2390 /* We have data_size bytes to put EA's into. */
2391 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2394 case SMB_FILE_BASIC_INFORMATION:
2395 case SMB_QUERY_FILE_BASIC_INFO:
2397 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
2398 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2403 put_long_date(pdata,c_time);
2404 put_long_date(pdata+8,sbuf.st_atime);
2405 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2406 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2407 SIVAL(pdata,32,mode);
2409 DEBUG(5,("SMB_QFBI - "));
2411 time_t create_time = c_time;
2412 DEBUG(5,("create: %s ", ctime(&create_time)));
2414 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2415 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2416 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2417 DEBUG(5,("mode: %x\n", mode));
2421 case SMB_FILE_STANDARD_INFORMATION:
2422 case SMB_QUERY_FILE_STANDARD_INFO:
2425 SOFF_T(pdata,0,allocation_size);
2426 SOFF_T(pdata,8,file_size);
2427 if (delete_pending & sbuf.st_nlink)
2428 SIVAL(pdata,16,sbuf.st_nlink - 1);
2430 SIVAL(pdata,16,sbuf.st_nlink);
2432 SCVAL(pdata,21,(mode&aDIR)?1:0);
2435 case SMB_FILE_EA_INFORMATION:
2436 case SMB_QUERY_FILE_EA_INFO:
2438 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2440 SIVAL(pdata,0,ea_size);
2444 /* Get the 8.3 name - used if NT SMB was negotiated. */
2445 case SMB_QUERY_FILE_ALT_NAME_INFO:
2446 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2450 pstrcpy(short_name,base_name);
2451 /* Mangle if not already 8.3 */
2452 if(!mangle_is_8_3(short_name, True)) {
2453 mangle_map(short_name,True,True,SNUM(conn));
2455 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2456 data_size = 4 + len;
2461 case SMB_QUERY_FILE_NAME_INFO:
2463 this must be *exactly* right for ACLs on mapped drives to work
2465 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2466 data_size = 4 + len;
2470 case SMB_FILE_ALLOCATION_INFORMATION:
2471 case SMB_QUERY_FILE_ALLOCATION_INFO:
2473 SOFF_T(pdata,0,allocation_size);
2476 case SMB_FILE_END_OF_FILE_INFORMATION:
2477 case SMB_QUERY_FILE_END_OF_FILEINFO:
2479 SOFF_T(pdata,0,file_size);
2482 case SMB_QUERY_FILE_ALL_INFO:
2483 case SMB_FILE_ALL_INFORMATION:
2484 put_long_date(pdata,c_time);
2485 put_long_date(pdata+8,sbuf.st_atime);
2486 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2487 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2488 SIVAL(pdata,32,mode);
2490 SOFF_T(pdata,0,allocation_size);
2491 SOFF_T(pdata,8,file_size);
2492 if (delete_pending && sbuf.st_nlink)
2493 SIVAL(pdata,16,sbuf.st_nlink - 1);
2495 SIVAL(pdata,16,sbuf.st_nlink);
2496 SCVAL(pdata,20,delete_pending);
2497 SCVAL(pdata,21,(mode&aDIR)?1:0);
2499 pdata += 4; /* EA info */
2500 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2503 data_size = PTR_DIFF(pdata,(*ppdata));
2506 case SMB_FILE_INTERNAL_INFORMATION:
2507 /* This should be an index number - looks like
2510 I think this causes us to fail the IFSKIT
2511 BasicFileInformationTest. -tpot */
2513 SIVAL(pdata,0,sbuf.st_dev);
2514 SIVAL(pdata,4,sbuf.st_ino);
2518 case SMB_FILE_ACCESS_INFORMATION:
2519 SIVAL(pdata,0,desired_access);
2523 case SMB_FILE_NAME_INFORMATION:
2524 /* Pathname with leading '\'. */
2527 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2528 SIVAL(pdata,0,byte_len);
2529 data_size = 4 + byte_len;
2533 case SMB_FILE_DISPOSITION_INFORMATION:
2535 SCVAL(pdata,0,delete_pending);
2538 case SMB_FILE_POSITION_INFORMATION:
2540 SOFF_T(pdata,0,pos);
2543 case SMB_FILE_MODE_INFORMATION:
2544 SIVAL(pdata,0,mode);
2548 case SMB_FILE_ALIGNMENT_INFORMATION:
2549 SIVAL(pdata,0,0); /* No alignment needed. */
2555 * NT4 server just returns "invalid query" to this - if we try to answer
2556 * it then NTws gets a BSOD! (tridge).
2557 * W2K seems to want this. JRA.
2559 case SMB_QUERY_FILE_STREAM_INFO:
2561 case SMB_FILE_STREAM_INFORMATION:
2565 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2566 SIVAL(pdata,0,0); /* ??? */
2567 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2568 SOFF_T(pdata,8,file_size);
2569 SIVAL(pdata,16,allocation_size);
2570 SIVAL(pdata,20,0); /* ??? */
2571 data_size = 24 + byte_len;
2575 case SMB_QUERY_COMPRESSION_INFO:
2576 case SMB_FILE_COMPRESSION_INFORMATION:
2577 SOFF_T(pdata,0,file_size);
2578 SIVAL(pdata,8,0); /* ??? */
2579 SIVAL(pdata,12,0); /* ??? */
2583 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2584 put_long_date(pdata,c_time);
2585 put_long_date(pdata+8,sbuf.st_atime);
2586 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2587 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2588 SIVAL(pdata,32,allocation_size);
2589 SOFF_T(pdata,40,file_size);
2590 SIVAL(pdata,48,mode);
2591 SIVAL(pdata,52,0); /* ??? */
2595 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2596 SIVAL(pdata,0,mode);
2602 * CIFS UNIX Extensions.
2605 case SMB_QUERY_FILE_UNIX_BASIC:
2607 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2609 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2612 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2615 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2616 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2617 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2620 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2624 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2628 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2631 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2635 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2639 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2642 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2646 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2649 data_size = PTR_DIFF(pdata,(*ppdata));
2653 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2655 for (i=0; i<100; i++)
2656 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2662 case SMB_QUERY_FILE_UNIX_LINK:
2667 if(!S_ISLNK(sbuf.st_mode))
2668 return(UNIXERROR(ERRSRV,ERRbadlink));
2670 return(UNIXERROR(ERRDOS,ERRbadlink));
2672 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2674 return(UNIXERROR(ERRDOS,ERRnoaccess));
2676 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2678 data_size = PTR_DIFF(pdata,(*ppdata));
2684 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2687 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2692 /****************************************************************************
2693 Deal with the internal needs of setting the delete on close flag. Note that
2694 as the tdb locking is recursive, it is safe to call this from within
2695 open_file_shared. JRA.
2696 ****************************************************************************/
2698 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2701 * Only allow delete on close for writable shares.
2704 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2705 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2707 return NT_STATUS_ACCESS_DENIED;
2710 * Only allow delete on close for files/directories opened with delete intent.
2713 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2714 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2716 return NT_STATUS_ACCESS_DENIED;
2719 if(fsp->is_directory) {
2720 fsp->directory_delete_on_close = delete_on_close;
2721 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2722 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2724 fsp->delete_on_close = delete_on_close;
2725 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2726 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2729 return NT_STATUS_OK;
2732 /****************************************************************************
2733 Sets the delete on close flag over all share modes on this file.
2734 Modify the share mode entry for all files open
2735 on this device and inode to tell other smbds we have
2736 changed the delete on close flag. This will be noticed
2737 in the close code, the last closer will delete the file
2739 ****************************************************************************/
2741 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2743 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2744 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2746 if (fsp->is_directory || fsp->is_stat)
2747 return NT_STATUS_OK;
2749 if (lock_share_entry_fsp(fsp) == False)
2750 return NT_STATUS_ACCESS_DENIED;
2752 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2753 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2755 unlock_share_entry_fsp(fsp);
2756 return NT_STATUS_ACCESS_DENIED;
2759 unlock_share_entry_fsp(fsp);
2760 return NT_STATUS_OK;
2763 /****************************************************************************
2764 Returns true if this pathname is within the share, and thus safe.
2765 ****************************************************************************/
2767 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2770 char resolved_name[PATH_MAX+1];
2772 pstring resolved_name;
2774 fstring last_component;
2778 BOOL bad_path = False;
2779 SMB_STRUCT_STAT sbuf;
2781 pstrcpy(link_dest, link_dest_in);
2782 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2784 /* Store the UNIX converted path. */
2785 pstrcpy(link_dest_out, link_dest);
2787 p = strrchr(link_dest, '/');
2789 fstrcpy(last_component, p+1);
2792 fstrcpy(last_component, link_dest);
2793 pstrcpy(link_dest, "./");
2796 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2799 pstrcpy(link_dest, resolved_name);
2800 pstrcat(link_dest, "/");
2801 pstrcat(link_dest, last_component);
2803 if (*link_dest != '/') {
2804 /* Relative path. */
2805 pstrcpy(link_test, conn->connectpath);
2806 pstrcat(link_test, "/");
2807 pstrcat(link_test, link_dest);
2809 pstrcpy(link_test, link_dest);
2813 * Check if the link is within the share.
2816 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2823 /****************************************************************************
2824 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2826 ****************************************************************************/
2828 NTSTATUS hardlink_internals(connection_struct *conn, char *name, char *newname)
2830 BOOL bad_path_src = False;
2831 BOOL bad_path_dest = False;
2832 SMB_STRUCT_STAT sbuf1, sbuf2;
2834 pstring last_component_src;
2835 pstring last_component_dest;
2836 NTSTATUS status = NT_STATUS_OK;
2842 if (ms_has_wild(name) || ms_has_wild(newname)) {
2843 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2846 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
2847 if (!rc && bad_path_src) {
2848 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2851 /* Quick check for "." and ".." */
2852 if (last_component_src[0] == '.') {
2853 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
2854 return NT_STATUS_OBJECT_NAME_INVALID;
2858 /* source must already exist. */
2859 if (!VALID_STAT(sbuf1)) {
2860 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2863 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
2864 if (!rcdest && bad_path_dest) {
2865 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2868 /* Quick check for "." and ".." */
2869 if (last_component_dest[0] == '.') {
2870 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
2871 return NT_STATUS_OBJECT_NAME_INVALID;
2875 /* Disallow if already exists. */
2876 if (VALID_STAT(sbuf2)) {
2877 return NT_STATUS_OBJECT_NAME_COLLISION;
2880 /* No links from a directory. */
2881 if (S_ISDIR(sbuf1.st_mode)) {
2882 return NT_STATUS_FILE_IS_A_DIRECTORY;
2885 if (ensure_link_is_safe(conn, newname, newname) != 0)
2886 return NT_STATUS_ACCESS_DENIED;
2888 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", name, newname ));
2890 if (SMB_VFS_LINK(conn,name,newname) != 0) {
2891 status = map_nt_error_from_unix(errno);
2892 DEBUG(3,("hardlink_internals: Error %s link %s -> %s\n",
2893 nt_errstr(status), name,newname));
2899 /****************************************************************************
2900 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2901 ****************************************************************************/
2903 static int call_trans2setfilepathinfo(connection_struct *conn,
2904 char *inbuf, char *outbuf, int length, int bufsize,
2905 char **pparams, int total_params, char **ppdata, int total_data)
2907 char *params = *pparams;
2908 char *pdata = *ppdata;
2909 uint16 tran_call = SVAL(inbuf, smb_setup0);
2914 SMB_STRUCT_STAT sbuf;
2917 BOOL bad_path = False;
2918 files_struct *fsp = NULL;
2919 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2920 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2921 mode_t unixmode = 0;
2922 NTSTATUS status = NT_STATUS_OK;
2925 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2927 if (tran_call == TRANSACT2_SETFILEINFO) {
2928 if (total_params < 4)
2929 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2931 fsp = file_fsp(params,0);
2932 info_level = SVAL(params,2);
2934 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2936 * This is actually a SETFILEINFO on a directory
2937 * handle (returned from an NT SMB). NT5.0 seems
2938 * to do this call. JRA.
2940 pstrcpy(fname, fsp->fsp_name);
2941 unix_convert(fname,conn,0,&bad_path,&sbuf);
2942 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2943 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2944 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2946 } else if (fsp && fsp->print_file) {
2948 * Doing a DELETE_ON_CLOSE should cancel a print job.
2950 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2951 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2953 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2956 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2959 return (UNIXERROR(ERRDOS,ERRbadpath));
2962 * Original code - this is an open file.
2964 CHECK_FSP(fsp,conn);
2966 pstrcpy(fname, fsp->fsp_name);
2969 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2970 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2971 return(UNIXERROR(ERRDOS,ERRbadfid));
2976 if (total_params < 6)
2977 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2979 info_level = SVAL(params,0);
2980 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2981 if (!NT_STATUS_IS_OK(status)) {
2982 return ERROR_NT(status);
2984 unix_convert(fname,conn,0,&bad_path,&sbuf);
2987 * For CIFS UNIX extensions the target name may not exist.
2990 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2991 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2992 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2995 if(!check_name(fname, conn)) {
2996 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3001 if (!CAN_WRITE(conn))
3002 return ERROR_DOS(ERRSRV,ERRaccess);
3004 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3005 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3007 if (VALID_STAT(sbuf))
3008 unixmode = sbuf.st_mode;
3010 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3011 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3013 /* Realloc the parameter and data sizes */
3014 params = Realloc(*pparams,2);
3016 return ERROR_DOS(ERRDOS,ERRnomem);
3022 /* the pending modtime overrides the current modtime */
3023 sbuf.st_mtime = fsp->pending_modtime;
3026 size = get_file_size(sbuf);
3027 tvs.modtime = sbuf.st_mtime;
3028 tvs.actime = sbuf.st_atime;
3029 dosmode = dos_mode(conn,fname,&sbuf);
3030 unixmode = sbuf.st_mode;
3032 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3033 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3035 switch (info_level) {
3036 case SMB_INFO_STANDARD:
3038 if (total_data < 12)
3039 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3042 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3044 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3048 case SMB_INFO_SET_EA:
3049 status = set_ea(conn, fsp, fname, pdata, total_data);
3050 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3051 return ERROR_NT(status);
3054 /* XXXX um, i don't think this is right.
3055 it's also not in the cifs6.txt spec.
3057 case SMB_INFO_QUERY_EAS_FROM_LIST:
3058 if (total_data < 28)
3059 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3061 tvs.actime = make_unix_date2(pdata+8);
3062 tvs.modtime = make_unix_date2(pdata+12);
3063 size = IVAL(pdata,16);
3064 dosmode = IVAL(pdata,24);
3067 /* XXXX nor this. not in cifs6.txt, either. */
3068 case SMB_INFO_QUERY_ALL_EAS:
3069 if (total_data < 28)
3070 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3072 tvs.actime = make_unix_date2(pdata+8);
3073 tvs.modtime = make_unix_date2(pdata+12);
3074 size = IVAL(pdata,16);
3075 dosmode = IVAL(pdata,24);
3078 case SMB_SET_FILE_BASIC_INFO:
3079 case SMB_FILE_BASIC_INFORMATION:
3081 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3083 time_t changed_time;
3085 if (total_data < 36)
3086 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3088 /* Ignore create time at offset pdata. */
3091 tvs.actime = interpret_long_date(pdata+8);
3093 write_time = interpret_long_date(pdata+16);
3094 changed_time = interpret_long_date(pdata+24);
3096 tvs.modtime = MIN(write_time, changed_time);
3098 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3099 tvs.modtime = write_time;
3101 /* Prefer a defined time to an undefined one. */
3102 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3103 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3104 ? changed_time : write_time);
3107 dosmode = IVAL(pdata,32);
3111 case SMB_FILE_ALLOCATION_INFORMATION:
3112 case SMB_SET_FILE_ALLOCATION_INFO:
3115 SMB_BIG_UINT allocation_size;
3118 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3120 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3121 #ifdef LARGE_SMB_OFF_T
3122 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3123 #else /* LARGE_SMB_OFF_T */
3124 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3125 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3126 #endif /* LARGE_SMB_OFF_T */
3127 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3128 fname, (double)allocation_size ));
3130 if (allocation_size)
3131 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3133 if(allocation_size != get_file_size(sbuf)) {
3134 SMB_STRUCT_STAT new_sbuf;
3136 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3137 fname, (double)allocation_size ));
3140 files_struct *new_fsp = NULL;
3141 int access_mode = 0;
3144 if(global_oplock_break) {
3145 /* Queue this file modify as we are the process of an oplock break. */
3147 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3148 DEBUGADD(2,( "in oplock break state.\n"));
3150 push_oplock_pending_smb_message(inbuf, length);
3154 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3155 SET_OPEN_MODE(DOS_OPEN_RDWR),
3156 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3157 FILE_ATTRIBUTE_NORMAL,
3158 0, &access_mode, &action);
3160 if (new_fsp == NULL)
3161 return(UNIXERROR(ERRDOS,ERRbadpath));
3162 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3163 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3164 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3165 new_fsp->fnum, strerror(errno)));
3168 close_file(new_fsp,True);
3170 ret = vfs_allocate_file_space(fsp, allocation_size);
3171 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3172 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3173 fsp->fnum, strerror(errno)));
3178 return ERROR_NT(NT_STATUS_DISK_FULL);
3180 /* Allocate can truncate size... */
3181 size = get_file_size(new_sbuf);
3187 case SMB_FILE_END_OF_FILE_INFORMATION:
3188 case SMB_SET_FILE_END_OF_FILE_INFO:
3191 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3193 size = IVAL(pdata,0);
3194 #ifdef LARGE_SMB_OFF_T
3195 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3196 #else /* LARGE_SMB_OFF_T */
3197 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3198 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3199 #endif /* LARGE_SMB_OFF_T */
3200 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3204 case SMB_FILE_DISPOSITION_INFORMATION:
3205 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3207 BOOL delete_on_close;
3210 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3212 delete_on_close = (CVAL(pdata,0) ? True : False);
3214 /* Just ignore this set on a path. */
3215 if (tran_call != TRANSACT2_SETFILEINFO)
3219 return(UNIXERROR(ERRDOS,ERRbadfid));
3221 status = set_delete_on_close_internal(fsp, delete_on_close);
3223 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3224 return ERROR_NT(status);
3226 /* The set is across all open files on this dev/inode pair. */
3227 status =set_delete_on_close_over_all(fsp, delete_on_close);
3228 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3229 return ERROR_NT(status);
3234 case SMB_FILE_POSITION_INFORMATION:
3236 SMB_BIG_UINT position_information;
3239 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3241 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3242 #ifdef LARGE_SMB_OFF_T
3243 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3244 #else /* LARGE_SMB_OFF_T */
3245 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3246 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3247 #endif /* LARGE_SMB_OFF_T */
3248 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3249 fname, (double)position_information ));
3251 fsp->position_information = position_information;
3256 * CIFS UNIX extensions.
3259 case SMB_SET_FILE_UNIX_BASIC:
3261 uint32 raw_unixmode;
3263 if (total_data < 100)
3264 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3266 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3267 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3268 size=IVAL(pdata,0); /* first 8 Bytes are size */
3269 #ifdef LARGE_SMB_OFF_T
3270 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3271 #else /* LARGE_SMB_OFF_T */
3272 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3273 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3274 #endif /* LARGE_SMB_OFF_T */
3276 pdata+=24; /* ctime & st_blocks are not changed */
3277 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3278 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3280 set_owner = (uid_t)IVAL(pdata,0);
3282 set_grp = (gid_t)IVAL(pdata,0);
3284 raw_unixmode = IVAL(pdata,28);
3285 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3286 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3288 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3289 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3290 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3292 if (!VALID_STAT(sbuf)) {
3295 * The only valid use of this is to create character and block
3296 * devices, and named pipes. This is deprecated (IMHO) and
3297 * a new info level should be used for mknod. JRA.
3300 #if !defined(HAVE_MAKEDEV_FN)
3301 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3302 #else /* HAVE_MAKEDEV_FN */
3303 uint32 file_type = IVAL(pdata,0);
3304 uint32 dev_major = IVAL(pdata,4);
3305 uint32 dev_minor = IVAL(pdata,12);
3307 uid_t myuid = geteuid();
3308 gid_t mygid = getegid();
3311 if (tran_call == TRANSACT2_SETFILEINFO)
3312 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3314 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3315 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3317 dev = makedev(dev_major, dev_minor);
3319 /* We can only create as the owner/group we are. */
3321 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3322 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3323 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3324 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3326 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
3327 file_type != UNIX_TYPE_FIFO)
3328 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3330 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3331 0%o for file %s\n", (double)dev, unixmode, fname ));
3333 /* Ok - do the mknod. */
3334 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
3335 return(UNIXERROR(ERRDOS,ERRnoaccess));
3337 inherit_access_acl(conn, fname, unixmode);
3340 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3342 #endif /* HAVE_MAKEDEV_FN */
3347 * Deal with the UNIX specific mode set.
3350 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3351 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3352 (unsigned int)unixmode, fname ));
3353 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3354 return(UNIXERROR(ERRDOS,ERRnoaccess));
3358 * Deal with the UNIX specific uid set.
3361 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3362 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3363 (unsigned int)set_owner, fname ));
3364 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3365 return(UNIXERROR(ERRDOS,ERRnoaccess));
3369 * Deal with the UNIX specific gid set.
3372 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3373 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3374 (unsigned int)set_owner, fname ));
3375 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3376 return(UNIXERROR(ERRDOS,ERRnoaccess));
3381 case SMB_SET_FILE_UNIX_LINK:
3384 /* Set a symbolic link. */
3385 /* Don't allow this if follow links is false. */
3387 if (!lp_symlinks(SNUM(conn)))
3388 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3390 srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
3391 if (!NT_STATUS_IS_OK(status)) {
3392 return ERROR_NT(status);
3395 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
3396 return(UNIXERROR(ERRDOS,ERRnoaccess));
3398 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3399 fname, link_dest ));
3401 if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
3402 return(UNIXERROR(ERRDOS,ERRnoaccess));
3404 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3408 case SMB_SET_FILE_UNIX_HLINK:
3412 /* Set a hard link. */
3413 srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 return ERROR_NT(status);
3418 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3419 fname, link_dest ));
3421 status = hardlink_internals(conn, fname, link_dest);
3422 if (!NT_STATUS_IS_OK(status)) {
3423 return ERROR_NT(status);
3427 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3431 case SMB_FILE_RENAME_INFORMATION:
3440 if (total_data < 12)
3441 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3443 overwrite = (CVAL(pdata,0) ? True : False);
3444 root_fid = IVAL(pdata,4);
3445 len = IVAL(pdata,8);
3446 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3447 if (!NT_STATUS_IS_OK(status)) {
3448 return ERROR_NT(status);
3451 /* Check the new name has no '/' characters. */
3452 if (strchr_m(newname, '/'))
3453 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3455 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3457 /* Create the base directory. */
3458 pstrcpy(base_name, fname);
3459 p = strrchr_m(base_name, '/');
3462 /* Append the new name. */
3463 pstrcat(base_name, "/");
3464 pstrcat(base_name, newname);
3467 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3468 fsp->fnum, fsp->fsp_name, base_name ));
3469 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3471 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3473 status = rename_internals(conn, fname, base_name, 0, overwrite);
3475 if (!NT_STATUS_IS_OK(status)) {
3476 return ERROR_NT(status);
3478 process_pending_change_notify_queue((time_t)0);
3480 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3484 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3487 /* get some defaults (no modifications) if any info is zero or -1. */
3488 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3489 tvs.actime = sbuf.st_atime;
3491 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3492 tvs.modtime = sbuf.st_mtime;
3494 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3495 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3496 DEBUG(6,("size: %.0f ", (double)size));
3499 if (S_ISDIR(sbuf.st_mode))
3505 DEBUG(6,("dosmode: %x\n" , dosmode));
3507 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3508 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3509 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3510 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3513 * Only do this test if we are not explicitly
3514 * changing the size of a file.
3517 size = get_file_size(sbuf);
3521 * Try and set the times, size and mode of this file -
3522 * if they are different from the current values
3524 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3527 * This was a setfileinfo on an open file.
3528 * NT does this a lot. It's actually pointless
3529 * setting the time here, as it will be overwritten
3530 * on the next write, so we save the request
3531 * away and will set it on file close. JRA.
3534 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3535 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3536 fsp->pending_modtime = tvs.modtime;
3541 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3543 if(file_utime(conn, fname, &tvs)!=0)
3544 return(UNIXERROR(ERRDOS,ERRnoaccess));
3548 /* check the mode isn't different, before changing it */
3549 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3551 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3553 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3554 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3555 return(UNIXERROR(ERRDOS,ERRnoaccess));
3559 if (size != get_file_size(sbuf)) {
3563 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3564 fname, (double)size ));
3567 files_struct *new_fsp = NULL;
3568 int access_mode = 0;
3571 if(global_oplock_break) {
3572 /* Queue this file modify as we are the process of an oplock break. */
3574 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3575 DEBUGADD(2,( "in oplock break state.\n"));
3577 push_oplock_pending_smb_message(inbuf, length);
3581 new_fsp = open_file_shared(conn, fname, &sbuf,
3582 SET_OPEN_MODE(DOS_OPEN_RDWR),
3583 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3584 FILE_ATTRIBUTE_NORMAL,
3585 0, &access_mode, &action);
3587 if (new_fsp == NULL)
3588 return(UNIXERROR(ERRDOS,ERRbadpath));
3589 ret = vfs_set_filelen(new_fsp, size);
3590 close_file(new_fsp,True);
3592 ret = vfs_set_filelen(fsp, size);
3596 return (UNIXERROR(ERRHRD,ERRdiskfull));
3600 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3605 /****************************************************************************
3606 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3607 ****************************************************************************/
3609 static int call_trans2mkdir(connection_struct *conn,
3610 char *inbuf, char *outbuf, int length, int bufsize,
3611 char **pparams, int total_params, char **ppdata, int total_data)
3613 char *params = *pparams;
3616 SMB_STRUCT_STAT sbuf;
3617 BOOL bad_path = False;
3618 NTSTATUS status = NT_STATUS_OK;
3620 if (!CAN_WRITE(conn))
3621 return ERROR_DOS(ERRSRV,ERRaccess);
3623 if (total_params < 4)
3624 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3626 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
3627 if (!NT_STATUS_IS_OK(status)) {
3628 return ERROR_NT(status);
3631 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3633 unix_convert(directory,conn,0,&bad_path,&sbuf);
3634 if (check_name(directory,conn))
3635 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3638 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3639 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3642 /* Realloc the parameter and data sizes */
3643 params = Realloc(*pparams,2);
3645 return ERROR_DOS(ERRDOS,ERRnomem);
3650 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3655 /****************************************************************************
3656 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3657 We don't actually do this - we just send a null response.
3658 ****************************************************************************/
3660 static int call_trans2findnotifyfirst(connection_struct *conn,
3661 char *inbuf, char *outbuf, int length, int bufsize,
3662 char **pparams, int total_params, char **ppdata, int total_data)
3664 static uint16 fnf_handle = 257;
3665 char *params = *pparams;
3668 if (total_params < 6)
3669 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3671 info_level = SVAL(params,4);
3672 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3674 switch (info_level) {
3679 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3682 /* Realloc the parameter and data sizes */
3683 params = Realloc(*pparams,6);
3685 return ERROR_DOS(ERRDOS,ERRnomem);
3688 SSVAL(params,0,fnf_handle);
3689 SSVAL(params,2,0); /* No changes */
3690 SSVAL(params,4,0); /* No EA errors */
3697 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3702 /****************************************************************************
3703 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3704 changes). Currently this does nothing.
3705 ****************************************************************************/
3707 static int call_trans2findnotifynext(connection_struct *conn,
3708 char *inbuf, char *outbuf, int length, int bufsize,
3709 char **pparams, int total_params, char **ppdata, int total_data)
3711 char *params = *pparams;
3713 DEBUG(3,("call_trans2findnotifynext\n"));
3715 /* Realloc the parameter and data sizes */
3716 params = Realloc(*pparams,4);
3718 return ERROR_DOS(ERRDOS,ERRnomem);
3721 SSVAL(params,0,0); /* No changes */
3722 SSVAL(params,2,0); /* No EA errors */
3724 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3729 /****************************************************************************
3730 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3731 ****************************************************************************/
3733 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3734 char* outbuf, int length, int bufsize,
3735 char **pparams, int total_params, char **ppdata, int total_data)
3737 char *params = *pparams;
3740 int max_referral_level;
3742 DEBUG(10,("call_trans2getdfsreferral\n"));
3744 if (total_params < 2)
3745 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3747 max_referral_level = SVAL(params,0);
3749 if(!lp_host_msdfs())
3750 return ERROR_DOS(ERRDOS,ERRbadfunc);
3752 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
3753 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3754 return UNIXERROR(ERRDOS,ERRbadfile);
3756 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3757 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3762 #define LMCAT_SPL 0x53
3763 #define LMFUNC_GETJOBID 0x60
3765 /****************************************************************************
3766 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3767 ****************************************************************************/
3769 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3770 char* outbuf, int length, int bufsize,
3771 char **pparams, int total_params, char **ppdata, int total_data)
3773 char *pdata = *ppdata;
3774 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3776 /* check for an invalid fid before proceeding */
3779 return(ERROR_DOS(ERRDOS,ERRbadfid));
3781 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3782 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3783 pdata = Realloc(*ppdata, 32);
3785 return ERROR_DOS(ERRDOS,ERRnomem);
3788 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3789 CAN ACCEPT THIS IN UNICODE. JRA. */
3791 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3792 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3793 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3794 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3797 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3798 return ERROR_DOS(ERRSRV,ERRerror);
3802 /****************************************************************************
3803 Reply to a SMBfindclose (stop trans2 directory search).
3804 ****************************************************************************/
3806 int reply_findclose(connection_struct *conn,
3807 char *inbuf,char *outbuf,int length,int bufsize)
3810 int dptr_num=SVALS(inbuf,smb_vwv0);
3811 START_PROFILE(SMBfindclose);
3813 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3815 dptr_close(&dptr_num);
3817 outsize = set_message(outbuf,0,0,True);
3819 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3821 END_PROFILE(SMBfindclose);
3825 /****************************************************************************
3826 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3827 ****************************************************************************/
3829 int reply_findnclose(connection_struct *conn,
3830 char *inbuf,char *outbuf,int length,int bufsize)
3834 START_PROFILE(SMBfindnclose);
3836 dptr_num = SVAL(inbuf,smb_vwv0);
3838 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3840 /* We never give out valid handles for a
3841 findnotifyfirst - so any dptr_num is ok here.
3844 outsize = set_message(outbuf,0,0,True);
3846 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3848 END_PROFILE(SMBfindnclose);
3852 /****************************************************************************
3853 Reply to a SMBtranss2 - just ignore it!
3854 ****************************************************************************/
3856 int reply_transs2(connection_struct *conn,
3857 char *inbuf,char *outbuf,int length,int bufsize)
3859 START_PROFILE(SMBtranss2);
3860 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3861 END_PROFILE(SMBtranss2);
3865 /****************************************************************************
3866 Reply to a SMBtrans2.
3867 ****************************************************************************/
3869 int reply_trans2(connection_struct *conn,
3870 char *inbuf,char *outbuf,int length,int bufsize)
3873 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3874 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3876 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3877 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3878 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3879 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3880 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3881 int32 timeout = IVALS(inbuf,smb_timeout);
3883 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3884 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3885 char *params = NULL, *data = NULL;
3886 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3887 START_PROFILE(SMBtrans2);
3889 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3890 /* Queue this open message as we are the process of an
3893 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3894 DEBUGADD(2,( "in oplock break state.\n"));
3896 push_oplock_pending_smb_message(inbuf, length);
3897 END_PROFILE(SMBtrans2);
3901 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3902 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3903 END_PROFILE(SMBtrans2);
3904 return ERROR_DOS(ERRSRV,ERRaccess);
3907 outsize = set_message(outbuf,0,0,True);
3909 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3910 is so as a sanity check */
3913 * Need to have rc=0 for ioctl to get job id for OS/2.
3914 * Network printing will fail if function is not successful.
3915 * Similar function in reply.c will be used if protocol
3916 * is LANMAN1.0 instead of LM1.2X002.
3917 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3918 * outbuf doesn't have to be set(only job id is used).
3920 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3921 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3922 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3923 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3925 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3926 DEBUG(2,("Transaction is %d\n",tran_call));
3927 END_PROFILE(SMBtrans2);
3928 ERROR_DOS(ERRDOS,ERRinvalidparam);
3932 /* Allocate the space for the maximum needed parameters and data */
3933 if (total_params > 0)
3934 params = (char *)malloc(total_params);
3936 data = (char *)malloc(total_data);
3938 if ((total_params && !params) || (total_data && !data)) {
3939 DEBUG(2,("Out of memory in reply_trans2\n"));
3942 END_PROFILE(SMBtrans2);
3943 return ERROR_DOS(ERRDOS,ERRnomem);
3946 /* Copy the param and data bytes sent with this request into
3947 the params buffer */
3948 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3949 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3951 if (num_params > total_params || num_data > total_data)
3952 exit_server("invalid params in reply_trans2");
3955 unsigned int psoff = SVAL(inbuf, smb_psoff);
3956 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3958 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
3959 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
3961 memcpy( params, smb_base(inbuf) + psoff, num_params);
3964 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3965 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3967 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
3968 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
3970 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3973 srv_signing_trans_start(SVAL(inbuf,smb_mid));
3975 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3976 /* We need to send an interim response then receive the rest
3977 of the parameter/data bytes */
3978 outsize = set_message(outbuf,0,0,True);
3979 srv_signing_trans_stop();
3980 if (!send_smb(smbd_server_fd(),outbuf))
3981 exit_server("reply_trans2: send_smb failed.");
3983 while (num_data_sofar < total_data ||
3984 num_params_sofar < total_params) {
3986 unsigned int param_disp;
3987 unsigned int param_off;
3988 unsigned int data_disp;
3989 unsigned int data_off;
3991 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3994 * The sequence number for the trans reply is always
3995 * based on the last secondary received.
3998 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4001 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4002 outsize = set_message(outbuf,0,0,True);
4004 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4006 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4007 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4011 /* Revise total_params and total_data in case
4012 they have changed downwards */
4013 if (SVAL(inbuf, smb_tpscnt) < total_params)
4014 total_params = SVAL(inbuf, smb_tpscnt);
4015 if (SVAL(inbuf, smb_tdscnt) < total_data)
4016 total_data = SVAL(inbuf, smb_tdscnt);
4018 num_params = SVAL(inbuf,smb_spscnt);
4019 param_off = SVAL(inbuf, smb_spsoff);
4020 param_disp = SVAL(inbuf, smb_spsdisp);
4021 num_params_sofar += num_params;
4023 num_data = SVAL(inbuf, smb_sdscnt);
4024 data_off = SVAL(inbuf, smb_sdsoff);
4025 data_disp = SVAL(inbuf, smb_sdsdisp);
4026 num_data_sofar += num_data;
4028 if (num_params_sofar > total_params || num_data_sofar > total_data)
4032 if (param_disp + num_params >= total_params)
4034 if ((param_disp + num_params < param_disp) ||
4035 (param_disp + num_params < num_params))
4037 if (param_disp > total_params)
4039 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4040 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4042 if (params + param_disp < params)
4045 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4048 if (data_disp + num_data >= total_data)
4050 if ((data_disp + num_data < data_disp) ||
4051 (data_disp + num_data < num_data))
4053 if (data_disp > total_data)
4055 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4056 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4058 if (data + data_disp < data)
4061 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4066 if (Protocol >= PROTOCOL_NT1) {
4067 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4070 /* Now we must call the relevant TRANS2 function */
4072 case TRANSACT2_OPEN:
4073 START_PROFILE_NESTED(Trans2_open);
4074 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4075 ¶ms, total_params, &data, total_data);
4076 END_PROFILE_NESTED(Trans2_open);
4079 case TRANSACT2_FINDFIRST:
4080 START_PROFILE_NESTED(Trans2_findfirst);
4081 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4082 ¶ms, total_params, &data, total_data);
4083 END_PROFILE_NESTED(Trans2_findfirst);
4086 case TRANSACT2_FINDNEXT:
4087 START_PROFILE_NESTED(Trans2_findnext);
4088 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4089 ¶ms, total_params, &data, total_data);
4090 END_PROFILE_NESTED(Trans2_findnext);
4093 case TRANSACT2_QFSINFO:
4094 START_PROFILE_NESTED(Trans2_qfsinfo);
4095 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4096 ¶ms, total_params, &data, total_data);
4097 END_PROFILE_NESTED(Trans2_qfsinfo);
4100 #ifdef HAVE_SYS_QUOTAS
4101 case TRANSACT2_SETFSINFO:
4102 START_PROFILE_NESTED(Trans2_setfsinfo);
4103 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4104 ¶ms, total_params, &data, total_data);
4105 END_PROFILE_NESTED(Trans2_setfsinfo);
4108 case TRANSACT2_QPATHINFO:
4109 case TRANSACT2_QFILEINFO:
4110 START_PROFILE_NESTED(Trans2_qpathinfo);
4111 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4112 ¶ms, total_params, &data, total_data);
4113 END_PROFILE_NESTED(Trans2_qpathinfo);
4115 case TRANSACT2_SETPATHINFO:
4116 case TRANSACT2_SETFILEINFO:
4117 START_PROFILE_NESTED(Trans2_setpathinfo);
4118 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4119 ¶ms, total_params, &data, total_data);
4120 END_PROFILE_NESTED(Trans2_setpathinfo);
4123 case TRANSACT2_FINDNOTIFYFIRST:
4124 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4125 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4126 ¶ms, total_params, &data, total_data);
4127 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4130 case TRANSACT2_FINDNOTIFYNEXT:
4131 START_PROFILE_NESTED(Trans2_findnotifynext);
4132 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4133 ¶ms, total_params, &data, total_data);
4134 END_PROFILE_NESTED(Trans2_findnotifynext);
4136 case TRANSACT2_MKDIR:
4137 START_PROFILE_NESTED(Trans2_mkdir);
4138 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4139 ¶ms, total_params, &data, total_data);
4140 END_PROFILE_NESTED(Trans2_mkdir);
4143 case TRANSACT2_GET_DFS_REFERRAL:
4144 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4145 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4146 ¶ms, total_params, &data, total_data);
4147 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4149 case TRANSACT2_IOCTL:
4150 START_PROFILE_NESTED(Trans2_ioctl);
4151 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4152 ¶ms, total_params, &data, total_data);
4153 END_PROFILE_NESTED(Trans2_ioctl);
4156 /* Error in request */
4157 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4160 END_PROFILE(SMBtrans2);
4161 srv_signing_trans_stop();
4162 return ERROR_DOS(ERRSRV,ERRerror);
4165 /* As we do not know how many data packets will need to be
4166 returned here the various call_trans2xxxx calls
4167 must send their own. Thus a call_trans2xxx routine only
4168 returns a value other than -1 when it wants to send
4172 srv_signing_trans_stop();
4176 END_PROFILE(SMBtrans2);
4177 return outsize; /* If a correct response was needed the
4178 call_trans2xxx calls have already sent
4179 it. If outsize != -1 then it is returning */
4183 srv_signing_trans_stop();
4186 END_PROFILE(SMBtrans2);
4187 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);